Dessin OLED
Cette page permet de créer un dessin affiché sur un écran OLED relié à un ESP32. Renseignez l'identifiant de l'ESP32 ci-dessous afin de charger ou modifier le dernier dessin associé à cet appareil.
Branchements du projet (I2C)
Connectez les broches de votre écran OLED aux broches de votre ESP32 comme suit :
- VCC (OLED) → 3.3V (ESP32)
- GND (OLED) → GND (ESP32)
- SCL (OLED) → Broche D22 (ESP32)
- SDA (OLED) → Broche D21 (ESP32)
Code C++ (Arduino)
Téléversez le code suivant sur votre ESP32 à l'aide de l'IDE Arduino. N'oubliez pas d'installer les bibliothèques Adafruit_SSD1306, Adafruit_GFX et Arduino_JSON.
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// --- Configuration WiFi et API ---
const char* ssid = "NOM_DU_WIFI"; // Nom du réseau WiFi
const char* password = "MOT_DE_PASSE_DU_WIFI"; // Mot de passe du WiFi
const char* server_url = "https://b-robot.davram.mg/api/project/esp32/poll-drawing-oled"; // URL du serveur
const char* esp32_identifier = "david_the_goat"; // L'identifiant (que vous créez) de cet ESP32
// --- Configuration Écran OLED ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// --- Variables de contrôle ---
String currentDrawingId = "null"; // Devient l'ID numérique du dessin quand il existe
unsigned long lastCheckTime = 0;
const unsigned long checkInterval = 5000; // 5 secondes
uint8_t bitmapBuffer[1024];
// Fonction pour afficher les informations système s'il n'y a pas de dessin
void displayStatusText(String statusMessage) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// Header
display.setCursor(0, 0);
display.println("=== SYSTEM STATUS ===");
// Affichage de l'identifiant de l'appareil
display.setCursor(0, 16);
display.print("ESP32 ID: ");
display.println(esp32_identifier);
// Affichage de l'IP si connecté au WiFi
display.setCursor(0, 28);
if (WiFi.status() == WL_CONNECTED) {
display.print("IP: ");
display.println(WiFi.localIP());
} else {
display.println("IP: Non connecte");
}
// Ligne de séparation
display.setCursor(0, 40);
display.println("---------------------");
// Message de statut (Connexion, Pas de dessin, Erreur...)
display.setCursor(0, 52);
display.print("Etat: ");
display.println(statusMessage);
display.display();
}
// Convertisseur Hex vers Bytes
void hexStringToBytes(const char* hexString, uint8_t* outputBytes, size_t outputLen) {
for (size_t i = 0; i < outputLen; i++) {
char high = hexString[i * 2];
char low = hexString[i * 2 + 1];
uint8_t highByte = (high >= 'a') ? (high - 'a' + 10) : ((high >= 'A') ? (high - 'A' + 10) : (high - '0'));
uint8_t lowByte = (low >= 'a') ? (low - 'a' + 10) : ((low >= 'A') ? (low - 'A' + 10) : (low - '0'));
outputBytes[i] = (highByte << 4) | lowByte;
}
}
// Fonction de requête API principale
void checkAndUpdateDrawing() {
// Vérification de la connexion WiFi avant d'interroger l'API
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Erreur : WiFi deconnecte.");
currentDrawingId = "null"; // On reset l'ID pour forcer le rafraîchissement du texte
displayStatusText("WiFi Perdu !");
return;
}
HTTPClient http;
String url = String(server_url) + "?identifier=" + esp32_identifier + "&id=" + currentDrawingId;
Serial.print("Requete API : ");
Serial.println(url);
http.begin(url);
int httpResponseCode = http.GET();
if (httpResponseCode == 200) {
String payload = http.getString();
Serial.println("Reponse : " + payload);
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print("Erreur parsing JSON : ");
Serial.println(error.c_str());
if (currentDrawingId == "null") {
displayStatusText("Erreur JSON");
}
http.end();
return;
}
// Cas 1 : L'ID renvoyé par Flask est NULL (Le dessin n'existe pas en BDD)
if (doc["id"].isNull()) {
Serial.println("Aucun dessin pour cet ID.");
currentDrawingId = "null";
displayStatusText("Pas de dessin"); // Affiche l'écran d'infos utiles
}
else {
String newId = doc["id"].as<String>();
// Cas 2 : Un nouveau dessin est disponible (ID différent)
if (newId != currentDrawingId) {
Serial.println("Nouveau dessin detecte ! Applique a l'OLED.");
currentDrawingId = newId;
if (doc.containsKey("bitmap")) {
const char* bitmapHex = doc["bitmap"];
hexStringToBytes(bitmapHex, bitmapBuffer, 1024);
// On efface les textes d'infos et on dessine le bitmap complet
display.clearDisplay();
display.drawBitmap(0, 0, bitmapBuffer, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
display.display();
}
}
// Cas 3 : Le dessin est le même
else {
Serial.println("Le dessin n'a pas change.");
}
}
} else {
// Gestion des erreurs de connexion au serveur (Serveur Flask éteint, mauvaise IP, etc.)
Serial.print("Erreur HTTP : ");
Serial.println(httpResponseCode);
// Si on n'avait pas de dessin en cours, on affiche l'erreur sur l'écran
if (currentDrawingId == "null") {
displayStatusText("Err Server: " + String(httpResponseCode));
}
}
http.end();
}
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Désactive le détecteur de Brownout
Serial.begin(115200);
// Initialisation OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("Erreur OLED : Verifie le cablage."));
for(;;);
}
// Affichage initial pendant le démarrage
displayStatusText("Booting...");
// Connexion WiFi
WiFi.begin(ssid, password);
int retryCount = 0;
while (WiFi.status() != WL_CONNECTED && retryCount < 20) {
delay(500);
Serial.print(".");
displayStatusText("Connexion WiFi...");
retryCount++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi Connecte !");
displayStatusText("WiFi OK. Sync API...");
delay(500);
} else {
Serial.println("\nEchec de la connexion WiFi.");
displayStatusText("WiFi ECHOUE !");
delay(2000);
}
// Premier appel direct après l'initialisation
checkAndUpdateDrawing();
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - lastCheckTime >= checkInterval) {
lastCheckTime = currentMillis;
checkAndUpdateDrawing();
}
}