#include <Wire.h>
#include <Encoder.h>
#include <Servo.h>
#include <U8glib.h>
#include <HX711.h>
#include <EEPROM.h>
U8GLIB_SSD1306_128X64 Oled(U8G_I2C_OPT_NONE);
Encoder encoder(9, 8);
Servo myservo;
const int buttonPin = 5;
bool test = true;
const int LOADCELL_DOUT_PIN = 7;
const int LOADCELL_SCK_PIN = 6;
HX711 scale;
float CALIBRATION_FACTOR;
const int EEPROM_ADDR = 0;
const int EEPROM_M = 4;
const int EEPROM_S = 8;
const int EEPROM_V = 12;
const char* mainItems[] = {
"Kalibracia",
"Plnenie",
"Vaha",
"Nastavenia",
};
const char* menuItems[] = {
"Maly pohar",
"Stredny pohar",
"Velky pohar",
"Menu"
};
float hmotnostM;
float hmotnostS;
float hmotnostV;
const int mainLength = sizeof(mainItems) / sizeof(mainItems[0]);
const int menuLength = sizeof(menuItems) / sizeof(menuItems[0]);
const int settingsLength = sizeof(menuItems) / sizeof(menuItems[0]);
int menuIndex = 0;
int menuIndex2 = 0;
int settings = 0;
int displayOffset = 0;
int displayOffset2 = 0;
const int maxVisibleItems = 3;
long lastEncoderPos = encoder.read() / 2;
const int threshold = 2;
bool inSubmenu = false;
bool inSubmenu2 = false;
bool inSubmenu3 = false;
bool inSubmenu4 = false;
bool zmena = true;
bool zmena2 = false;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
displayMain();
myservo.attach(3);
myservo.write(0);
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
EEPROM.get(EEPROM_ADDR, CALIBRATION_FACTOR);
if (isnan(CALIBRATION_FACTOR)) {
CALIBRATION_FACTOR = 403.95;
}
EEPROM.get(EEPROM_M, hmotnostM);
if (isnan(hmotnostM)) {
hmotnostM = 2000;
}
EEPROM.get(EEPROM_S, hmotnostS);
if (isnan(hmotnostS)) {
hmotnostS = 3500;
}
EEPROM.get(EEPROM_V, hmotnostV);
if (isnan(hmotnostV)) {
hmotnostV = 5000;
}
scale.set_scale(CALIBRATION_FACTOR);
scale.tare();
Serial.begin(9600);
}
void loop() {
long newPos = encoder.read() / 2;
unsigned long currentMillis = millis();
const int debounceDelay = 50;
if (abs(newPos - lastEncoderPos) >= threshold) {
if (!inSubmenu) {
if (newPos > lastEncoderPos) {
menuIndex++;
} else if (newPos < lastEncoderPos) {
menuIndex--;
}
if (menuIndex < 0) {
menuIndex = 0;
} else if (menuIndex >= mainLength) {
menuIndex = mainLength - 1;
}
if (menuIndex >= displayOffset + maxVisibleItems) {
displayOffset = menuIndex - maxVisibleItems + 1;
} else if (menuIndex < displayOffset) {
displayOffset = menuIndex;
}
displayMain();
} else {
if (newPos > lastEncoderPos) {
menuIndex2++;
} else if (newPos < lastEncoderPos) {
menuIndex2--;
}
if (menuIndex2 < 0) {
menuIndex2 = 0;
} else if (menuIndex2 >= menuLength) {
menuIndex2 = menuLength - 1;
}
if (menuIndex2 >= displayOffset2 + maxVisibleItems) {
displayOffset2 = menuIndex2 - maxVisibleItems + 1;
} else if (menuIndex2 < displayOffset2) {
displayOffset2 = menuIndex2;
}
displayMenu();
}
lastEncoderPos = newPos;
}
if (digitalRead(buttonPin) == LOW && menuIndex == 1 && !inSubmenu) {
inSubmenu = true;
displayMenu();
delay(200);
} else if (digitalRead(buttonPin) == LOW && menuIndex == 0 && !inSubmenu2) {
inSubmenu2 = true;
kalibracia();
delay(200);
} else if (digitalRead(buttonPin) == LOW && menuIndex == 2 && !inSubmenu3) {
inSubmenu3 = true;
vaha();
delay(200);
}
else if (digitalRead(buttonPin) == LOW && menuIndex == 3 && !inSubmenu4) {
inSubmenu4 = true;
nastavenia();
delay(200);
}
if (digitalRead(buttonPin) == LOW && inSubmenu) {
int i = scale.get_units();
if (digitalRead(buttonPin) == LOW && test == true && i < 20) {
test = false;
if (menuIndex2 != 3) {
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Polozte nadobu");
Oled.drawStr(2, 20, "na vahu a stlacte");
Oled.drawStr(2, 30, "tlacidlo.");
} while (Oled.nextPage());
delay(100);
while(digitalRead(buttonPin) == HIGH) {
}
scale.tare();
if (menuIndex2 == 0) {
plnenie(hmotnostM);
} else if (menuIndex2 == 1) {
plnenie(hmotnostS);
} else if (menuIndex2 == 2) {
plnenie(hmotnostV);
}
displayMenu();
}
if (menuIndex2 == 3) {
inSubmenu = false;
menuIndex2 = 0;
displayOffset2 = 0;
delay(100);
menuIndex = 1;
displayOffset2 = 0;
displayMain();
}
}
if (digitalRead(buttonPin) == HIGH && test == false) {
test = true;
}
if (digitalRead(buttonPin) == LOW && test == true && i > 20) {
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Odstrante nadobu");
Oled.drawStr(2, 20, "z vahy");
} while (Oled.nextPage());
delay(1000);
displayMenu();
}
}
}
void plnenie(float potrebnahmotnost) {
bool servoBezi = false;
bool servoBezi2 = false;
bool servoBezi3 = false;
bool hotovo = false;
bool cakanieNaOdstranenie = false;
bool cakanieNaNovuNadobu = false;
bool odstranene = false;
bool ukoncenie = false;
while (true) {
int aktualnahmotnost = scale.get_units();
if (!hotovo){
int percento = (aktualnahmotnost / potrebnahmotnost) * 100;
if (percento > 100) {
percento = 100;
}
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Plni sa:");
Oled.drawStr(50, 10, menuItems[menuIndex2]);
char buffer[20];
sprintf(buffer, "Naplnene na: %d%%", percento);
Oled.drawStr(0, 34, buffer);
} while (Oled.nextPage());
if (percento < 90 && !servoBezi) {
myservo.write(180);
delay(2000);
myservo.write(90);
servoBezi = true;
} else if (percento >= 90 && percento < 100 && !servoBezi2) {
myservo.write(180);
delay(1000);
myservo.write(90);
servoBezi2 = true;
} else if (percento == 100 && !servoBezi3) {
myservo.write(180);
delay(1000);
myservo.write(90);
servoBezi3 = true;
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Pockajte");
Oled.drawStr(2, 20, "3 sekundy");
Oled.drawStr(2, 30, "med odkvapkava");
} while (Oled.nextPage());
delay(3000);
hotovo = true;
cakanieNaOdstranenie = true;
}
while(hotovo) {
aktualnahmotnost = scale.get_units();
if (cakanieNaOdstranenie) {
if (aktualnahmotnost > 10) {
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Odstrante naplneny pohar");
} while (Oled.nextPage());
}
else {
cakanieNaOdstranenie = false;
cakanieNaNovuNadobu = true;
scale.tare();
}
}
else if (cakanieNaNovuNadobu) {
if (aktualnahmotnost < 10) {
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Polozte nadobu");
Oled.drawStr(2, 20, "na vahu alebo stlacte");
Oled.drawStr(2, 30, "tlacidlo pre navrat.");
} while (Oled.nextPage());
odstranene = true;
} else if (aktualnahmotnost > 10 && odstranene == true) {
delay(1000);
scale.tare();
hotovo = false;
cakanieNaNovuNadobu = false;
odstranene = false;
servoBezi = false;
servoBezi2 = false;
servoBezi3 = false;
}
}
if (digitalRead(buttonPin) == LOW) {
hotovo = false;
ukoncenie = true;
}
}
}
if(ukoncenie)
{
break;
}
delay(100);
if (digitalRead(buttonPin) == LOW) {
myservo.write(180);
delay(2000);
myservo.write(90);
displayMenu();
break;
}
}
}
void vaha() {
scale.tare();
while (true) {
int aktualnahmotnost = scale.get_units();
String x = String(aktualnahmotnost);
Serial.print("Aktualna vaha: ");
Serial.println(aktualnahmotnost);
if (aktualnahmotnost <= 0) {
aktualnahmotnost = 0;
}
Oled.firstPage();
do {
Oled.setFont(u8g_font_7x14);
Oled.drawStr(40, 10, "Vaha je:");
Oled.drawStr(55, 30, x.c_str());
Oled.drawStr(55, 50, "g");
} while (Oled.nextPage());
delay(100);
if (digitalRead(buttonPin) == LOW) {
inSubmenu3 = false;
displayMain();
break;
}
}
}
void kalibracia() {
int aktualnahmotnost;
scale.tare();
lastEncoderPos = encoder.read() / 2;
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Teraz polozte znamu");
Oled.drawStr(2, 20, "vahu");
Oled.drawStr(2, 40, "Pomocou enkoderu");
Oled.drawStr(2, 50, "nastavte kal. faktor");
Oled.drawStr(2, 60, "na znamu vahu.");
} while (Oled.nextPage());
delay(100);
while(digitalRead(buttonPin) == HIGH) {}
while (true) {
aktualnahmotnost = scale.get_units();
Oled.firstPage();
do {
Oled.setFont(u8g_font_7x14);
Oled.drawStr(2, 10, "Vaha je:");
long newPos = encoder.read() / 2;
if (abs(newPos - lastEncoderPos) >= 1) {
if (newPos > lastEncoderPos) {
CALIBRATION_FACTOR++;
} else if (newPos < lastEncoderPos) {
CALIBRATION_FACTOR--;
}
lastEncoderPos = newPos;
scale.set_scale(CALIBRATION_FACTOR);
}
Oled.drawStr(60, 10, String(aktualnahmotnost).c_str());
Oled.drawStr(2, 40, "Kalibracny faktor:");
Oled.drawStr(2, 55, String(CALIBRATION_FACTOR).c_str());
} while (Oled.nextPage());
delay(100);
if (digitalRead(buttonPin) == LOW) {
EEPROM.put(EEPROM_ADDR, CALIBRATION_FACTOR);
inSubmenu2 = false;
menuIndex2 = 0;
displayMain();
break;
}
}
}
void displayMain() {
Oled.firstPage();
do {
Oled.setFont(u8g_font_9x18);
int lineHeight = 12;
for (int i = 0; i < maxVisibleItems; i++) {
int itemIndex = i + displayOffset;
if (itemIndex >= mainLength) break;
int textWidth = Oled.getStrWidth(mainItems[itemIndex]);
int xOffset = (128 - textWidth) / 2;
int yPosition = (i + 1) * lineHeight;
if (itemIndex == menuIndex) {
Oled.setColorIndex(1);
Oled.drawRFrame(0, yPosition - lineHeight + 2, 128, lineHeight, 2);
Oled.setColorIndex(1);
} else {
Oled.setColorIndex(1);
}
Oled.drawStr(xOffset, yPosition, mainItems[itemIndex]);
}
if (mainLength > maxVisibleItems) {
int scrollBarHeight = 40;
int scrollBarTop = map(menuIndex, 0, mainLength - 1, 0, 64 - scrollBarHeight);
Oled.drawBox(120, scrollBarTop, 6, scrollBarHeight);
}
} while (Oled.nextPage());
}
void displayMenu() {
Oled.firstPage();
do {
Oled.setFont(u8g_font_9x18);
int lineHeight = 12;
Oled.drawStr(2, 10, "Vyber pohar:");
for (int i = 0; i < maxVisibleItems; i++) {
int itemIndex = i + displayOffset2;
if (itemIndex >= menuLength) break;
int textWidth = Oled.getStrWidth(menuItems[itemIndex]);
int xOffset = (128 - textWidth) / 2;
int yPosition = (i + 2) * lineHeight;
if (itemIndex == menuIndex2) {
Oled.setColorIndex(1);
Oled.drawRFrame(0, yPosition - lineHeight + 2, 128, lineHeight, 2);
Oled.setColorIndex(1);
} else {
Oled.setColorIndex(1);
}
Oled.drawStr(xOffset, yPosition, menuItems[itemIndex]);
}
if (menuLength > maxVisibleItems) {
int scrollBarHeight = 40; // Height of the scrollbar
int scrollBarTop = map(menuIndex2, 0, menuLength - 1, 0, 64 - scrollBarHeight);
Oled.drawBox(120, scrollBarTop, 6, scrollBarHeight); // Draw the scrollbar
}
} while (Oled.nextPage());
}
void nastavenia() {
int pv = 0;
lastEncoderPos = encoder.read() / 2;
delay(500);
while (true) {
Oled.firstPage();
do {
Oled.setFont(u8g_font_6x12);
Oled.drawStr(2, 10, "Nastavenia:");
long newPos = encoder.read() / 2;
if (abs(newPos - lastEncoderPos) >= 2) {
if (newPos > lastEncoderPos) {
pv = +25;
zmena2 = true;
} else if (newPos < lastEncoderPos) {
pv = -25;
zmena2 = true;
}
lastEncoderPos = newPos;
}
String M = String(hmotnostM);
String S = String(hmotnostS);
String V = String(hmotnostV);
if (digitalRead(buttonPin) == LOW && zmena == true) {
zmena = false;
settings++;
}
else if(digitalRead(buttonPin) == HIGH && zmena == false) {
zmena = true;
pv = 0;
}
Oled.drawStr(2, 30, menuItems[settings]);
if (settings == 0) {
Oled.drawStr(2, 50, M.c_str());
if(zmena2 == true)
{
hmotnostM += pv;
zmena2 = false;
}
}
else if (settings == 1) {
Oled.drawStr(2, 50, S.c_str());
if(zmena2 == true)
{
hmotnostS += pv;
zmena2 = false;
}
}
else if (settings == 2) {
Oled.drawStr(2, 50, V.c_str());
if(zmena2 == true)
{
hmotnostV += pv;
zmena2 = false;
}
}
else if (settings == 3) {
EEPROM.put(EEPROM_M, hmotnostM);
EEPROM.put(EEPROM_S, hmotnostS);
EEPROM.put(EEPROM_V, hmotnostV);
inSubmenu4 = false;
settings = 0;
menuIndex = 3;
displayOffset = 2;
displayMain();
return;
}
} while (Oled.nextPage());
}
}