Grove 16x2 LCD Series
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);
}