Difference between revisions of "Grove 16x2 LCD Series"

From
Jump to: navigation, search
(Code)
(Affichage "Hello" @ Wire.h ✅)
 
(114 intermediate revisions by 4 users not shown)
Line 4: Line 4:
  
 
=== images ===
 
=== images ===
 +
 +
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 ===
[https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight/archive/master.zip Librairie fichier Zip]https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight/archive/master.zip
 
  
[http://wiki.seeedstudio.com/Grove-16x2_LCD_Series/ wiki Grove-16x2_LCD]<br>
+
[http://wiki.seeedstudio.com/Grove-16x2_LCD_Series http://wiki.seeedstudio.com/Grove-16x2_LCD_Series LCD] wiki Grove-16x2<br>
[https://www.seeedstudio.com/Grove-16x2-LCD-White-on-Blue.html Shop Grove-16x2_LCD]
+
 
 +
[https://www.seeedstudio.com/Grove-16x2-LCD-White-on-Blue.html https://www.seeedstudio.com/Grove-16x2-LCD-White-on-Blue.html] Shop Grove-16x2_LCD
  
 
=== Connectique ===
 
=== Connectique ===
interface : I2C-bus<br>
+
interface : <b>I2C</b>-bus<br>
I2C Address: 0X3E<br>
+
I2C Adresse: '''0X3E'''<br>
[[File:16x2 LCD White on Blue Connect 01.jpg|400px]]
+
 
=== Code ===
+
[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...
 +
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]]
 +
 
 +
=== Librairie Seed-Studio ===
 
install an Arduino library<br>
 
install an Arduino library<br>
[[File:Add Library Zip.png|300px]]<br>
+
 
 +
[https://github.come/Seed-Studio/Grove_LCD_RGB_Backlight https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight] <font = red>Librairie</font><br>
 +
 
 +
[https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight/archive/master.zip https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight/archive/master.zip] Librairie fichier Zip<br>
 +
 
 +
[[File:Add Library Zip.png|400px]]<br>
  
 
[[HelloWorld Grove LCD| HelloWorld Grove LCD.ino]]<br>
 
[[HelloWorld Grove LCD| HelloWorld Grove LCD.ino]]<br>
 +
 +
=== Code 2 @ rgb_lcd.h &#9989; ===
 +
 +
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>) &#9989;<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>) &#9989;<br>
 +
XIAO-ESP32S3 <br>
 +
16x2 LCD White on Blue
 +
 +
<PRE>
 +
#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);
 +
}
 +
</pre>
 +
 +
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>) &#9989;<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 &#x274C; ===
 +
 +
ceci ne fonctionne pas ! &otimes; &#x274C; &#x26D4; 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://www.arduinolibraries.info/libraries/liquid-crystal-i2-c https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c]
 +
 +
<pre>
 +
 +
#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);
 +
}
 +
 +
</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 &#9989; ===
 +
 +
[[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>) &#9989;<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 &#9989; ===
 +
 +
[[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>) &#9989;<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 &#x274C; ===
 +
 +
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 &#10062; à cause de 'Preferences' &#x274C;
 +
 +
SQUARED OK &#x1F197; & #x1F197;<br>
 +
ANTENNA BARS &#x1F4F6; & #x1F4F6;<br>
 +
WIFI &#128732; & #128732;<br>
 +
BRIGHTNESS SYMBOL &#x1F506; & #x1F506;<br>
 +
CROSS MARK &#x274C; & #x274C;<br>
 +
CROSS MARK &#x274E; & #x274E;<br>
 +
WHITE HEAVY &#x2705; & #x2705;<br>
 +
NO ENTRY &#x26D4; & #x26D4;<br>
 +
CLOCK &#x1F552; & #x1F552;<br>
 +
ROUND PUSHPIN &#x1F4CD; & #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 &#128732; &#9989; ===
 +
 +
[[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>) &#9989;<br>
 +
XIAO-ESP32S3 &#x1F4F6;<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>

Latest revision as of 18:16, 5 November 2025

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

16x2 LCD White on Blue 01.jpg 16x2 LCD White on Blue 02.jpg

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.

16x2 LCD White on Blue Connect 01.jpg

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

Add Library Zip.png

HelloWorld Grove LCD.ino

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-connect.png Pinout Grove Shield Arduino Nano.JPG 16x2 LCD White on Blue 01.jpg

Seeeduino-nano / (port i2c) ✅
16x2 LCD White on Blue

Grove Base for XIAO 1.PNG XIAO-ESP32S3 1.PNG 16x2 LCD White on Blue 01.jpg

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 1.PNG XIAO-ESP32S3 1.PNG 16x2 LCD White on Blue 01.jpg

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 1.PNG XIAO-ESP32S3 1.PNG 16x2 LCD White on Blue 01.jpg

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 1.PNG XIAO-ESP32S3 1.PNG 16x2 LCD White on Blue 01.jpg

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 1.PNG XIAO-ESP32S3 1.PNG 16x2 LCD White on Blue 01.jpg

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);
}