#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define DHTPIN 6
#define DHTTYPE DHT22
#define RED_LED_PIN 10 // LED Rouge pour alarme température
#define GREEN_LED_PIN 9 // LED Verte (optionnel)
#define BLUE_LED_PIN 11 // LED Bleue (optionnel)
#define TEMP_LIMIT 30
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
DHT dht(DHTPIN, DHTTYPE);
// Coordonnées du visage 32x32 centré en bas
const int FACE_W = 32;
const int FACE_H = 32;
const int FACE_X = (SCREEN_WIDTH - FACE_W) / 2; // 48
const int FACE_Y = SCREEN_HEIGHT - FACE_H; // 32
// Dessine un visage générique 32x32 (tête + yeux). La bouche dépend de l'humeur.
void drawHeadBase(int x, int y) {
// Tête (cercle) – centre et rayon
int cx = x + FACE_W / 2; // centre X
int cy = y + FACE_H / 2; // centre Y
int r = 15;
display.drawCircle(cx, cy, r, SSD1306_WHITE);
// Yeux (deux petits disques)
int eyeOffsetX = 6;
int eyeOffsetY = -3;
display.fillCircle(cx - eyeOffsetX, cy + eyeOffsetY, 2, SSD1306_WHITE);
display.fillCircle(cx + eyeOffsetX, cy + eyeOffsetY, 2, SSD1306_WHITE);
// Sourcils légers (courtes lignes)
display.drawLine(cx - eyeOffsetX - 3, cy + eyeOffsetY - 4, cx - eyeOffsetX + 3, cy + eyeOffsetY - 5, SSD1306_WHITE);
display.drawLine(cx + eyeOffsetX - 3, cy + eyeOffsetY - 5, cx + eyeOffsetX + 3, cy + eyeOffsetY - 4, SSD1306_WHITE);
}
// Bouche contente (arc vers le haut)
void drawMouthHappy(int x, int y) {
int cx = x + FACE_W / 2;
int cy = y + FACE_H / 2 + 5;
// Arc simplifié avec plusieurs lignes pour lisser
for (int i = -8; i <= 8; i++) {
int yy = cy + (i * i) / 16; // parabole douce
display.drawPixel(cx + i, yy, SSD1306_WHITE);
display.drawPixel(cx + i, yy + 1, SSD1306_WHITE);
}
}
// Bouche neutre (ligne droite)
void drawMouthNeutral(int x, int y) {
int cx = x + FACE_W / 2;
int cy = y + FACE_H / 2 + 6;
display.drawLine(cx - 8, cy, cx + 8, cy, SSD1306_WHITE);
display.drawLine(cx - 8, cy + 1, cx + 8, cy + 1, SSD1306_WHITE);
}
// Bouche triste (arc vers le bas)
void drawMouthSad(int x, int y) {
int cx = x + FACE_W / 2;
int cy = y + FACE_H / 2 + 10;
for (int i = -8; i <= 8; i++) {
int yy = cy - (i * i) / 16; // parabole inversée
display.drawPixel(cx + i, yy, SSD1306_WHITE);
display.drawPixel(cx + i, yy - 1, SSD1306_WHITE);
}
}
// Visages complets selon humeur
void drawHappyFace(int x, int y) { drawHeadBase(x, y); drawMouthHappy(x, y); }
void drawNeutralFace(int x, int y) { drawHeadBase(x, y); drawMouthNeutral(x, y); }
void drawSadFace(int x, int y) { drawHeadBase(x, y); drawMouthSad(x, y); }
void setup() {
Wire.begin(); // SDA=A4, SCL=A5 sur Arduino Uno
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
dht.begin();
// Configuration des LEDs RGB
pinMode(RED_LED_PIN, OUTPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(BLUE_LED_PIN, OUTPUT);
// Éteindre toutes les LEDs au démarrage
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(BLUE_LED_PIN, LOW);
}
void loop() {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
display.clearDisplay();
if (isnan(temp) || isnan(hum)) {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Erreur capteur");
display.display();
delay(1000);
return;
}
// Texte en haut
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Temp: ");
display.print(temp, 1);
display.print(" C");
display.setCursor(0, 10);
display.print("Hum: ");
display.print(hum, 1);
display.print(" %");
// LOGIQUE SANTÉ (OMS / Santé Canada)
// < 40% = Trop sec (inconfortable) → Triste 😟
// 40-60% = ZONE OPTIMALE (confort) → Content 😊
// > 60% = Trop humide (moite) → Neutre 😐
if (hum < 40) { drawHappyFace(FACE_X, FACE_Y); // 😟 Air trop sec
digitalWrite(GREEN_LED_PIN, HIGH); // LED verte = tout va bien
digitalWrite(BLUE_LED_PIN, LOW);
} else if (hum <= 60) {
drawSadFace(FACE_X, FACE_Y); // 😊 Confort optimal !
digitalWrite(BLUE_LED_PIN, HIGH); // LED bleue = alerte sec
digitalWrite(GREEN_LED_PIN, LOW);
} else {
drawNeutralFace(FACE_X, FACE_Y); // 😐 Air trop humide
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(BLUE_LED_PIN, LOW); // Aucune LED
}
// 🔴 ALERTE TEMPÉRATURE : LED rouge clignotante + écran clignotant
if (temp > TEMP_LIMIT) {
// Allumer LED rouge + afficher écran
digitalWrite(RED_LED_PIN, HIGH);
display.display();
delay(300);
// Éteindre LED rouge + effacer écran
digitalWrite(RED_LED_PIN, LOW);
display.clearDisplay();
display.display();
delay(300);
// On sort pour garder le rythme de clignotement
return;
} else {
// Température normale : LED rouge éteinte
digitalWrite(RED_LED_PIN, LOW);
}
display.display();
delay(500);
}