Laboratoire Robotique

Chargement...

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

© 2026 Robot. Tous droits réservés.

Made withby David