Difference between revisions of "Grove 16x2 LCD Series"
(→Code) |
(→Affichage "Hello" @ Wire.h ✅) |
||
| (94 intermediate revisions by 4 users not shown) | |||
| Line 5: | Line 5: | ||
=== images === | === images === | ||
| − | ici on utilise le White on Blue<br> | + | ici on utilise le (White on Blue) V1.0<br> |
[[File:16x2 LCD White on Blue 01.jpg|400px]] [[File:16x2 LCD White on Blue 02.jpg|400px]] | [[File:16x2 LCD White on Blue 01.jpg|400px]] [[File:16x2 LCD White on Blue 02.jpg|400px]] | ||
| − | === liens === | + | === liens externes === |
| − | |||
| − | |||
| − | |||
| − | |||
[http://wiki.seeedstudio.com/Grove-16x2_LCD_Series http://wiki.seeedstudio.com/Grove-16x2_LCD_Series LCD] wiki Grove-16x2<br> | [http://wiki.seeedstudio.com/Grove-16x2_LCD_Series http://wiki.seeedstudio.com/Grove-16x2_LCD_Series LCD] wiki Grove-16x2<br> | ||
| Line 20: | Line 16: | ||
=== Connectique === | === Connectique === | ||
| − | interface : I2C-bus<br> | + | interface : <b>I2C</b>-bus<br> |
I2C Adresse: '''0X3E'''<br> | I2C Adresse: '''0X3E'''<br> | ||
| − | [https://wiki.myows.top/index.php?title=I2cScanner https://wiki.myows.top/index.php?title=I2cScanner] I2cScanner | + | [https://wiki.myows.top/index.php?title=I2cScanner https://wiki.myows.top/index.php?title=I2cScanner] <b>I2cScanner</b> |
| + | |||
| + | on va chercher l'adresse I2C, on regarde sur l'écran série | ||
Scanning... | Scanning... | ||
| − | I2C device found at address | + | I2C device found at address 0x3E ! |
| + | done<br> | ||
| + | c'est la même indiqué par le constructeur.<br> | ||
[[File:16x2 LCD White on Blue Connect 01.jpg|600px]] | [[File:16x2 LCD White on Blue Connect 01.jpg|600px]] | ||
| Line 41: | Line 41: | ||
[[HelloWorld Grove LCD| HelloWorld Grove LCD.ino]]<br> | [[HelloWorld Grove LCD| HelloWorld Grove LCD.ino]]<br> | ||
| − | === Code 2 === | + | === Code 2 @ rgb_lcd.h ✅ === |
| + | |||
| + | Affichage du texte "hello, world!" et dans la deuxième ligne affichage d'un compteur depuis zéro, +1 chaque seconde, 0,1,2, 3, ...51... | ||
| + | |||
| + | [https://github.come/Seed-Studio/Grove_LCD_RGB_Backlight https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight] <font = red>Librairie</font><br> | ||
| + | |||
| + | [[File:Seeeduino-nano-connect.png|150px]] | ||
| + | [[File:Pinout Grove Shield Arduino Nano.JPG|150px]] | ||
| + | [[File:16x2 LCD White on Blue 01.jpg|200px]] | ||
| + | |||
| + | Seeeduino-nano / (port <b>i2c</b>) ✅<br> | ||
| + | 16x2 LCD White on Blue<br> | ||
| + | |||
| + | [[File:Grove Base for XIAO 1.PNG|200px]] | ||
| + | [[File:XIAO-ESP32S3 1.PNG|125px]] | ||
| + | [[File:16x2 LCD White on Blue 01.jpg|200px]] | ||
| + | |||
| + | Grove Base for XIAO (Port <b>i2c</b>) ✅<br> | ||
| + | XIAO-ESP32S3 <br> | ||
| + | 16x2 LCD White on Blue | ||
| − | < | + | <PRE> |
#include <Wire.h> | #include <Wire.h> | ||
#include "rgb_lcd.h" | #include "rgb_lcd.h" | ||
| Line 80: | Line 99: | ||
</pre> | </pre> | ||
| − | === Code 3 === | + | un léger changement : pour <b>"hello, world!"</b> |
| + | |||
| + | https://github.come/Seed-Studio/Grove_LCD_RGB_Backlight Librairie | ||
| + | |||
| + | [[File:Grove Base for XIAO 1.PNG|200px]] | ||
| + | [[File:XIAO-ESP32S3 1.PNG|125px]] | ||
| + | [[File:16x2 LCD White on Blue 01.jpg|200px]] | ||
| + | |||
| + | Grove Base for XIAO (Port <b>i2c</b>) ✅<br> | ||
| + | XIAO-ESP32S3 <br> | ||
| + | 16x2 LCD White on Blue | ||
| + | |||
| + | <pre> | ||
| + | #include <Wire.h> | ||
| + | #include "rgb_lcd.h" | ||
| + | |||
| + | rgb_lcd lcd; | ||
| + | |||
| + | void setup() { | ||
| + | lcd.begin(16, 2); // 16 colonnes, 2 lignes | ||
| + | // lcd.setRGB(0, 128, 64); // Couleur de fond (vert doux) | ||
| + | lcd.setCursor(0, 0); | ||
| + | lcd.print("Hello ESP32S3!"); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print(millis() / 1000); | ||
| + | delay(1000); | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | <br> | ||
| + | ---- | ||
| + | |||
| + | === Code 3 @ LiquidCrystal_I2C.h ❌ === | ||
| + | |||
| + | ceci ne fonctionne pas ! ⊗ ❌ ⛔ avec : <br> | ||
| + | Seeeduino-nano + <br> | ||
| + | Port <b>I2c</b> + <br> | ||
| + | 16x2 LCD White on Blue<br> | ||
[https://github.com/johnrickman/LiquidCrystal_I2C https://github.com/johnrickman/LiquidCrystal_I2C] Librairy | [https://github.com/johnrickman/LiquidCrystal_I2C https://github.com/johnrickman/LiquidCrystal_I2C] Librairy | ||
| Line 117: | Line 176: | ||
} | } | ||
| + | </pre> | ||
| + | |||
| + | <br> | ||
| + | ---- | ||
| + | |||
| + | === Affichage "Hello" @ LiquidCrystal_I2C_ESP32 === | ||
| + | |||
| + | https://github.com/iakop/LiquidCrystal_I2C_ESP32 Librairie | ||
| + | |||
| + | <PRE> | ||
| + | #include <Wire.h> | ||
| + | #include <LiquidCrystal_I2C.h> | ||
| + | |||
| + | LiquidCrystal_I2C lcd(0x3E, 16, 2); // Adresse I2C 0x3E pour Grove LCD | ||
| + | |||
| + | void setup() { | ||
| + | Wire.begin(); // Initialise I2C | ||
| + | lcd.init(); // Initialise l'écran | ||
| + | lcd.backlight(); | ||
| + | lcd.setCursor(0, 0); | ||
| + | lcd.print("Hello ESP32!"); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | lcd.setCursor(0, 1); | ||
| + | lcd.print(millis() / 1000); | ||
| + | delay(1000); | ||
| + | } | ||
| + | </PRE> | ||
| + | |||
| + | <br> | ||
| + | ---- | ||
| + | |||
| + | === Affichage "Hello" @ Wire.h ✅ === | ||
| + | |||
| + | [[File:Grove Base for XIAO 1.PNG|200px]] | ||
| + | [[File:XIAO-ESP32S3 1.PNG|125px]] | ||
| + | [[File:16x2 LCD White on Blue 01.jpg|200px]] | ||
| + | |||
| + | Grove Base for XIAO (Port <b>i2c</b>) ✅<br> | ||
| + | XIAO-ESP32S3 <br> | ||
| + | 16x2 LCD White on Blue | ||
| + | |||
| + | LCD I2C Adresse 0X3E | ||
| + | RGB I2C Adresse 0X62 | ||
| + | |||
| + | <pre> | ||
| + | #include <Wire.h> | ||
| + | |||
| + | #define LCD_ADDR 0x3E // Adresse I2C du Grove LCD | ||
| + | #define COMMAND 0x00 // Mode commande | ||
| + | #define DATA 0x40 // Mode données | ||
| + | |||
| + | void sendCommand(uint8_t cmd) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(COMMAND); | ||
| + | Wire.write(cmd); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void sendData(uint8_t data) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(DATA); | ||
| + | Wire.write(data); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void initLCD() { | ||
| + | delay(50); // Attente après alimentation | ||
| + | sendCommand(0x38); // Fonction : 2 lignes, 8 bits | ||
| + | sendCommand(0x39); // Fonction étendue | ||
| + | sendCommand(0x14); // Oscillateur | ||
| + | sendCommand(0x70); // Contraste (ajuster si nécessaire) | ||
| + | sendCommand(0x56); // Puissance + icône + contraste | ||
| + | sendCommand(0x6C); // Activation du booster | ||
| + | delay(200); | ||
| + | sendCommand(0x38); // Retour mode normal | ||
| + | sendCommand(0x0C); // Affichage ON, curseur OFF | ||
| + | sendCommand(0x01); // Clear | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void printText(const char* text) { | ||
| + | while (*text) { | ||
| + | sendData(*text++); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void setup() { | ||
| + | Wire.begin(); | ||
| + | delay(100); | ||
| + | initLCD(); | ||
| + | printText("Hello ESP32!Wire"); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | // Rien ici pour l'instant | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | <br> | ||
| + | ---- | ||
| + | |||
| + | === "Compteur dynamique avec curseur" @ Wire.h ✅ === | ||
| + | |||
| + | [[File:Grove Base for XIAO 1.PNG|200px]] | ||
| + | [[File:XIAO-ESP32S3 1.PNG|125px]] | ||
| + | [[File:16x2 LCD White on Blue 01.jpg|200px]] | ||
| + | |||
| + | Grove Base for XIAO (Port <b>i2c</b>) ✅<br> | ||
| + | XIAO-ESP32S3 <br> | ||
| + | 16x2 LCD White on Blue | ||
| + | |||
| + | LCD I2C Adresse 0X3E<br> | ||
| + | RGB I2C Adresse 0X62 | ||
| + | |||
| + | |||
| + | <pre> | ||
| + | #include <Wire.h> | ||
| + | |||
| + | #define LCD_ADDR 0x3E | ||
| + | #define COMMAND 0x00 | ||
| + | #define DATA 0x40 | ||
| + | |||
| + | void sendCommand(uint8_t cmd) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(COMMAND); | ||
| + | Wire.write(cmd); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void sendData(uint8_t data) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(DATA); | ||
| + | Wire.write(data); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void setCursor(uint8_t col, uint8_t row) { | ||
| + | uint8_t pos = (row == 0) ? 0x80 + col : 0xC0 + col; | ||
| + | sendCommand(pos); | ||
| + | } | ||
| + | |||
| + | void clearLCD() { | ||
| + | sendCommand(0x01); // Clear display | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void initLCD() { | ||
| + | delay(50); | ||
| + | sendCommand(0x38); | ||
| + | sendCommand(0x39); | ||
| + | sendCommand(0x14); | ||
| + | sendCommand(0x70); // contraste | ||
| + | sendCommand(0x56); | ||
| + | sendCommand(0x6C); | ||
| + | delay(200); | ||
| + | sendCommand(0x38); | ||
| + | sendCommand(0x0C); // affichage ON | ||
| + | clearLCD(); | ||
| + | } | ||
| + | |||
| + | void printText(const char* text) { | ||
| + | while (*text) { | ||
| + | sendData(*text++); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void setup() { | ||
| + | Wire.begin(); | ||
| + | initLCD(); | ||
| + | setCursor(0, 0); | ||
| + | printText("Compteur:"); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | static int count = 0; | ||
| + | setCursor(0, 1); // ligne 2 | ||
| + | char buffer[16]; | ||
| + | snprintf(buffer, sizeof(buffer), "Valeur: %4d", count++); | ||
| + | printText(buffer); | ||
| + | delay(1000); | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | <br> | ||
| + | ---- | ||
| + | |||
| + | === Internet Clock 1 LCD "16x2 I2C" @ Wire.h ❌ === | ||
| + | |||
| + | Bibliothèques à installer : | ||
| + | |||
| + | https://github.com/me-no-dev/ESPAsyncWebServer 'ESPAsyncWebServer' | ||
| + | https://github.com/me-no-dev/AsyncTCP 'AsyncTCP' | ||
| + | La Bibliothèque 'Preferences' est ✅ déjà incluse dans le core ESP32 | ||
| + | |||
| + | ceci ne fonctionne pas ❎ à cause de 'Preferences' ❌ | ||
| + | |||
| + | SQUARED OK 🆗 & #x1F197;<br> | ||
| + | ANTENNA BARS 📶 & #x1F4F6;<br> | ||
| + | WIFI 🛜 & #128732;<br> | ||
| + | BRIGHTNESS SYMBOL 🔆 & #x1F506;<br> | ||
| + | CROSS MARK ❌ & #x274C;<br> | ||
| + | CROSS MARK ❎ & #x274E;<br> | ||
| + | WHITE HEAVY ✅ & #x2705;<br> | ||
| + | NO ENTRY ⛔ & #x26D4;<br> | ||
| + | CLOCK 🕒 & #x1F552;<br> | ||
| + | ROUND PUSHPIN 📍 & #x1F4CD;<br> | ||
| + | |||
| + | https://www.quackit.com/character_sets/emoji/emoji_v3.0/unicode_emoji_v3.0_characters_all.cfm | ||
| + | |||
| + | <pre> | ||
| + | #include <WiFi.h> | ||
| + | #include <Preferences.h> | ||
| + | #include <ESPAsyncWebServer.h> | ||
| + | #include <Wire.h> | ||
| + | #include <time.h> | ||
| + | |||
| + | // LCD I2C | ||
| + | #define LCD_ADDR 0x3E | ||
| + | #define COMMAND 0x00 | ||
| + | #define DATA 0x40 | ||
| + | |||
| + | Preferences prefs; | ||
| + | AsyncWebServer server(80); | ||
| + | |||
| + | // Variables config | ||
| + | String wifiSSID; | ||
| + | String wifiPASS; | ||
| + | String timezone; | ||
| + | |||
| + | const char* htmlPage = R"rawliteral( | ||
| + | <!DOCTYPE html> | ||
| + | <html> | ||
| + | <head><meta charset="UTF-8"><title>ESP32 Config</title></head> | ||
| + | <body> | ||
| + | <h1>Configuration ESP32</h1> | ||
| + | <form action="/save" method="GET"> | ||
| + | <label>WiFi SSID:</label><br> | ||
| + | <input type="text" name="ssid" value="%SSID%"><br> | ||
| + | <label>WiFi Password:</label><br> | ||
| + | <input type="password" name="pass" value="%PASS%"><br><br> | ||
| + | <label>Fuseau horaire:</label><br> | ||
| + | <select name="tz"> | ||
| + | <option value="CET-1CEST,M3.5.0/2,M10.5.0/3" %TZ1%>Europe/Zurich</option> | ||
| + | <option value="UTC0" %TZ2%>UTC</option> | ||
| + | </select><br><br> | ||
| + | <input type="submit" value="Enregistrer"> | ||
| + | </form> | ||
| + | </body> | ||
| + | </html> | ||
| + | )rawliteral"; | ||
| + | |||
| + | String processor(const String& var) { | ||
| + | if (var == "SSID") return wifiSSID; | ||
| + | if (var == "PASS") return wifiPASS; | ||
| + | if (var == "TZ1") return (timezone == "CET-1CEST,M3.5.0/2,M10.5.0/3") ? "selected" : ""; | ||
| + | if (var == "TZ2") return (timezone == "UTC0") ? "selected" : ""; | ||
| + | return String(); | ||
| + | } | ||
| + | |||
| + | // LCD functions | ||
| + | void sendCommand(uint8_t cmd) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(COMMAND); | ||
| + | Wire.write(cmd); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void sendData(uint8_t data) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(DATA); | ||
| + | Wire.write(data); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void setCursor(uint8_t col, uint8_t row) { | ||
| + | uint8_t pos = (row == 0) ? 0x80 + col : 0xC0 + col; | ||
| + | sendCommand(pos); | ||
| + | } | ||
| + | |||
| + | void clearLCD() { | ||
| + | sendCommand(0x01); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void initLCD() { | ||
| + | delay(50); | ||
| + | sendCommand(0x38); | ||
| + | sendCommand(0x39); | ||
| + | sendCommand(0x14); | ||
| + | sendCommand(0x70); | ||
| + | sendCommand(0x56); | ||
| + | sendCommand(0x6C); | ||
| + | delay(200); | ||
| + | sendCommand(0x38); | ||
| + | sendCommand(0x0C); | ||
| + | clearLCD(); | ||
| + | } | ||
| + | |||
| + | void printText(const char* text) { | ||
| + | while (*text) { | ||
| + | sendData(*text++); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | Wire.begin(); | ||
| + | initLCD(); | ||
| + | |||
| + | // Charger paramètres | ||
| + | prefs.begin("config", false); | ||
| + | wifiSSID = prefs.getString("ssid", "Your_wifi_SSID"); | ||
| + | wifiPASS = prefs.getString("pass", "Wifi_password"); | ||
| + | timezone = prefs.getString("tz", "CET-1CEST,M3.5.0/2,M10.5.0/3"); | ||
| + | |||
| + | // Connexion Wi-Fi | ||
| + | WiFi.begin(wifiSSID.c_str(), wifiPASS.c_str()); | ||
| + | if (WiFi.waitForConnectResult() != WL_CONNECTED) { | ||
| + | Serial.println("WiFi non trouvé, démarrage en AP..."); | ||
| + | WiFi.softAP("ESP32_Config", "12345678"); | ||
| + | } else { | ||
| + | Serial.println("Connecté au WiFi"); | ||
| + | } | ||
| + | |||
| + | // Serveur Web | ||
| + | server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ | ||
| + | request->send_P(200, "text/html", htmlPage, processor); | ||
| + | }); | ||
| + | |||
| + | server.on("/save", HTTP_GET, [](AsyncWebServerRequest *request){ | ||
| + | if (request->hasParam("ssid")) wifiSSID = request->getParam("ssid")->value(); | ||
| + | if (request->hasParam("pass")) wifiPASS = request->getParam("pass")->value(); | ||
| + | if (request->hasParam("tz")) timezone = request->getParam("tz")->value(); | ||
| + | |||
| + | prefs.putString("ssid", wifiSSID); | ||
| + | prefs.putString("pass", wifiPASS); | ||
| + | prefs.putString("tz", timezone); | ||
| + | |||
| + | request->send(200, "text/html", "<h1>Paramètres enregistrés. Redémarrage...</h1>"); | ||
| + | delay(2000); | ||
| + | ESP.restart(); | ||
| + | }); | ||
| + | |||
| + | server.begin(); | ||
| + | |||
| + | // Fuseau horaire | ||
| + | configTime(0, 0, "pool.ntp.org", "time.nist.gov"); | ||
| + | setenv("TZ", timezone.c_str(), 1); | ||
| + | tzset(); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | struct tm timeinfo; | ||
| + | if (!getLocalTime(&timeinfo)) { | ||
| + | Serial.println("Impossible d'obtenir l'heure"); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | char timeStr[17]; | ||
| + | snprintf(timeStr, sizeof(timeStr), "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); | ||
| + | |||
| + | char dateStr[17]; | ||
| + | snprintf(dateStr, sizeof(dateStr), "%02d/%02d/%04d", timeinfo.tm_mday, timeinfo.tm_mon + 1, timeinfo.tm_year + 1900); | ||
| + | |||
| + | setCursor(0, 0); | ||
| + | printText(timeStr); | ||
| + | setCursor(0, 1); | ||
| + | printText(dateStr); | ||
| + | |||
| + | delay(1000); | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | <br> | ||
| + | ---- | ||
| + | |||
| + | === Internet Clock 2 LCD "16x2 I2C" @ Wire.h 🛜 ✅ === | ||
| + | |||
| + | [[File:Grove Base for XIAO 1.PNG|200px]] | ||
| + | [[File:XIAO-ESP32S3 1.PNG|125px]] | ||
| + | [[File:16x2 LCD White on Blue 01.jpg|200px]] | ||
| + | |||
| + | Grove Base for XIAO (Port <b>i2c</b>) ✅<br> | ||
| + | XIAO-ESP32S3 📶<br> | ||
| + | 16x2 LCD White on Blue | ||
| + | |||
| + | LCD I2C Adresse 0X3E<br> | ||
| + | RGB I2C Adresse 0X62 | ||
| + | |||
| + | <pre> | ||
| + | #include <Wire.h> | ||
| + | #include <WiFi.h> | ||
| + | #include <time.h> | ||
| + | |||
| + | #define LCD_ADDR 0x3E | ||
| + | #define COMMAND 0x00 | ||
| + | #define DATA 0x40 | ||
| + | |||
| + | const char* ssid = "Mon_SSID"; | ||
| + | const char* password = "Mon_pass"; | ||
| + | |||
| + | // Fuseau horaire suisse avec heure d’été automatique | ||
| + | const char* timeZone = "CET-1CEST,M3.5.0,M10.5.0/3"; | ||
| + | const char* ntpServer = "pool.ntp.org"; | ||
| + | |||
| + | void sendCommand(uint8_t cmd) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(COMMAND); | ||
| + | Wire.write(cmd); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void sendData(uint8_t data) { | ||
| + | Wire.beginTransmission(LCD_ADDR); | ||
| + | Wire.write(DATA); | ||
| + | Wire.write(data); | ||
| + | Wire.endTransmission(); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void setCursor(uint8_t col, uint8_t row) { | ||
| + | uint8_t pos = (row == 0) ? 0x80 + col : 0xC0 + col; | ||
| + | sendCommand(pos); | ||
| + | } | ||
| + | |||
| + | void clearLCD() { | ||
| + | sendCommand(0x01); | ||
| + | delay(2); | ||
| + | } | ||
| + | |||
| + | void initLCD() { | ||
| + | delay(50); | ||
| + | sendCommand(0x38); | ||
| + | sendCommand(0x39); | ||
| + | sendCommand(0x14); | ||
| + | sendCommand(0x70); | ||
| + | sendCommand(0x56); | ||
| + | sendCommand(0x6C); | ||
| + | delay(200); | ||
| + | sendCommand(0x38); | ||
| + | sendCommand(0x0C); | ||
| + | clearLCD(); | ||
| + | } | ||
| + | |||
| + | void printText(const char* text) { | ||
| + | while (*text) { | ||
| + | sendData(*text++); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void clearLine(uint8_t row) { | ||
| + | setCursor(0, row); | ||
| + | for (int i = 0; i < 16; i++) { | ||
| + | sendData(' '); | ||
| + | } | ||
| + | setCursor(0, row); | ||
| + | } | ||
| + | |||
| + | void setup() { | ||
| + | Wire.begin(); | ||
| + | initLCD(); | ||
| + | |||
| + | WiFi.begin(ssid, password); | ||
| + | while (WiFi.status() != WL_CONNECTED) { | ||
| + | delay(1000); | ||
| + | } | ||
| + | |||
| + | configTzTime(timeZone, ntpServer); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | struct tm timeInfo; | ||
| + | if (!getLocalTime(&timeInfo)) { | ||
| + | clearLine(0); | ||
| + | printText("Erreur NTP"); | ||
| + | delay(1000); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | // Ligne 1 : heure au format 24h | ||
| + | char line1[17]; | ||
| + | snprintf(line1, sizeof(line1), "%02d:%02d:%02d", timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec); | ||
| + | |||
| + | // Ligne 2 : date au format JJ/MM/AAAA | ||
| + | char line2[17]; | ||
| + | snprintf(line2, sizeof(line2), "%02d/%02d/%04d", timeInfo.tm_mday, timeInfo.tm_mon + 1, timeInfo.tm_year + 1900); | ||
| + | |||
| + | // Centrage : calculer le décalage pour centrer chaque ligne | ||
| + | int len1 = strlen(line1); | ||
| + | int len2 = strlen(line2); | ||
| + | int pad1 = (16 - len1) / 2; | ||
| + | int pad2 = (16 - len2) / 2; | ||
| + | |||
| + | // Nettoyer et afficher ligne 1 | ||
| + | clearLine(0); | ||
| + | setCursor(pad1, 0); | ||
| + | printText(line1); | ||
| + | |||
| + | // Nettoyer et afficher ligne 2 | ||
| + | clearLine(1); | ||
| + | setCursor(pad2, 1); | ||
| + | printText(line2); | ||
| + | |||
| + | delay(1000); | ||
| + | } | ||
</pre> | </pre> | ||
Latest revision as of 18:16, 5 November 2025
Contents
- 1 Grove - 16x2 LCD Series
- 2 images
- 3 liens externes
- 4 Connectique
- 5 Librairie Seed-Studio
- 6 Code 2 @ rgb_lcd.h ✅
- 7 Code 3 @ LiquidCrystal_I2C.h ❌
- 8 Affichage "Hello" @ LiquidCrystal_I2C_ESP32
- 9 Affichage "Hello" @ Wire.h ✅
- 10 "Compteur dynamique avec curseur" @ Wire.h ✅
- 11 Internet Clock 1 LCD "16x2 I2C" @ Wire.h ❌
- 12 Internet Clock 2 LCD "16x2 I2C" @ Wire.h 🛜 ✅
Grove - 16x2 LCD Series[edit]
16 Characters * 2 Lines
Operating Voltage : 3.3V / 5V
images[edit]
ici on utilise le (White on Blue) V1.0
liens externes[edit]
http://wiki.seeedstudio.com/Grove-16x2_LCD_Series LCD wiki Grove-16x2
https://www.seeedstudio.com/Grove-16x2-LCD-White-on-Blue.html Shop Grove-16x2_LCD
Connectique[edit]
interface : I2C-bus
I2C Adresse: 0X3E
https://wiki.myows.top/index.php?title=I2cScanner I2cScanner
on va chercher l'adresse I2C, on regarde sur l'écran série
Scanning...
I2C device found at address 0x3E !
done
c'est la même indiqué par le constructeur.
Librairie Seed-Studio[edit]
install an Arduino library
https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight Librairie
https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight/archive/master.zip Librairie fichier Zip
Code 2 @ rgb_lcd.h ✅[edit]
Affichage du texte "hello, world!" et dans la deuxième ligne affichage d'un compteur depuis zéro, +1 chaque seconde, 0,1,2, 3, ...51...
https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight Librairie
Seeeduino-nano / (port i2c) ✅
16x2 LCD White on Blue
Grove Base for XIAO (Port i2c) ✅
XIAO-ESP32S3
16x2 LCD White on Blue
#include <Wire.h>
#include "rgb_lcd.h"
rgb_lcd lcd;
/*
const int colorR = 255;
const int colorG = 0;
const int colorB = 0;
*/
void setup()
{
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
//lcd.setRGB(colorR, colorG, colorB);
// Print a message to the LCD.
lcd.print("hello, world!");
delay(1000);
}
void loop()
{
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print(millis()/1000);
delay(100);
}
un léger changement : pour "hello, world!"
https://github.come/Seed-Studio/Grove_LCD_RGB_Backlight Librairie
Grove Base for XIAO (Port i2c) ✅
XIAO-ESP32S3
16x2 LCD White on Blue
#include <Wire.h>
#include "rgb_lcd.h"
rgb_lcd lcd;
void setup() {
lcd.begin(16, 2); // 16 colonnes, 2 lignes
// lcd.setRGB(0, 128, 64); // Couleur de fond (vert doux)
lcd.setCursor(0, 0);
lcd.print("Hello ESP32S3!");
}
void loop() {
lcd.setCursor(0, 1);
lcd.print(millis() / 1000);
delay(1000);
}
Code 3 @ LiquidCrystal_I2C.h ❌[edit]
ceci ne fonctionne pas ! ⊗ ❌ ⛔ avec :
Seeeduino-nano +
Port I2c +
16x2 LCD White on Blue
https://github.com/johnrickman/LiquidCrystal_I2C Librairy
https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c
#include <LiquidCrystal_I2C.h>
// I2C address of the LCD (check your specific LCD if it's different)
#define LCD_I2C_ADDRESS 0x01
// Define the LCD as an object
LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, 16, 2); // 16 columns, 2 rows
void setup() {
// Initialize the LCD
lcd.init();
// Turn on the backlight
// lcd.backlight();
// Optional: Set custom characters if needed
// lcd.createChar(0, custom_char_data);
// You can use the custom_char_data array from a tool like LCD-Character-Creator (https://maxpromer.github.io/LCD-Character-Creator/)
}
void loop() {
// Clear the LCD (optional)
lcd.clear();
// Set the cursor to the desired position (column, row)
// 0,0 is the top-left corner
lcd.setCursor(0, 0);
// Print text to the LCD
lcd.print("Hello, World!");
// Optionally, delay for a period
delay(2000);
}
Affichage "Hello" @ LiquidCrystal_I2C_ESP32[edit]
https://github.com/iakop/LiquidCrystal_I2C_ESP32 Librairie
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3E, 16, 2); // Adresse I2C 0x3E pour Grove LCD
void setup() {
Wire.begin(); // Initialise I2C
lcd.init(); // Initialise l'écran
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Hello ESP32!");
}
void loop() {
lcd.setCursor(0, 1);
lcd.print(millis() / 1000);
delay(1000);
}
Affichage "Hello" @ Wire.h ✅[edit]
Grove Base for XIAO (Port i2c) ✅
XIAO-ESP32S3
16x2 LCD White on Blue
LCD I2C Adresse 0X3E RGB I2C Adresse 0X62
#include <Wire.h>
#define LCD_ADDR 0x3E // Adresse I2C du Grove LCD
#define COMMAND 0x00 // Mode commande
#define DATA 0x40 // Mode données
void sendCommand(uint8_t cmd) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(COMMAND);
Wire.write(cmd);
Wire.endTransmission();
delay(2);
}
void sendData(uint8_t data) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(DATA);
Wire.write(data);
Wire.endTransmission();
delay(2);
}
void initLCD() {
delay(50); // Attente après alimentation
sendCommand(0x38); // Fonction : 2 lignes, 8 bits
sendCommand(0x39); // Fonction étendue
sendCommand(0x14); // Oscillateur
sendCommand(0x70); // Contraste (ajuster si nécessaire)
sendCommand(0x56); // Puissance + icône + contraste
sendCommand(0x6C); // Activation du booster
delay(200);
sendCommand(0x38); // Retour mode normal
sendCommand(0x0C); // Affichage ON, curseur OFF
sendCommand(0x01); // Clear
delay(2);
}
void printText(const char* text) {
while (*text) {
sendData(*text++);
}
}
void setup() {
Wire.begin();
delay(100);
initLCD();
printText("Hello ESP32!Wire");
}
void loop() {
// Rien ici pour l'instant
}
"Compteur dynamique avec curseur" @ Wire.h ✅[edit]
Grove Base for XIAO (Port i2c) ✅
XIAO-ESP32S3
16x2 LCD White on Blue
LCD I2C Adresse 0X3E
RGB I2C Adresse 0X62
#include <Wire.h>
#define LCD_ADDR 0x3E
#define COMMAND 0x00
#define DATA 0x40
void sendCommand(uint8_t cmd) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(COMMAND);
Wire.write(cmd);
Wire.endTransmission();
delay(2);
}
void sendData(uint8_t data) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(DATA);
Wire.write(data);
Wire.endTransmission();
delay(2);
}
void setCursor(uint8_t col, uint8_t row) {
uint8_t pos = (row == 0) ? 0x80 + col : 0xC0 + col;
sendCommand(pos);
}
void clearLCD() {
sendCommand(0x01); // Clear display
delay(2);
}
void initLCD() {
delay(50);
sendCommand(0x38);
sendCommand(0x39);
sendCommand(0x14);
sendCommand(0x70); // contraste
sendCommand(0x56);
sendCommand(0x6C);
delay(200);
sendCommand(0x38);
sendCommand(0x0C); // affichage ON
clearLCD();
}
void printText(const char* text) {
while (*text) {
sendData(*text++);
}
}
void setup() {
Wire.begin();
initLCD();
setCursor(0, 0);
printText("Compteur:");
}
void loop() {
static int count = 0;
setCursor(0, 1); // ligne 2
char buffer[16];
snprintf(buffer, sizeof(buffer), "Valeur: %4d", count++);
printText(buffer);
delay(1000);
}
Internet Clock 1 LCD "16x2 I2C" @ Wire.h ❌[edit]
Bibliothèques à installer :
https://github.com/me-no-dev/ESPAsyncWebServer 'ESPAsyncWebServer' https://github.com/me-no-dev/AsyncTCP 'AsyncTCP' La Bibliothèque 'Preferences' est ✅ déjà incluse dans le core ESP32
ceci ne fonctionne pas ❎ à cause de 'Preferences' ❌
SQUARED OK 🆗 & #x1F197;
ANTENNA BARS 📶 & #x1F4F6;
WIFI 🛜 & #128732;
BRIGHTNESS SYMBOL 🔆 & #x1F506;
CROSS MARK ❌ & #x274C;
CROSS MARK ❎ & #x274E;
WHITE HEAVY ✅ & #x2705;
NO ENTRY ⛔ & #x26D4;
CLOCK 🕒 & #x1F552;
ROUND PUSHPIN 📍 & #x1F4CD;
https://www.quackit.com/character_sets/emoji/emoji_v3.0/unicode_emoji_v3.0_characters_all.cfm
#include <WiFi.h>
#include <Preferences.h>
#include <ESPAsyncWebServer.h>
#include <Wire.h>
#include <time.h>
// LCD I2C
#define LCD_ADDR 0x3E
#define COMMAND 0x00
#define DATA 0x40
Preferences prefs;
AsyncWebServer server(80);
// Variables config
String wifiSSID;
String wifiPASS;
String timezone;
const char* htmlPage = R"rawliteral(
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>ESP32 Config</title></head>
<body>
<h1>Configuration ESP32</h1>
<form action="/save" method="GET">
<label>WiFi SSID:</label><br>
<input type="text" name="ssid" value="%SSID%"><br>
<label>WiFi Password:</label><br>
<input type="password" name="pass" value="%PASS%"><br><br>
<label>Fuseau horaire:</label><br>
<select name="tz">
<option value="CET-1CEST,M3.5.0/2,M10.5.0/3" %TZ1%>Europe/Zurich</option>
<option value="UTC0" %TZ2%>UTC</option>
</select><br><br>
<input type="submit" value="Enregistrer">
</form>
</body>
</html>
)rawliteral";
String processor(const String& var) {
if (var == "SSID") return wifiSSID;
if (var == "PASS") return wifiPASS;
if (var == "TZ1") return (timezone == "CET-1CEST,M3.5.0/2,M10.5.0/3") ? "selected" : "";
if (var == "TZ2") return (timezone == "UTC0") ? "selected" : "";
return String();
}
// LCD functions
void sendCommand(uint8_t cmd) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(COMMAND);
Wire.write(cmd);
Wire.endTransmission();
delay(2);
}
void sendData(uint8_t data) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(DATA);
Wire.write(data);
Wire.endTransmission();
delay(2);
}
void setCursor(uint8_t col, uint8_t row) {
uint8_t pos = (row == 0) ? 0x80 + col : 0xC0 + col;
sendCommand(pos);
}
void clearLCD() {
sendCommand(0x01);
delay(2);
}
void initLCD() {
delay(50);
sendCommand(0x38);
sendCommand(0x39);
sendCommand(0x14);
sendCommand(0x70);
sendCommand(0x56);
sendCommand(0x6C);
delay(200);
sendCommand(0x38);
sendCommand(0x0C);
clearLCD();
}
void printText(const char* text) {
while (*text) {
sendData(*text++);
}
}
void setup() {
Serial.begin(115200);
Wire.begin();
initLCD();
// Charger paramètres
prefs.begin("config", false);
wifiSSID = prefs.getString("ssid", "Your_wifi_SSID");
wifiPASS = prefs.getString("pass", "Wifi_password");
timezone = prefs.getString("tz", "CET-1CEST,M3.5.0/2,M10.5.0/3");
// Connexion Wi-Fi
WiFi.begin(wifiSSID.c_str(), wifiPASS.c_str());
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("WiFi non trouvé, démarrage en AP...");
WiFi.softAP("ESP32_Config", "12345678");
} else {
Serial.println("Connecté au WiFi");
}
// Serveur Web
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", htmlPage, processor);
});
server.on("/save", HTTP_GET, [](AsyncWebServerRequest *request){
if (request->hasParam("ssid")) wifiSSID = request->getParam("ssid")->value();
if (request->hasParam("pass")) wifiPASS = request->getParam("pass")->value();
if (request->hasParam("tz")) timezone = request->getParam("tz")->value();
prefs.putString("ssid", wifiSSID);
prefs.putString("pass", wifiPASS);
prefs.putString("tz", timezone);
request->send(200, "text/html", "<h1>Paramètres enregistrés. Redémarrage...</h1>");
delay(2000);
ESP.restart();
});
server.begin();
// Fuseau horaire
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
setenv("TZ", timezone.c_str(), 1);
tzset();
}
void loop() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Impossible d'obtenir l'heure");
return;
}
char timeStr[17];
snprintf(timeStr, sizeof(timeStr), "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
char dateStr[17];
snprintf(dateStr, sizeof(dateStr), "%02d/%02d/%04d", timeinfo.tm_mday, timeinfo.tm_mon + 1, timeinfo.tm_year + 1900);
setCursor(0, 0);
printText(timeStr);
setCursor(0, 1);
printText(dateStr);
delay(1000);
}
Internet Clock 2 LCD "16x2 I2C" @ Wire.h 🛜 ✅[edit]
Grove Base for XIAO (Port i2c) ✅
XIAO-ESP32S3 📶
16x2 LCD White on Blue
LCD I2C Adresse 0X3E
RGB I2C Adresse 0X62
#include <Wire.h>
#include <WiFi.h>
#include <time.h>
#define LCD_ADDR 0x3E
#define COMMAND 0x00
#define DATA 0x40
const char* ssid = "Mon_SSID";
const char* password = "Mon_pass";
// Fuseau horaire suisse avec heure d’été automatique
const char* timeZone = "CET-1CEST,M3.5.0,M10.5.0/3";
const char* ntpServer = "pool.ntp.org";
void sendCommand(uint8_t cmd) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(COMMAND);
Wire.write(cmd);
Wire.endTransmission();
delay(2);
}
void sendData(uint8_t data) {
Wire.beginTransmission(LCD_ADDR);
Wire.write(DATA);
Wire.write(data);
Wire.endTransmission();
delay(2);
}
void setCursor(uint8_t col, uint8_t row) {
uint8_t pos = (row == 0) ? 0x80 + col : 0xC0 + col;
sendCommand(pos);
}
void clearLCD() {
sendCommand(0x01);
delay(2);
}
void initLCD() {
delay(50);
sendCommand(0x38);
sendCommand(0x39);
sendCommand(0x14);
sendCommand(0x70);
sendCommand(0x56);
sendCommand(0x6C);
delay(200);
sendCommand(0x38);
sendCommand(0x0C);
clearLCD();
}
void printText(const char* text) {
while (*text) {
sendData(*text++);
}
}
void clearLine(uint8_t row) {
setCursor(0, row);
for (int i = 0; i < 16; i++) {
sendData(' ');
}
setCursor(0, row);
}
void setup() {
Wire.begin();
initLCD();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
}
configTzTime(timeZone, ntpServer);
}
void loop() {
struct tm timeInfo;
if (!getLocalTime(&timeInfo)) {
clearLine(0);
printText("Erreur NTP");
delay(1000);
return;
}
// Ligne 1 : heure au format 24h
char line1[17];
snprintf(line1, sizeof(line1), "%02d:%02d:%02d", timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
// Ligne 2 : date au format JJ/MM/AAAA
char line2[17];
snprintf(line2, sizeof(line2), "%02d/%02d/%04d", timeInfo.tm_mday, timeInfo.tm_mon + 1, timeInfo.tm_year + 1900);
// Centrage : calculer le décalage pour centrer chaque ligne
int len1 = strlen(line1);
int len2 = strlen(line2);
int pad1 = (16 - len1) / 2;
int pad2 = (16 - len2) / 2;
// Nettoyer et afficher ligne 1
clearLine(0);
setCursor(pad1, 0);
printText(line1);
// Nettoyer et afficher ligne 2
clearLine(1);
setCursor(pad2, 1);
printText(line2);
delay(1000);
}