// Paramètres de Blynk
#define BLYNK_TEMPLATE_ID "TMPL2Wk0aIzw8"
#define BLYNK_TEMPLATE_NAME "Smart window actuator"
#define BLYNK_AUTH_TOKEN "nbPSl8YkqpIqGFBbNJiQHfLgckAICMxD"
#include "DHT.h"
#include <ESP32Servo.h>
#include <WiFi.h>
#include <ThingSpeak.h>
#include <BlynkSimpleEsp32.h>
// Déclaration des constantes pour les seuils de luminosité
const int DARK = 200;
const int LIGHT = 500;
const int BRIGHT = 800;
const int VERY_BRIGHT = 1000;
// Déclaration des broches pour les composants
#define PIN_RED 12
#define PIN_GREEN 14
#define PIN_BLUE 27
#define digital_In 34
#define analog_In 35
#define POT_PIN 25
#define SERVO_PIN 32
#define DHT_PIN 13
// Informations d'identification WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Informations du channel ThingSpeak
unsigned long myChannelNumber = 2551328;
const char* myWriteAPIKey = "IVMR6NLBWLCGJ6EY";
// Seuil CO2 (Scenario 1)
const int CO2_UNDER_7500 = 45;
const int CO2_UNDER_10000 = 90;
const int CO2_UNDER_15000 = 135;
// Seuil humidité
const int HUMD_UNDER_50 = 45;
const int HUMD_UNDER_60 = 90;
const int HUMD_UNDER_70 = 135;
// Seuil temperature (Scenario 2)
const int SEUIL_TEMP = 23;
// Déclaration des objets
DHT dht(DHT_PIN, DHT22);
Servo servo;
// Déclaration du tableau de broches LED
const int ledCount = 10;
int ledPins[] = {23, 22, 21, 19, 18, 5, 17, 16, 4, 2};
// L'angle d'ouvertures courante du servo
int CURRENT_ANGLE = 0;
bool manualMode = false; // Variable pour stocker l'état du mode manuel
char auth[] = BLYNK_AUTH_TOKEN;
void setup() {
Serial.begin(9600);
// Initialisation des composants
dht.begin();
servo.attach(SERVO_PIN);
servo.write(0);
// Configuration des entrées et sorties
pinMode(POT_PIN, INPUT);
pinMode(PIN_RED, OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
pinMode(PIN_BLUE, OUTPUT);
pinMode(digital_In, INPUT);
pinMode(analog_In, INPUT);
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
pinMode(ledPins[thisLed], OUTPUT);
}
delay(2000);
// Connexion au WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connecté");
// Initialiser ThingSpeak
WiFiClient client;
ThingSpeak.begin(client);
// Initialiser Blynk
Blynk.begin(auth, ssid, password);
}
void loop() {
Blynk.run();
if (!manualMode) { // Exécuter les scénarios uniquement si le mode manuel n'est pas actif
// 2. Scénario : Température
climatiseur();
// 3. Scénario : Luminosité
luminosite();
// 1. Scénario : CO2 élevé
fenetre();
}
// Vérifiez le niveau de CO2 et envoyez une notification si nécessaire
checkCO2();
// Envoyer des données à ThingSpeak
float temp = dht.readTemperature();
float hum = dht.readHumidity();
int luminosity = analogRead(analog_In);
Serial.print("Envoi des données à ThingSpeak... ");
ThingSpeak.setField(1, temp);
ThingSpeak.setField(2, hum);
ThingSpeak.setField(3, luminosity);
int responseCode = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if (responseCode == 200) {
Serial.println("Mise à jour du canal réussie.");
} else {
Serial.println("Problème de mise à jour du canal. Code d'erreur HTTP " + String(responseCode));
}
Serial.println();
delay(5000);
// Envoyer des données à Blynk
sendToBlynk();
}
void sendToBlynk() {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
int luminosity = analogRead(analog_In);
Blynk.virtualWrite(V1, temp);
Blynk.virtualWrite(V2, hum);
Blynk.virtualWrite(V3, luminosity);
}
// Fonction pour gérer le contrôle manuel depuis Blynk
BLYNK_WRITE(V4) {
int manual_angle = param.asInt();
if (manualMode) {
Serial.print("Angle de contrôle manuel : ");
Serial.println(manual_angle);
servo.write(manual_angle);
CURRENT_ANGLE = manual_angle;
}
}
// Fonction pour gérer l'activation/désactivation du mode manuel depuis Blynk
BLYNK_WRITE(V5) {
manualMode = param.asInt();
if (manualMode) {
Serial.println("Mode manuel activé");
} else {
Serial.println("Mode automatique activé");
}
}
void climatiseur() {
float temp = dht.readTemperature();
if (isnan(temp)) {
Serial.println(F("Échec de la lecture de la température"));
} else {
Serial.print("La température actuelle est de ");
Serial.print(temp);
Serial.print(" °C, ");
if (temp > SEUIL_TEMP) {
Serial.println("supérieure au seuil (23 °C) => Refroidissement");
analogWrite(PIN_RED, 0);
analogWrite(PIN_GREEN, 0);
analogWrite(PIN_BLUE, 255);
} else {
Serial.println("inférieure au seuil (23 °C) => Chauffage");
analogWrite(PIN_RED, 255);
analogWrite(PIN_GREEN, 0);
analogWrite(PIN_BLUE, 0);
}
}
}
void luminosite() {
int analogValue = analogRead(analog_In);
float voltage = analogValue / 4096.0 * 5.0;
float resistance = 2000.0 * voltage / (1.0 - voltage / 5.0);
float lux_a = pow(50.0 * 1000.0 * pow(10.0, 0.7) / resistance, 1.0 / 0.7);
Serial.print("Analogique : Lux ");
Serial.println(lux_a);
// Allumer les LED en fonction de la luminosité
if (lux_a <= DARK) {
Serial.println("Sombre");
for (int i = 0; i < 4; i++) {
digitalWrite(ledPins[0], HIGH);
digitalWrite(ledPins[1], LOW);
digitalWrite(ledPins[2], LOW);
digitalWrite(ledPins[3], LOW);
}
} else if (lux_a >= DARK && lux_a <= LIGHT ) {
Serial.println("Lumière");
for (int i = 0; i < 4; i++) {
digitalWrite(ledPins[0], HIGH);
digitalWrite(ledPins[1], HIGH);
digitalWrite(ledPins[2], LOW);
digitalWrite(ledPins[3], LOW);
}
} else if (lux_a <= LIGHT && lux_a >= BRIGHT) {
Serial.println("Luminosité élevée");
for (int i = 0; i < 4; i++) {
digitalWrite(ledPins[0], HIGH);
digitalWrite(ledPins[1], HIGH);
digitalWrite(ledPins[2], HIGH);
digitalWrite(ledPins[3], LOW);
}
} else {
Serial.println("Très lumineux");
for (int i = 0; i < 4; i++) {
digitalWrite(ledPins[0], HIGH);
digitalWrite(ledPins[1], HIGH);
digitalWrite(ledPins[2], HIGH);
digitalWrite(ledPins[3], HIGH);
}
}
}
void checkCO2() {
int potValue = analogRead(POT_PIN);
potValue = map(potValue, 0, 4095, 0, 17000); // concentration du CO2 (0ppm - 17000ppm)
potValue = 12000; // Simuler un niveau critique de CO2 supérieur à 10000 ppm
Serial.print("CO2 Level: ");
Serial.println(potValue);
if (potValue > 10000) {
Blynk.logEvent("co2_lev", "Attention : Niveau de CO2 très élevé détecté !");
}
}
int angleFromPot() {
// lire la valeur du potentiometre
int potValue = analogRead(POT_PIN);
potValue = map(potValue, 0, 4095, 0, 17000); // concentration du CO2 (0ppm - 3000ppm)
// choisir l'angle d'ouverture de la fenetre
int angle = 0;
if (potValue < 400) {
angle = 0;
Serial.println("Concentration de CO2 inférieure à 400ppm, fermer la fenêtre");
} else if (potValue < 7500) {
angle = CO2_UNDER_7500;
Serial.print("Concentration de CO2 inférieure à 7500ppm, ouvrir la fenêtre de ");
Serial.println(CO2_UNDER_7500);
} else if (potValue < 10000) {
angle = CO2_UNDER_10000;
Serial.print("Concentration de CO2 inférieure à 10000ppm, ouvrir la fenêtre de ");
Serial.println(CO2_UNDER_10000);
} else {
angle = CO2_UNDER_15000;
Serial.print("Concentration de CO2 inférieure à 15000ppm, ouvrir la fenêtre de ");
Serial.println(CO2_UNDER_15000);
}
return angle;
}
void fenetre() {
int humidity = dht.readHumidity();
int potValue = analogRead(POT_PIN);
potValue = map(potValue, 0, 4095, 0, 17000); // concentration du CO2 (0ppm - 3000ppm)
int angle = angleFromPot(); // obtenir l'angle en fonction de la concentration de CO2
if (humidity < 50) {
Serial.print("Humidité inférieure à 50%, fermer la fenêtre");
servo.write(0);
CURRENT_ANGLE = 0;
} else if (humidity < 60) {
angle = HUMD_UNDER_50;
Serial.print("Humidité entre 50% et 60%, ouvrir la fenêtre de ");
Serial.println(angle);
} else if (humidity < 70) {
angle = HUMD_UNDER_60;
Serial.print("Humidité entre 60% et 70%, ouvrir la fenêtre de ");
Serial.println(angle);
} else {
angle = HUMD_UNDER_70;
Serial.print("Humidité supérieure à 70%, ouvrir la fenêtre complètement de ");
Serial.println(angle);
}
if (!manualMode) { // Déplacer le servo uniquement si le mode manuel n'est pas activé
servo.write(angle);
CURRENT_ANGLE = angle;
Serial.print("\nAngle actuel ");
Serial.print(CURRENT_ANGLE);
Serial.print(", déplacer vers ");
Serial.println(angle);
}
}