Détecteur de gaz

📄 Description
Créer un détecteur de gaz (méthane, propane, butane) utilisant une carte ESP32-C3 avec un affichage OLED 0.42" et un capteur MQ-4.
| 💰 Coût estimation |
📊 Difficulté | ⚖️ Licence | ⏱️ Durée |
|---|---|---|---|
| ~ € | 🟠🟠🟠⚪⚪ Moyen | CC-BY | 2 heures |
Outils & Matériaux
| Matériaux | Outils |
|---|---|
| - ESP32-C3 avec affichage OLED intégré | - IDE |
| - Capteur MQ-4 (détection de méthane, propane, butane) | |
| - Bibliothèques : U8g2 (pour l’OLED), Arduino IDE |
Étapes clés
- Câblage : Connexion du MQ-4 et de l’OLED à l’ESP32.
- Programmation : Lecture des données du MQ-4, affichage sur l’OLED, et déclenchement d’une alerte en cas de détection.
- Calibration : Mesure de la résistance du capteur en air propre (R0) et calcul de la concentration en PPM.
- Test : Vérification du bon fonctionnement via le moniteur série et l’affichage OLED.
📌 Introduction
- Objectif du projet : Dans le cadre de l’OpenLab, au fil de nos digressions créatives, nous avons abouti à une idée aussi farfelue qu’amusante : concevoir un “Mesureur de Pet” — un projet qui, sous couvert d’humour, pourra être légitimé comme un véritable détecteur de gaz.
- Matériel nécessaire (liens Amazon, fiches techniques)
- ESP32 C3 Carte de développement avec Affichage OLED 0.42inch (amazon)
-
Schéma de principe

🔧 Matériel et câblage
-
Liste des composants
-
ESP32 C3 Carte de développement avec Affichage OLED 0.42inch (amazon) - ~ 8€
Data-sheet-CBAA0046-038_FR.pdf
Description du produit






-
Détecteur MQ-4 (amazon) - ~ 3€
-
-
Schéma de câblage (ESP32 ↔ MQ-4 ↔ OLED)
- connections: "gas1:VCC", "esp:5V.1", "red" "gas1:GND", "esp:GND.4", "black" "gas1:DOUT", "esp:2", "yellow" "gas1:AOUT", "esp:1", "cyan" "oled1:SDA", "esp:5", "green" "oled1:SCL", "esp:6", "blue" "oled1:VCC", "esp:5V.2", "red" "oled1:GND", "esp:GND.5", "black"

💻 Programmation - Test et calibration
- Installation des bibliothèques (U8g2, MQ-4)
- Code Arduino pour lire le MQ-4 et afficher sur l’OLED
- Exemple de calibration et calcul des PPM
Vérification du bon fonctionnement de la carte
Test d’upload et de retour dans le moniteur série
✅ Configuration complète pour ESP32-C3 sur Arduino IDE 2.3.6 (Ubuntu)
1. Vérifie que tu as bien installé les cartes ESP32
- Va dans Fichier → Préférences
- Dans URL de gestionnaire de cartes supplémentaires, ajoute
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - Puis va dans Outils → Type de carte → Gestionnaire de cartes
- Recherche ESP32
- Installe ou mets à jour esp32 by Espressif Systems (version ≥ 2.0.14 recommandée)
2. Sélectionne les bons paramètres
Dans Outils, choisis :
- Carte :
ESP32C3 Dev Module - Port :
/dev/ttyACM0 - Vitesse de téléversement :
115200ou921600 - Flash Mode :
QIO - Flash Size :
4MB - USB CDC On Boot :
Enabled✅ (important pour le port série)
3. Code de test série minimal
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("✅ Série OK !");
}
void loop() {
Serial.println("🌀 Boucle active...");
delay(1000);
}
- Téléverse ce code
- Ouvre le Moniteur Série (Ctrl+Maj+M)
- Régle le baudrate sur 115200
4. Si toujours rien : appuie sur RESET
Après le message :
Hard resetting via RTS pin...
➡️ Appuie manuellement sur le bouton RESET de la carte si besoin.
Tu devrais voir une ligne comme :
[12345.6789] cdc_acm 1-1:1.0: ttyACM0: USB ACM device

Test vérification câblage écran
#include <Wire.h>
TwoWire testBus(0); // Bus I2C personnalisé
void scanBus(uint8_t sda, uint8_t scl) {
Serial.print("Test SDA=");
Serial.print(sda);
Serial.print(" SCL=");
Serial.println(scl);
testBus.begin(sda, scl);
delay(100);
bool found = false;
for (uint8_t addr = 1; addr < 127; addr++) {
testBus.beginTransmission(addr);
if (testBus.endTransmission() == 0) {
Serial.print(" ✅ Adresse I2C trouvée : 0x");
Serial.println(addr, HEX);
found = true;
}
}
if (!found) {
Serial.println(" ❌ Aucun périphérique I2C détecté.");
}
testBus.end();
delay(500);
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("🔍 Scan I2C multi-broches...");
// Liste de paires SDA/SCL à tester
uint8_t sdaPins[] = {4, 5, 6, 7, 8, 9, 10};
uint8_t sclPins[] = {4, 5, 6, 7, 8, 9, 10};
for (uint8_t i = 0; i < sizeof(sdaPins); i++) {
for (uint8_t j = 0; j < sizeof(sclPins); j++) {
if (sdaPins[i] != sclPins[j]) {
scanBus(sdaPins[i], sclPins[j]);
}
}
}
Serial.println("✅ Scan terminé.");
}
void loop() {}
Résultat :
12:46:51.123 -> ❌ Aucun périphérique I2C détecté.
12:46:51.638 -> Test SDA=4 SCL=9
12:46:51.734 -> ❌ Aucun périphérique I2C détecté.
12:46:52.249 -> Test SDA=4 SCL=10
12:46:52.377 > ❌ Aucun périphérique I2C détecté.
12:46:52.862 -> Test SDA=5 SCL=4
12:46:52.991 -> ❌ Aucun périphérique I2C détecté.
12:46:53.474 -> Test SDA=5 SCL=6
12:46:53.571 -> ✅ Adresse I2C trouvée : 0x3C
Vérification écran + calibrage
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 6, /* data=*/ 5, /* reset=*/ U8X8_PIN_NONE);
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("✅ Série OK - Texte centré");
u8g2.begin();
u8g2.setContrast(255);
u8g2.clearBuffer();
const int xOffset = 28;
const int yOffset = 24;
// Dessin du cadre
u8g2.drawFrame(xOffset, yOffset, 72, 40);
// Police et texte centré
u8g2.setFont(u8g2_font_5x8_tr);
int textWidth = 9 * 5; // "OLED OK !" = 9 caractères × 5px
int textX = xOffset + (72 - textWidth) / 2;
int textY = yOffset + (40 + 8) / 2; // centré verticalement
u8g2.drawStr(textX, textY, "OLED OK !");
u8g2.sendBuffer();
}
void loop() {
Serial.println("🌀 Boucle active...");
delay(1000);
}

📌 Fiche technique : ESP32-C3 HW675 + OLED 0.42"
- Résolution réelle : 72×40 pixels
- Broches I2C confirmées : SDA = GPIO5, SCL = GPIO6
- Adresse I2C :
0x3C - Orientation correcte : U8G2_R0 (USB en bas = texte à l’endroit)
- Décalage visuel : xOffset = 28, yOffset = 24
- Texte centré :
"OLED OK !"avec policeu8g2_font_5x8_tr
🧪 Le sketch utilisé affiche un cadre complet et centre le texte dans la zone visible. Parfait pour valider l’écran avant d’ajouter des pictos ou des capteurs.
🧠 Guide de test OLED – ESP32-C3 HW675
🎯 Objectif
Valider l’affichage d’un écran OLED 0.42" soudé sur la carte HW675, en corrigeant les broches, l’orientation et la zone d’affichage pour un rendu centré et lisible.
🧰 Matériel
- Carte ESP32-C3 HW675
- Écran OLED 0.42" SSD1306 (soudé)
- Câble USB-C
- Arduino IDE avec bibliothèque U8g2 installée
🔌 Connexions I2C confirmées
| Fonction | GPIO |
|---|---|
| SDA | 5 |
| SCL | 6 |
| Adresse | 0x3C |
🧪 Sketch de test OLED centré
cpp
`#include
void setup() { Serial.begin(115200); delay(1000); Serial.println("✅ Série OK - Texte centré");
u8g2.begin(); u8g2.setContrast(255); u8g2.clearBuffer();
const int xOffset = 28; const int yOffset = 24;
u8g2.drawFrame(xOffset, yOffset, 72, 40); // cadre visible
u8g2.setFont(u8g2_font_5x8_tr); int textWidth = 9 * 5; // "OLED OK !" = 9 caractères × 5px int textX = xOffset + (72 - textWidth) / 2; int textY = yOffset + (40 + 8) / 2;
u8g2.drawStr(textX, textY, "OLED OK !"); u8g2.sendBuffer(); }
void loop() { Serial.println("🌀 Boucle active..."); delay(1000); }`
🧭 Orientation confirmée
- Tenir la carte USB en bas
- Utiliser
U8G2_R0pour un affichage à l’endroit - Décalage horizontal :
xOffset = 28 - Décalage vertical :
yOffset = 24
✅ Résultat attendu
- Moniteur série : “✅ Série OK - Texte centré”
- Écran OLED : cadre complet 72×40 pixels avec texte “OLED OK !” centré
📎 Ressources visuelles
- Fiche visuelle disponible ci-dessus (image)
- Peut être intégrée dans Notion, Canva, Genially ou imprimée
Ajout du capteur MQ4
🔌 Câblage du capteur MQ-4 vers ESP32-C3 HW675
| Broche MQ-4 | Fonction | Connexion ESP32-C3 HW675 |
|---|---|---|
| VCC | Alimentation | 3.3V ou 5V (si disponible) |
| GND | Masse | GND |
| AOUT | Sortie analogique | GPIO1 ou autre broche ADC |
| DOUT | Seuil numérique | (optionnel) GPIO2 ou autre digital |
🔎 Recommandation : utilise AOUT pour une lecture analogique plus précise du taux de méthane (CH₄). Le MQ-4 est un capteur à oxyde métallique (SnO₂) dont la résistance varie selon la concentration de gaz.
⚙️ Exemple de lecture analogique dans Arduino
const int mq4Pin = 1; // GPIO1 = broche ADC
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("MQ-4 prêt !");
}
void loop() {
int valeur = analogRead(mq4Pin);
Serial.print("Lecture MQ-4 : ");
Serial.println(valeur);
delay(1000);
}
✅ Sketch MQ-4 + OLED avec 5 niveaux d’alerte
#include <U8g2lib.h>const int mq4Pin = 1; // GPIO1 = entrée analogique
// OLED calibré : orientation normale, décalage visuel
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 6, 5, U8X8_PIN_NONE);
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("MQ-4 + OLED avec 5 niveaux ✅");
u8g2.begin();
u8g2.setContrast(255);
}
void loop() {
int valeur = analogRead(mq4Pin); // lecture brute (0–4095)
Serial.print("MQ-4 : ");
Serial.println(valeur);
// Message d’état selon seuils
const char* etat;
if (valeur < 300) {
etat = "Tres faible";
} else if (valeur < 700) {
etat = "Faible";
} else if (valeur < 1000) {
etat = "Normal";
} else if (valeur < 2000) {
etat = "Attention";
} else {
etat = "Mortel";
}
// Conversion en texte
char ligne1[16];
snprintf(ligne1, sizeof(ligne1), "MQ4: %d", valeur);
// Affichage OLED calibré
u8g2.clearBuffer();
const int xOffset = 28;
const int yOffset = 24;
u8g2.drawFrame(xOffset, yOffset, 72, 40); // cadre visible
u8g2.setFont(u8g2_font_5x8_tr);
// Ligne 1 : valeur
int textWidth1 = strlen(ligne1) * 5;
int textX1 = xOffset + (72 - textWidth1) / 2;
int textY1 = yOffset + 14;
// Ligne 2 : état
int textWidth2 = strlen(etat) * 5;
int textX2 = xOffset + (72 - textWidth2) / 2;
int textY2 = textY1 + 12;
u8g2.drawStr(textX1, textY1, ligne1);
u8g2.drawStr(textX2, textY2, etat);
u8g2.sendBuffer();
delay(1000); // mise à jour toutes les secondes
}
🧪 Résultat attendu
| Valeur MQ-4 | Message affiché |
|---|---|
| 150 | Très faible |
| 450 | Faible |
| 850 | Normal |
| 1450 | Attention |
| 2300 | Mortel |
Code final commenté
#include <U8g2lib.h> // Bibliothèque U8g2 pour gérer l’écran OLED
// Déclaration de la broche analogique utilisée pour le capteur MQ-4
const int mq4Pin = 1; // GPIO1 = entrée analogique sur ESP32-C3
// Initialisation de l’écran OLED avec les bons paramètres
// - Type d’écran : SSD1306 128x64
// - Mode logiciel I2C
// - Orientation : U8G2_R0 (texte à l’endroit quand USB en bas)
// - Broches I2C : SCL = GPIO6, SDA = GPIO5
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 6, 5, U8X8_PIN_NONE);
void setup() {
Serial.begin(115200); // Initialisation du port série pour affichage dans le moniteur
delay(1000); // Petite pause pour stabiliser
Serial.println("MQ-4 + OLED avec 5 niveaux ✅");
u8g2.begin(); // Démarrage de l’écran OLED
u8g2.setContrast(255); // Contraste maximal pour une bonne lisibilité
}
void loop() {
// Lecture de la valeur analogique brute du capteur MQ-4 (entre 0 et 4095)
int valeur = analogRead(mq4Pin);
Serial.print("MQ-4 : ");
Serial.println(valeur);
// Détermination du message d’alerte selon la valeur lue
const char* etat;
if (valeur < 300) {
etat = "Tres faible"; // Air ambiant, pas de gaz détecté
} else if (valeur < 700) {
etat = "Faible"; // Présence résiduelle possible
} else if (valeur < 1000) {
etat = "Normal"; // Niveau tolérable
} else if (valeur < 2000) {
etat = "Attention"; // Concentration significative
} else {
etat = "Mortel"; // Risque élevé, danger potentiel
}
// Conversion de la valeur en texte affichable
char ligne1[16];
snprintf(ligne1, sizeof(ligne1), "MQ4: %d", valeur);
// Nettoyage du tampon d’affichage
u8g2.clearBuffer();
// Décalage visuel confirmé pour la zone 72×40 pixels
const int xOffset = 28;
const int yOffset = 24;
// Dessin du cadre visible
u8g2.drawFrame(xOffset, yOffset, 72, 40);
// Choix de la police
u8g2.setFont(u8g2_font_5x8_tr);
// Calcul de la position horizontale pour centrer la ligne 1
int textWidth1 = strlen(ligne1) * 5;
int textX1 = xOffset + (72 - textWidth1) / 2;
int textY1 = yOffset + 14; // Ligne du haut
// Calcul de la position pour la ligne 2 (message d’alerte)
int textWidth2 = strlen(etat) * 5;
int textX2 = xOffset + (72 - textWidth2) / 2;
int textY2 = textY1 + 12; // Ligne du bas
// Affichage des deux lignes
u8g2.drawStr(textX1, textY1, ligne1);
u8g2.drawStr(textX2, textY2, etat);
// Envoi du tampon à l’écran
u8g2.sendBuffer();
delay(1000); // Mise à jour toutes les secondes
}
Code corrigé avec barre de niveau
#include <U8g2lib.h>
// 🧪 MQ-4 sur GPIO2
const int mq4Pin = 2;
// 🖥️ OLED SSD1306 (I2C logiciel : SCL = GPIO6, SDA = GPIO5)
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 6, 5, U8X8_PIN_NONE);
// ⏱️ Alternance d’affichage
unsigned long lastSwitch = 0;
const unsigned long switchInterval = 5000;
bool afficherTexte = true;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("MQ-4 + OLED + Affichage alterné ✅");
u8g2.begin();
u8g2.setContrast(255);
}
void drawBatteryBar(int valeur) {
const int xOffset = 28;
const int yOffset = 24;
int largeur = 72;
int hauteur = 40;
// Cadre
u8g2.drawFrame(xOffset, yOffset, largeur, hauteur);
// Barre horizontale centrée
int barWidth = map(valeur, 0, 4095, 0, largeur - 4);
int barHeight = 10;
int barX = xOffset + 2;
int barY = yOffset + (hauteur - barHeight) / 2;
u8g2.drawBox(barX, barY, barWidth, barHeight);
}
void loop() {
int valeur = analogRead(mq4Pin);
Serial.print("MQ-4 : ");
Serial.println(valeur);
const char* etat;
if (valeur < 300) {
etat = "Tres faible";
} else if (valeur < 700) {
etat = "Faible";
} else if (valeur < 1600) { // ✅ seuil corrigé : 1500 = "Normal"
etat = "Normal";
} else if (valeur < 2500) {
etat = "Attention";
} else {
etat = "Mortel";
}
// Alternance d’affichage toutes les 5 secondes
if (millis() - lastSwitch > switchInterval) {
afficherTexte = !afficherTexte;
lastSwitch = millis();
}
u8g2.clearBuffer();
const int xOffset = 28;
const int yOffset = 24;
u8g2.drawFrame(xOffset, yOffset, 72, 40);
u8g2.setFont(u8g2_font_5x8_tr);
if (afficherTexte) {
// Texte centré dans le cadre
char ligne1[16];
snprintf(ligne1, sizeof(ligne1), "MQ4: %d", valeur);
int textWidth1 = strlen(ligne1) * 5;
int textX1 = xOffset + (72 - textWidth1) / 2;
int textY1 = yOffset + 14;
int textWidth2 = strlen(etat) * 5;
int textX2 = xOffset + (72 - textWidth2) / 2;
int textY2 = textY1 + 12;
u8g2.drawStr(textX1, textY1, ligne1);
u8g2.drawStr(textX2, textY2, etat);
} else {
drawBatteryBar(valeur);
}
u8g2.sendBuffer();
delay(1000);
}
Code commenté avec 3 écrans d’affichage en boucle
#include <U8g2lib.h>
// 📚 Bibliothèque U8g2 pour gérer l’écran OLED SSD1306 via I2C logiciel
const int mq4Pin = 2;
// 🧪 MQ-4 branché sur GPIO2 (entrée analogique)
// 🖥️ Déclaration de l’écran OLED SSD1306 (128x64 pixels)
// Utilisation d’I2C logiciel : SCL = GPIO6, SDA = GPIO5
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 6, 5, U8X8_PIN_NONE);
unsigned long lastSwitch = 0; // ⏱️ Dernier changement d’écran
const unsigned long switchInterval = 5000; // ⏱️ Intervalle entre écrans (5s)
int modeAffichage = 0; // 0 = valeur+texte, 1 = barre, 2 = icône ASCII
bool startupDone = false; // ⚡ Pour afficher l’écran d’accueil une seule fois
void setup() {
Serial.begin(115200);
delay(1000);
u8g2.begin();
u8g2.setContrast(255); // Luminosité maximale
// === Écran d’accueil ===
const int xOffset = 28; // Position X du cadre
const int yOffset = 24; // Position Y du cadre
const int largeur = 72; // Largeur du cadre
const int hauteur = 40; // Hauteur du cadre
u8g2.clearBuffer();
u8g2.drawFrame(xOffset, yOffset, largeur, hauteur); // Dessin du cadre
u8g2.setFont(u8g2_font_6x12_tr); // Police compacte pour 3 lignes
// Texte à afficher
const char* l1 = "Gaz";
const char* l2 = "Detector";
const char* l3 = "v1.0";
// 📐 Calcul typographique pour centrer verticalement les 3 lignes
int ascent = u8g2.getAscent();
int descent = u8g2.getDescent(); // négatif
int fontH = ascent - descent;
int lineSpacing = 2; // espace entre lignes
int blockH = 3 * fontH + 2 * lineSpacing; // hauteur totale du bloc texte
// Baseline de chaque ligne
int baseY1 = yOffset + (hauteur - blockH) / 2 + ascent;
int baseY2 = baseY1 + fontH + lineSpacing;
int baseY3 = baseY2 + fontH + lineSpacing;
// Centrage horizontal par ligne
int w1 = u8g2.getStrWidth(l1);
int w2 = u8g2.getStrWidth(l2);
int w3 = u8g2.getStrWidth(l3);
int x1 = xOffset + (largeur - w1) / 2;
int x2 = xOffset + (largeur - w2) / 2;
int x3 = xOffset + (largeur - w3) / 2;
// ✍️ Dessin des 3 lignes
u8g2.drawStr(x1, baseY1, l1);
u8g2.drawStr(x2, baseY2, l2);
u8g2.drawStr(x3, baseY3, l3);
u8g2.sendBuffer();
delay(3000); // Affichage pendant 3 secondes
startupDone = true; // ⚡ Ensuite on passe au cycle normal
}
// 🔲 Fonction pour dessiner une barre horizontale (écran 2)
void drawBatteryBar(int valeur) {
const int xOffset = 28;
const int yOffset = 24;
int largeur = 72;
int hauteur = 40;
u8g2.drawFrame(xOffset, yOffset, largeur, hauteur);
int barWidth = map(valeur, 0, 4095, 0, largeur - 4);
int barHeight = 10;
int barX = xOffset + 2;
int barY = yOffset + (hauteur - barHeight) / 2;
u8g2.drawBox(barX, barY, barWidth, barHeight);
}
void loop() {
if (!startupDone) return; // ⏸️ Ne rien faire tant que l’écran d’accueil n’est pas passé
// 📥 Lecture du capteur MQ-4
int valeur = analogRead(mq4Pin);
// Détermination du niveau
const char* etat;
int niveau;
if (valeur < 500) { etat = "Tres faible"; niveau = 1; }
else if (valeur < 2000) { etat = "Faible"; niveau = 2; }
else if (valeur < 5000) { etat = "Moyen"; niveau = 3; }
else if (valeur < 8000) { etat = "Eleve"; niveau = 4; }
else { etat = "Critique"; niveau = 5; }
// ⏱️ Alternance d’écran toutes les 5 secondes
if (millis() - lastSwitch > switchInterval) {
modeAffichage = (modeAffichage + 1) % 3;
lastSwitch = millis();
}
u8g2.clearBuffer();
if (modeAffichage == 0) {
// === Écran 1 : valeur MQ4 + niveau ===
const int xOffset = 28;
const int yOffset = 24;
int largeur = 72;
int hauteur = 40;
u8g2.drawFrame(xOffset, yOffset, largeur, hauteur);
u8g2.setFont(u8g2_font_7x14_tr);
// Ligne 1 : valeur brute
char ligne1[20];
snprintf(ligne1, sizeof(ligne1), "MQ4:%d", valeur);
int w1 = u8g2.getStrWidth(ligne1);
int x1 = xOffset + (largeur - w1) / 2;
int y1 = yOffset + 16;
// Ligne 2 : texte du niveau
int w2 = u8g2.getStrWidth(etat);
int x2 = xOffset + (largeur - w2) / 2;
int y2 = yOffset + 32;
u8g2.drawStr(x1, y1, ligne1);
u8g2.drawStr(x2, y2, etat);
}
else if (modeAffichage == 1) {
// === Écran 2 : barre horizontale ===
drawBatteryBar(valeur);
}
else {
// === Écran 3 : icône ASCII centrée ===
const int xOffset = 28;
const int yOffset = 24;
int largeur = 72;
int hauteur = 40;
u8g2.drawFrame(xOffset, yOffset, largeur, hauteur);
u8g2.setFont(u8g2_font_10x20_tr);
// Choix du symbole ASCII selon le niveau
const char* symbole;
switch (niveau) {
case 1: symbole = "OK"; break;
case 2: symbole = ":)"; break;
case 3: symbole = ":|"; break;
case 4: symbole = "!!"; break;
case 5: symbole = "!!!"; break;
}
// Centrage horizontal
int w = u8g2.getStrWidth(symbole);
int x = xOffset + (largeur - w) / 2;
// Centrage vertical avec ascent/descent
int ascent = u8g2.getAscent();
int descent = u8g2.getDescent();
int fontH = ascent - descent;
int y = yOffset + (hauteur - fontH) / 2 + ascent;
u8g2.drawStr(x, y, symbole);
}
u8g2.sendBuffer();
delay(1000); // Pause entre deux mesures
}
📂 Ressources
- PDF du datasheet MQ-4
Fichiers
gaz-detector.ino gaz-detector-w-comments.ino
Amélioration
- Ajouter une alerte sonore, une connexion Wi-Fi pour des notifications, ou une interface web.