// ------------------------------------------------------------------------------------------------------------------- // // Simple ESP8266 CLOCK by TOMASZ MAJCHER (TRANSLINE GROUP POLSKA) // // e-mail : transline.majcher@gmail.com // // licence : DonationWare // // ------------------------------------------------------------------------------------------------------------------- // // // v0.3 (27.05.2021) - FULL BETA :-) // v0.2 (26.05.2021) - budowa klasy LCD // v0.1 (26.05.2021) - budowa projektu // // ------------------------------------------------------------------------------------------------------------------- // // // GND <---> GND // VCC <---> Vin // SDA <---> D2 (NodeMCU) GPIO 4 // SCL <---> D1 (NodeMCU) GPIO 5 // // ------------------------------------------------------------------------------------------------------------------- // #include "LiquidCrystal_I2C.h" // https://circuits4you.com/wp-content/uploads/2019/03/I2C-LCD-ESP8266-Library.zip #include // biblioteka Wi-Fi #include // NTP klient (czas) #include // UDP dla NTP (czas) #include // scheluder #include // dla ntp LiquidCrystal_I2C lcd(0x27,20,4); const char *ssid = "DIABLO"; // network wifi ssid const char *password = "xxxxxxxxxxx"; // network wifi password #define SERIAL true // ------------------------------------------------------------------------------------------------------------------- // // --- P R O T O T Y P Y --------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void Task0Callback(); // funkcja dla task_0 void Task1Callback(); // funkcja dla task_1 void Task2Callback(); // funkcja dla task_2 // ------------------------------------------------------------------------------------------------------------------- // // --- Z A D A N I A S C H E L U D E R ' A ------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // Task task_0( 3600000, TASK_FOREVER, &Task0Callback); // task_0 - co 1 godzinę Task task_1( 60000, TASK_FOREVER, &Task1Callback); // task_2 - co 1 minutę Task task_2( 1000, TASK_FOREVER, &Task2Callback); // task_3 - co 1 sekundę Scheduler runner; // ------------------------------------------------------------------------------------------------------------------- // // *** STRUKTURA CZAS *** // // ------------------------------------------------------------------------------------------------------------------- // struct ZEGAR { int Godzina = 0; int Minuta = 0; int Sekunda = 0; } czas; // ------------------------------------------------------------------------------------------------------------------- // // *** KLASA LCD *** by Tomasz Majcher (TLG) v1.00 Lite *** // // ------------------------------------------------------------------------------------------------------------------- // class LCD { private : // --- ZMIENNE PRYWATNE -------------------------------------------------------------------------------------- // byte LGc[8] = { B00111, B01111, B11111, B11111, B11111, B11111, B11111, B11111 }; // lewy górny ----- // byte LDc[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B01111, B00111 }; // lewy dolny ----- // byte PGc[8] = { B11100, B11110, B11111, B11111, B11111, B11111, B11111, B11111 }; // prawy górny ---- // byte PDc[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11110, B11100 }; // prawy dolny ---- // byte UDb[8] = { B11111, B11111, B11111, B11111, B11111, B00000, B00000, B00000 }; // górny 1/2 ------ // byte DDb[8] = { B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111 }; // dolny 1/2 ------ // byte blk[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; // blok pełny ----- // byte emp[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000 }; // blok pusty ----- // // --- ZMIENNE PRYWATNE -------------------------------------------------------------------------------------- // LiquidCrystal_I2C & wyswietlacz; // ---------------------------------------------------------------------------------------- // // --- METODY PRYWATNE -------------------------------------------------------------------- // // ---------------------------------------------------------------------------------------- // void Kropka(int x, int y); void Dwukropek(int x, int y); void Liczba0(int x, int y); void Liczba1(int x, int y); void Liczba2(int x, int y); void Liczba3(int x, int y); void Liczba4(int x, int y); void Liczba5(int x, int y); void Liczba6(int x, int y); void Liczba7(int x, int y); void Liczba8(int x, int y); void Liczba9(int x, int y); void WyswietlCyfre(int x, int y, int numer); // ---------------------------------------------------------------------------------------- // public : // ---------------------------------------------------------------------------------------- // // --- KONSTRUKTOR KLACY LCD -------------------------------------------------------------- // // ---------------------------------------------------------------------------------------- // LCD (LiquidCrystal_I2C &adres_lc) : wyswietlacz(adres_lc) { LcdRegister(); } // ---------------------------------------------------------------------------------------- // // --- METODY PUBLICZNE KLASY LCD -------------------------------------------------------- // // ---------------------------------------------------------------------------------------- // void WyswietlCzas(); // wyswietl zegar void LcdRegister(); // zarejestruj nowy zestaw znaków specjalnych }; // ------------------------------------------------------------------------------------------------------------------- // // *** METODY PRYWATNE *** ZAREJESTRUJ NOWY ZESTAW ZNAKÓW SPECJALNYCH DLA WYŚWIETLACZA 20x4 *** // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: LcdRegister() { wyswietlacz.createChar(0,LGc); // 0 -> lewy górny narożnik ------------ // wyswietlacz.createChar(1,LDc); // 1 -> lewy dolny narożnik ------------ // wyswietlacz.createChar(2,PGc); // 2 -> prawy górny narożnik ----------- // wyswietlacz.createChar(3,PDc); // 3 -> prawy dolny narożnik ----------- // wyswietlacz.createChar(4,UDb); // 4 -> górny pół-blok ----------------- // wyswietlacz.createChar(5,DDb); // 5 -> dolny pół-blok ----------------- // wyswietlacz.createChar(6,blk); // 6 -> pełny blok --------------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 0 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba0(int x, int y) { // wyswietlacz.setCursor(x,y); // ustaw kursor ------------------------ // wyswietlacz.write(0); // lewy górny narożnk ------------------ // wyswietlacz.write(4); // kropa górna ------------------------- // wyswietlacz.write(2); // prawy górny narożnik ---------------- // wyswietlacz.setCursor(x,y+1); // ustaw kursor ------------------------ // wyswietlacz.write(6); // pełny 5x8 --------------------------- // wyswietlacz.print(F(" ")); // pusty blok -------------------------- // wyswietlacz.write(6); // pełny 5x8 --------------------------- // wyswietlacz.setCursor(x,y+2); // ustaw kursor ------------------------ // wyswietlacz.write(1); // lewy dolny narożnik ----------------- // wyswietlacz.write(5); // kropa dolna ------------------------- // wyswietlacz.write(3); // prawy dolny narożnik ---------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 1 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba1(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(4); // górna kropa ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.setCursor(x,y+1); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.setCursor(x,y+2); // ustaw kursor ----------------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 2 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba2(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(5); // kropa dolna ------------------------ // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 3 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba3(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(3); // prawy dolny narożnik --------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 4 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba4(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.write(1); // lewy dolny narożnik ---------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 5 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba5(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.write(1); // lewy dolny narożnik ---------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(6); // pełny 5x8 -------------------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 6 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba6(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(0); // lewy górny narożnk ----------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.write(1); // lewy dolny narożnik ---------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(3); // prawy dolny narożnik --------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 7 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba7(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 8 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba8(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(0); // lewy górny narożnk ----------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.write(1); // lewy dolny narożnik ---------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(3); // prawy dolny narożnik --------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 9 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Liczba9(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.write(0); // lewy górny narożnk ----------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.write(2); // prawy górny narożnik --------------- // wyswietlacz.setCursor(x, y+1); // ustaw kursor ----------------------- // wyswietlacz.write(1); // lewy dolny narożnik ---------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(6); // pełny 5x8 -------------------------- // wyswietlacz.setCursor(x, y+2); // ustaw kursor ----------------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(5); // kropa dolna ------------------------ // wyswietlacz.write(3); // prawy dolny narożnik --------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- Duża liczba 9 ------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Dwukropek(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.setCursor(x,y+1); // ustaw kursor ----------------------- // wyswietlacz.write(4); // kropa górna ------------------------ // wyswietlacz.setCursor(x,y+2); // ustaw kursor ----------------------- // wyswietlacz.write(5); // kropa dolna ------------------------ // } // ------------------------------------------------------------------------------------------------------------------- // // --- KROPA --------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: Kropka(int x, int y) { wyswietlacz.setCursor(x,y); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.setCursor(x,y+1); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // wyswietlacz.setCursor(x,y+2); // ustaw kursor ----------------------- // wyswietlacz.print(F(" ")); // pusty blok ------------------------- // } // ------------------------------------------------------------------------------------------------------------------- // // --- WYSWIETL CYFRE ------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: WyswietlCyfre(int x, int y, int numer) { // --------------------------------------------------------------------------------------------------------- // // K O N T R O L A B Ł Ę D U // if(x > 17) x = 17; // jesli pozycja x większa niż 17, ustaw maksymalną ------- // if(y > 1) y = 1; // jesli pozycja y wieksza niz 1 , ustaw maksymalna ------- // // // --------------------------------------------------------------------------------------------------------- // switch (numer) { case 0: Liczba0(x,y); break; case 1: Liczba1(x,y); break; case 2: Liczba2(x,y); break; case 3: Liczba3(x,y); break; case 4: Liczba4(x,y); break; case 5: Liczba5(x,y); break; case 6: Liczba6(x,y); break; case 7: Liczba7(x,y); break; case 8: Liczba8(x,y); break; case 9: Liczba9(x,y); break; } } // ------------------------------------------------------------------------------------------------------------------- // // *** METODY PUBLICZNE *** WYSWIETL CZAS *** // // ------------------------------------------------------------------------------------------------------------------- // void LCD :: WyswietlCzas() { static bool F_sec = false; static int O_min = 0; // optymalizacja (no flickering) static int O_hrs = 0; // optymalizacja (no flickering) if (O_min != czas.Minuta) { WyswietlCyfre(0, 0, czas.Godzina / 10); WyswietlCyfre(4, 0, czas.Godzina % 10); WyswietlCyfre(10, 0, czas.Minuta / 10); WyswietlCyfre(14, 0, czas.Minuta % 10); O_min = czas.Minuta; } switch (F_sec) { case 0 : Dwukropek(8,0); F_sec = true; break; case 1 : Kropka (8,0); F_sec = false; break; default: break; } wyswietlacz.setCursor(18,2); // ustaw pozycję SEKUNDNIKA wyswietlacz.print(czas.Sekunda / 10); // wyswietl dziesiątki sekundnika wyswietlacz.print(czas.Sekunda % 10); // wyswietl jednosci sekundnika if (O_hrs != czas.Godzina) { wyswietlacz.setCursor(18,0); // ustaw pozycję AM/PM if (czas.Godzina < 12) wyswietlacz.print(F("AM")); else wyswietlacz.print(F("PM")); wyswietlacz.setCursor(3,3); wyswietlacz.print(F("code by : TLG")); O_hrs = czas.Godzina; } } // ------------------------------------------------------------------------------------------------------------------- // // *** KLASA LCD *** by Tomasz Majcher (TLG) v1.00 Lite *** // // ------------------------------------------------------------------------------------------------------------------- // // * * * K O N I E C K L A S Y L C D *** // // ------------------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // // --- O B I E K T Y ------------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------------------------------- // LCD myLCD(lcd); WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 3600); // ------------------------------------------------------------------------------------------------------------------- // // --- Task0Callback() ----------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void Task0Callback() { } // ------------------------------------------------------------------------------------------------------------------- // // --- Task1Callback() ----------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void Task1Callback() { #if SERIAL Serial.printf("\n[ESP] [TASK1] Czas : %d:%d:%d", czas.Godzina, czas.Minuta, czas.Sekunda); #endif } // ------------------------------------------------------------------------------------------------------------------- // // --- Task2Callback() ----------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void Task2Callback() { timeClient.update(); czas.Godzina = timeClient.getHours()+1; // zapisz godzinę z serwera czas.Minuta = timeClient.getMinutes(); // zapisz minutę z serwera czas.Sekunda = timeClient.getSeconds(); // zapisz sekundę z serwera myLCD.WyswietlCzas(); } // ------------------------------------------------------------------------------------------------------------------- // // --- S E T U P ----------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void setup() { #if SERIAL Serial.begin(57600); #endif lcd.init(); lcd.backlight(); myLCD.LcdRegister(); WiFi.begin(ssid, password); while ( WiFi.status() != WL_CONNECTED ) // czekaj na połączenie { // wait for connect #if SERIAL delay ( 200 ); Serial.print ( "." ); #endif } runner.init(); // inicjalizuj scheluder runner.addTask(task_0); // dodaj zadanie do scheluder task_0.enable(); // włącz zadanie do scheluder runner.addTask(task_1); // dodaj zadanie do scheluder task_1.enable(); // włącz zadanie do scheluder runner.addTask(task_2); // dodaj zadanie do scheluder task_2.enable(); // włącz zadanie do scheluder } // ------------------------------------------------------------------------------------------------------------------- // // --- L O O P ------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------- // void loop() { runner.execute(); }