#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// --- LCD konfiguratsiyasi ---
LiquidCrystal_I2C lcd(0x27, 16, 2);
// --- Keypad konfiguratsiyasi ---
const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {7, 8, 9, 10};
byte colPins[COLS] = {11, 12, 13, A0};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// --- Rele pinlari ---
int pumpPins[5] = {2, 3, 4, 5, 6};
int buzzerPin = A1;
// --- Global o'zgaruvchilar ---
float targetWeight = 0; // ml yoki gramm
float liquidPercents[3] = {0, 0, 0}; // 3 nasos foizi
bool processRunning = false;
// Nasos tezligi (ml/s) - sozlashingiz mumkin
float pumpRate = 1.67; // 100ml/min ≈ 1.67ml/s
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.backlight();
lcd.print("Tizim yuklanmoqda");
for (int i = 0; i < 5; i++) pinMode(pumpPins[i], OUTPUT);
pinMode(buzzerPin, OUTPUT);
allOff();
delay(1000);
lcd.clear();
}
void loop() {
if (!processRunning) {
getUserInput();
}
int key = keypad.getKey();
if (key == 'A' && !processRunning) { // START
lcd.clear();
lcd.print("Jarayon boshlandi");
delay(800);
processRunning = true;
runPumps();
lcd.clear();
lcd.print("Tayyor!");
beep(3);
processRunning = false;
}
if (key == 'D') { // STOP
lcd.clear();
lcd.print("STOP: Jarayon");
stopAll();
beep(2);
processRunning = false;
delay(1000);
}
if (key == 'B' && !processRunning) { // QUYISH
lcd.clear();
lcd.print("Quyilmoqda...");
pourLiquid();
}
if (key == 'C' && !processRunning) { // CHIROQ
toggleLight();
}
}
// --- Asosiy jarayon (Progress bar + %) ---
void runPumps() {
for (int i = 0; i < 3; i++) {
float amount = targetWeight * (liquidPercents[i] / 100.0);
unsigned long runTime = (amount / pumpRate) * 1000; // ms ga o‘tkazish
digitalWrite(pumpPins[i], HIGH);
unsigned long startTime = millis();
while (millis() - startTime < runTime) {
float progress = ((float)(millis() - startTime) / runTime) * 10.0; // 10 blok
int percent = ((float)(millis() - startTime) / runTime) * 100.0;
lcd.setCursor(0, 0);
lcd.print("Nasos "); lcd.print(i+1);
drawProgressBar((int)progress, percent);
delay(100);
}
digitalWrite(pumpPins[i], LOW);
}
}
// --- Progress bar + % ko‘rsatish ---
void drawProgressBar(int blocks, int percent) {
lcd.setCursor(0,1);
for (int i=0; i<10; i++) {
if (i < blocks) lcd.print("#");
else lcd.print("-");
}
lcd.setCursor(11,1);
if (percent < 10) lcd.print(" ");
else if (percent < 100) lcd.print(" ");
lcd.print(percent);
lcd.print("%");
}
// --- Quyish ---
void pourLiquid() {
digitalWrite(pumpPins[3], HIGH);
delay(5000);
digitalWrite(pumpPins[3], LOW);
lcd.clear();
lcd.print("Quyildi!");
beep(1);
}
// --- Chiroq ---
void toggleLight() {
static bool lightOn = false;
lightOn = !lightOn;
digitalWrite(pumpPins[4], lightOn);
lcd.clear();
lcd.print(lightOn ? "Chiroq ON" : "Chiroq OFF");
}
// --- STOP ---
void stopAll() {
for (int i = 0; i < 5; i++) digitalWrite(pumpPins[i], LOW);
}
// --- Barcha o‘chirish ---
void allOff() {
for (int i = 0; i < 5; i++) digitalWrite(pumpPins[i], LOW);
}
// --- Signal ---
void beep(int times) {
for (int i=0; i<times; i++) {
digitalWrite(buzzerPin, HIGH);
delay(150);
digitalWrite(buzzerPin, LOW);
delay(150);
}
}
// --- Foydalanuvchi kiritishi ---
void getUserInput() {
do {
lcd.clear();
lcd.print("Miqdorni (ml):");
targetWeight = getNumberFromKeypad();
} while (targetWeight <= 0);
float sum = 0;
for (int i = 0; i < 3; i++) {
lcd.clear();
lcd.print("Nasos "); lcd.print(i + 1);
lcd.setCursor(0,1); lcd.print("foiz: ");
liquidPercents[i] = getNumberFromKeypad();
sum += liquidPercents[i];
}
// Tekshirish
if (sum != 100) {
lcd.clear();
lcd.print("Xato: Foiz 100%");
beep(2);
delay(1500);
getUserInput();
}
}
// --- Keypaddan raqam olish ---
float getNumberFromKeypad() {
String input = "";
char key;
while (true) {
key = keypad.getKey();
if (key) {
if (key == '#') break;
if (key == '*') { // Clear
input = "";
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
} else {
input += key;
lcd.setCursor(0,1);
lcd.print(input);
}
}
}
return input.toFloat();
}