// ============================================================
// Projet : Contrôle automatique du Winder — Dolidol
// Auteur : Stagiaire Bachelor EIA
// Outil : Wokwi + ESP32 Arduino
// Variateur simulé par : Servo Motor
// ============================================================
// LOGIQUE :
// Rouleau PLEIN = distance PETITE (capteur proche)
// Rouleau VIDE = dis
1234567891011121314151617181920212223242526
// ============================================================
// Projet : Contrôle automatique du Winder — Dolidol
// Auteur : Stagiaire Bachelor EIA
// Outil : Wokwi + ESP32 Arduino
// Variateur simulé par : Servo Motor
// ============================================================
// LOGIQUE :
// Rouleau PLEIN = distance PETITE (capteur proche)
// Rouleau VIDE = distance GRANDE (capteur loin)
// Servo angle = vitesse :
Simulation
$0tance GRANDE (capteur loin)
// Servo angle = vitesse :
// 180° = vitesse normale (100%)
// 130° = vitesse réduite (78%)
// 80° = vitesse lente (47%)
// 0° = STOP (0%)
// ============================================================
#define BLYNK_TEMPLATE_ID "TMPL2aafLykkT"
#define BLYNK_TEMPLATE_NAME "Sfe winder"
#define BLYNK_AUTH_TOKEN "Aedg-QuVNnqYj1pZ_LDyN1Pex4VmvN0h"
#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Servo.h>
// --- LCD ---
LiquidCrystal_I2C lcd(0x27, 16, 2);
// --- Servo (simule le variateur) ---
Servo variateur;
#define SERVO_PIN 32
// Angles = vitesses
#define VITESSE_NORMALE 180 // 100% — État 1
#define VITESSE_ALERTE 130 // 78% — État 2
#define VITESSE_LENTE 80 // 47% — État 3
#define VITESSE_STOP 0 // 0% — État 4
// --- Capteur ultrason ---
#define TRIG_PIN 5
#define ECHO_PIN 18
// --- LEDs ---
#define LED_VERTE 25
#define LED_ORANGE 26
#define LED_ROUGE 27
// --- Buzzer ---
#define BUZZER 14
// --- Boutons ---
#define BTN_START 12
#define BTN_STOP 13
#define BTN_RESET 15
// --- Seuils distance (cm) ---
#define SEUIL_NORMAL 5.0 // < 5 cm → rouleau plein
#define SEUIL_1 10.0 // 5-10 cm → pré-alerte
#define SEUIL_2 15.0 // 10-15 cm → compensation vitesse
#define SEUIL_3 20.0 // > 20 cm → arrêt automatique
// --- États ---
#define ETAT_ARRETE 0
#define ETAT_NORMAL 1
#define ETAT_ALERTE 2
#define ETAT_LENT 3
#define ETAT_STOP_AUTO 4
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
BlynkTimer timer;
int etatActuel = ETAT_ARRETE;
float distanceBlynk = 0.0;
int vitessePct = 0;
int angleServo = 0;
String etatTexte = "ARRET";
bool systemeAutorise = false;
BLYNK_WRITE(V4) { // Start/Stop depuis Blynk
int val = param.asInt();
if (val == 1 && etatActuel == ETAT_ARRETE) {
etatActuel = ETAT_NORMAL;
systemeAutorise = true;
afficherLCD("Systeme demarre ", "Blynk START ");
} else if (val == 0) {
etatActuel = ETAT_ARRETE;
systemeAutorise = false;
toutEteindre();
variateur.write(VITESSE_STOP);
afficherLCD("SYSTEME ARRETE ", "Blynk STOP ");
}
}
BLYNK_WRITE(V5) { // Reset depuis Blynk
int val = param.asInt();
if (val == 1 && etatActuel == ETAT_STOP_AUTO) {
etatActuel = ETAT_ARRETE;
systemeAutorise = false;
toutEteindre();
variateur.write(VITESSE_STOP);
afficherLCD("RESET OK ", "Blynk RESET ");
}
}
void envoyerBlynk() {
Blynk.virtualWrite(V0, distanceBlynk);
Blynk.virtualWrite(V1, etatTexte);
Blynk.virtualWrite(V2, vitessePct);
Blynk.virtualWrite(V3, angleServo);
}
// ============================================================
void setup() {
Serial.begin(115200);
// LCD
lcd.init();
lcd.backlight();
afficherLCD("Winder Control ", "Initialisation..");
delay(2000);
lcd.clear();
// Servo
variateur.attach(SERVO_PIN);
variateur.write(VITESSE_STOP);
// Capteur ultrason
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
// LEDs
pinMode(LED_VERTE, OUTPUT);
pinMode(LED_ORANGE, OUTPUT);
pinMode(LED_ROUGE, OUTPUT);
// Buzzer
pinMode(BUZZER, OUTPUT);
// Boutons
pinMode(BTN_START, INPUT_PULLUP);
pinMode(BTN_STOP, INPUT_PULLUP);
pinMode(BTN_RESET, INPUT_PULLUP);
toutEteindre();
afficherLCD("Appuyer START ", " ");
Blynk.begin(auth, ssid, pass);
timer.setInterval(1000L, envoyerBlynk);
}
// ============================================================
void loop() {
Blynk.run();
timer.run();
bool start = (digitalRead(BTN_START) == LOW);
bool stop = (digitalRead(BTN_STOP) == LOW);
bool reset = (digitalRead(BTN_RESET) == LOW);
// --- STOP : arrêt immédiat ---
if (stop) {
etatActuel = ETAT_ARRETE;
toutEteindre();
variateur.write(VITESSE_STOP);
afficherLCD("SYSTEME ARRETE ", "Appuyer START ");
delay(300);
return;
}
// --- RESET : débloque après arrêt automatique ---
if (reset && etatActuel == ETAT_STOP_AUTO) {
etatActuel = ETAT_ARRETE;
toutEteindre();
variateur.write(VITESSE_STOP);
afficherLCD("RESET OK ", "Appuyer START ");
delay(500);
return;
}
// --- START ---
if (start && etatActuel == ETAT_ARRETE) {
etatActuel = ETAT_NORMAL;
afficherLCD("Systeme demarre ", " ");
delay(300);
}
// Système arrêté → attend bouton
if (etatActuel == ETAT_ARRETE) return;
// ÉTAT 4 BLOQUÉ — ignore distance jusqu'au Reset
if (etatActuel == ETAT_STOP_AUTO) {
toutEteindre();
digitalWrite(LED_ROUGE, HIGH);
variateur.write(VITESSE_STOP);
afficherLCD("ARRET AUTO ! ", "Changer rouleau ");
bipBuzzer(1, 300);
delay(1000);
return;
}
// --- Mesure distance ---
float distance = mesurerDistance();
Serial.print("Distance: ");
Serial.print(distance, 1);
Serial.println(" cm");
// ============================================================
// LOGIQUE DES ÉTATS
// ============================================================
if (distance < SEUIL_NORMAL) {
// ÉTAT 1 : Rouleau plein — vitesse normale
etatActuel = ETAT_NORMAL;
toutEteindre();
digitalWrite(LED_VERTE, HIGH);
variateur.write(VITESSE_NORMALE);
afficherLCD("Rouleau : OK ", "V:100% " + String(distance,1) + "cm ");
distanceBlynk = distance;
vitessePct = 100;
angleServo = VITESSE_NORMALE;
etatTexte = "Etat 1 - Normal";
Serial.println("ETAT 1 — Servo: 180 (100%)");
} else if (distance >= SEUIL_NORMAL && distance < SEUIL_1) {
// ÉTAT 2 : Pré-alerte
etatActuel = ETAT_ALERTE;
toutEteindre();
digitalWrite(LED_ORANGE, HIGH);
variateur.write(VITESSE_ALERTE);
bipBuzzer(1, 150);
afficherLCD("ATTENTION ! ", "V:78% " + String(distance,1) + "cm ");
distanceBlynk = distance;
vitessePct = 78;
angleServo = VITESSE_ALERTE;
etatTexte = "Etat 2 - Alerte";
Serial.println("ETAT 2 — Servo: 130 (78%)");
} else if (distance >= SEUIL_1 && distance < SEUIL_2) {
// ÉTAT 3 : Compensation de vitesse
etatActuel = ETAT_LENT;
toutEteindre();
digitalWrite(LED_ORANGE, HIGH);
digitalWrite(LED_ROUGE, HIGH);
variateur.write(VITESSE_LENTE);
bipBuzzer(2, 100);
afficherLCD("VITESSE REDUITE ", "V:47% " + String(distance,1) + "cm ");
distanceBlynk = distance;
vitessePct = 47;
angleServo = VITESSE_LENTE;
etatTexte = "Etat 3 - Compensation";
Serial.println("ETAT 3 — Servo: 80 (47%)");
} else if (distance >= SEUIL_2) {
// ÉTAT 4 : Arrêt automatique
etatActuel = ETAT_STOP_AUTO;
toutEteindre();
digitalWrite(LED_ROUGE, HIGH);
variateur.write(VITESSE_STOP);
bipBuzzer(3, 400);
afficherLCD("ARRET AUTO ! ", "Changer rouleau ");
distanceBlynk = distance;
vitessePct = 0;
angleServo = VITESSE_STOP;
etatTexte = "Etat 4 - Stop Auto";
Serial.println(">>> ETAT 4 — Servo: 0 — ARRET AUTOMATIQUE !");
}
delay(200);
}
// ============================================================
// Mesure distance HC-SR04
// ============================================================
float mesurerDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duree = pulseIn(ECHO_PIN, HIGH, 30000);
if (duree == 0) return 999.0;
return (duree / 2.0) * 0.0343;
}
// ============================================================
// Éteindre LEDs et buzzer (pas le servo)
// ============================================================
void toutEteindre() {
digitalWrite(LED_VERTE, LOW);
digitalWrite(LED_ORANGE, LOW);
digitalWrite(LED_ROUGE, LOW);
digitalWrite(BUZZER, LOW);
}
// ============================================================
// Bips buzzer
// ============================================================
void bipBuzzer(int nombre, int dureeMs) {
for (int i = 0; i < nombre; i++) {
digitalWrite(BUZZER, HIGH);
delay(dureeMs);
digitalWrite(BUZZER, LOW);
delay(100);
}
}
// ============================================================
// Affichage LCD
// ============================================================
void afficherLCD(String ligne1, String ligne2) {
lcd.setCursor(0, 0);
lcd.print(ligne1);
lcd.setCursor(0, 1);
lcd.print(ligne2);
}