#include <stdio.h>
#include <Wire.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
// ========== BROCHES ESP32 ==========
#define PIN_DHT 14
#define TYPE_DHT DHT22
#define PIN_NTC 33
#define PIN_JOYSTICK 34
#define PIN_TENSION 35
#define PIN_GLYCEMIE 32
#define PIN_BOUTON_PAGE 4
#define PIN_BOUTON_ACQUIT 13
#define PIN_LED_ROUGE 25
#define PIN_LED_VERT 26
#define PIN_LED_BLEU 27
#define PIN_BUZZER 15
#define I2C_SDA 21
#define I2C_SCL 22
// ========== OBJETS ==========
DHT capteurDHT(PIN_DHT, TYPE_DHT);
Adafruit_SSD1306 ecran(128, 64, &Wire, -1);
Adafruit_MPU6050 capteurMouvement;
WiFiClient clientWiFi;
PubSubClient mqtt(clientWiFi);
// ========== WIFI / MQTT ==========
const char* WIFI_NOM = "Wokwi-GUEST";
const char* WIFI_MOT_DE_PASSE = "";
const char* MQTT_SERVEUR = "broker.hivemq.com";
const int MQTT_PORT = 1883;
const char* MQTT_TOPIC = "demo12345-iot/vitals";
// ========== VALEURS SIMULEES ==========
float temperatureAmbiante = 0;
float humidite = 0;
float temperatureNTC = 0;
int frequenceCardiaque = 80;
int tensionSystolique = 120;
int tensionDiastolique = 80;
int glycemie = 95;
int pageAffichee = 0;
bool alerteAcquittee = false;
bool mpuDisponible = false;
bool oledDisponible = false;
unsigned long dernierAffichage = 0;
unsigned long dernierMQTT = 0;
unsigned long dernierDHT = 0;
bool alerteActive = false;
// ========== LED RGB A ANODE COMMUNE ==========
void reglerLED(bool rouge, bool vert, bool bleu) {
digitalWrite(PIN_LED_ROUGE, rouge ? LOW : HIGH);
digitalWrite(PIN_LED_VERT, vert ? LOW : HIGH);
digitalWrite(PIN_LED_BLEU, bleu ? LOW : HIGH);
}
void afficherEtatLED() {
if (alerteActive) {
reglerLED(true, false, false); // Rouge
digitalWrite(PIN_BUZZER, HIGH);
} else {
reglerLED(false, true, false); // Vert
digitalWrite(PIN_BUZZER, LOW);
}
}
// ========== LECTURE DES POTENTIOMETRES ==========
void lireValeursSimulees() {
int valeurJoystick = analogRead(PIN_JOYSTICK);
int valeurTension = analogRead(PIN_TENSION);
int valeurGlycemie = analogRead(PIN_GLYCEMIE);
frequenceCardiaque = map(valeurJoystick, 0, 4095, 50, 130);
tensionSystolique = map(valeurTension, 0, 4095, 90, 180);
tensionDiastolique = map(valeurTension, 0, 4095, 60, 110);
glycemie = map(valeurGlycemie, 0, 4095, 50, 250);
}
// ========== DETECTION DES ALERTES ==========
void verifierAlertes() {
alerteActive =
frequenceCardiaque < 60 ||
frequenceCardiaque > 100 ||
tensionSystolique >= 140 ||
tensionDiastolique >= 90 ||
glycemie < 70 ||
glycemie >= 126;
if (!alerteActive) {
alerteAcquittee = false;
}
}
// ========== TEMPERATURE NTC ==========
float lireTemperatureNTC() {
// Approximation pour une thermistance NTC 10 kOhm,
// beta 3950 et résistance fixe 10 kOhm.
// Vérifier le câblage et le type exact du composant Wokwi.
int adc = analogRead(PIN_NTC);
if (adc <= 0 || adc >= 4095) {
return NAN;
}
const float resistanceFixe = 10000.0;
const float resistanceNominale = 10000.0;
const float beta = 3950.0;
const float temperatureNominale = 298.15;
float resistanceNTC =
resistanceFixe * ((float)adc / (4095.0 - adc));
float temperatureKelvin =
1.0 / (1.0 / temperatureNominale +
(1.0 / beta) * log(resistanceNTC / resistanceNominale));
return temperatureKelvin - 273.15;
}
// ========== OLED ==========
void afficherOLED() {
if (!oledDisponible) return;
ecran.clearDisplay();
ecran.setTextColor(SSD1306_WHITE);
ecran.setTextSize(1);
ecran.setCursor(0, 0);
if (pageAffichee == 0) {
ecran.println("SURVEILLANCE");
ecran.println("----------------");
ecran.print("Frequence: ");
ecran.print(frequenceCardiaque);
ecran.println(" bpm");
ecran.print("Tension: ");
ecran.print(tensionSystolique);
ecran.print("/");
ecran.println(tensionDiastolique);
ecran.print("Glycemie: ");
ecran.print(glycemie);
ecran.println(" mg/dL");
} else {
ecran.println("ENVIRONNEMENT");
ecran.println("----------------");
ecran.print("Air: ");
ecran.print(temperatureAmbiante, 1);
ecran.println(" C");
ecran.print("Humidite: ");
ecran.print(humidite, 0);
ecran.println(" %");
ecran.print("NTC: ");
if (isnan(temperatureNTC)) {
ecran.println("A verifier");
} else {
ecran.print(temperatureNTC, 1);
ecran.println(" C");
}
ecran.print("Alerte: ");
ecran.println(alerteActive ? "OUI" : "NON");
}
ecran.display();
}
// ========== MONITEUR SERIE ==========
void afficherMoniteurSerie() {
Serial.println();
Serial.println("========== SURVEILLANCE ==========");
Serial.printf("Frequence cardiaque : %d bpm\n",
frequenceCardiaque);
Serial.printf("Tension arterielle : %d/%d mmHg\n",
tensionSystolique, tensionDiastolique);
Serial.printf("Glycemie simulee : %d mg/dL\n",
glycemie);
if (!isnan(temperatureAmbiante)) {
Serial.printf("Temperature ambiante: %.1f C\n",
temperatureAmbiante);
} else {
Serial.println("Temperature ambiante: indisponible");
}
if (!isnan(humidite)) {
Serial.printf("Humidite : %.1f %%\n", humidite);
} else {
Serial.println("Humidite : indisponible");
}
if (!isnan(temperatureNTC)) {
Serial.printf("Temperature NTC : %.1f C\n",
temperatureNTC);
} else {
Serial.println("Temperature NTC : verifier capteur");
}
Serial.printf("Etat : %s\n",
alerteActive ? "ALERTE" : "NORMAL");
Serial.println("==================================");
}
// ========== WIFI ==========
void connecterWiFi() {
Serial.print("Connexion au Wi-Fi Wokwi");
WiFi.begin(WIFI_NOM, WIFI_MOT_DE_PASSE);
int essais = 0;
while (WiFi.status() != WL_CONNECTED && essais < 30) {
delay(500);
Serial.print(".");
essais++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWi-Fi connecte.");
} else {
Serial.println("\nWi-Fi indisponible. Mode local actif.");
}
}
// ========== MQTT ==========
void reconnecterMQTT() {
if (WiFi.status() != WL_CONNECTED || mqtt.connected()) return;
String identifiant = "ESP32-Monitor-" +
String((uint32_t)ESP.getEfuseMac(), HEX);
mqtt.connect(identifiant.c_str());
}
void publierMQTT() {
if (!mqtt.connected()) return;
char message[256];
snprintf(message, sizeof(message),
"{\"frequence_cardiaque\":%d,"
"\"tension_systolique\":%d,"
"\"tension_diastolique\":%d,"
"\"glycemie_simulee\":%d,"
"\"temperature_air\":%.1f,"
"\"humidite\":%.1f,"
"\"alerte\":%s}",
frequenceCardiaque,
tensionSystolique,
tensionDiastolique,
glycemie,
temperatureAmbiante,
humidite,
alerteActive ? "true" : "false");
mqtt.publish(MQTT_TOPIC, message);
}
// ========== BOUTONS ==========
void gererBoutons() {
static bool ancienEtatPage = HIGH;
static bool ancienEtatAcquit = HIGH;
bool etatPage = digitalRead(PIN_BOUTON_PAGE);
bool etatAcquit = digitalRead(PIN_BOUTON_ACQUIT);
if (ancienEtatPage == HIGH && etatPage == LOW) {
pageAffichee = 1 - pageAffichee;
afficherOLED();
}
if (ancienEtatAcquit == HIGH && etatAcquit == LOW) {
alerteAcquittee = true;
digitalWrite(PIN_BUZZER, LOW);
}
ancienEtatPage = etatPage;
ancienEtatAcquit = etatAcquit;
}
// ========== INITIALISATION ==========
void setup() {
Serial.begin(115200);
pinMode(PIN_BOUTON_PAGE, INPUT_PULLUP);
pinMode(PIN_BOUTON_ACQUIT, INPUT_PULLUP);
pinMode(PIN_LED_ROUGE, OUTPUT);
pinMode(PIN_LED_VERT, OUTPUT);
pinMode(PIN_LED_BLEU, OUTPUT);
pinMode(PIN_BUZZER, OUTPUT);
analogReadResolution(12);
reglerLED(false, false, false);
digitalWrite(PIN_BUZZER, LOW);
Wire.begin(I2C_SDA, I2C_SCL);
capteurDHT.begin();
oledDisponible = ecran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
if (!oledDisponible) {
Serial.println("OLED non detecte.");
}
mpuDisponible = capteurMouvement.begin();
if (mpuDisponible) {
Serial.println("MPU6050 detecte.");
} else {
Serial.println("MPU6050 non detecte.");
}
mqtt.setServer(MQTT_SERVEUR, MQTT_PORT);
connecterWiFi();
Serial.println("\nSysteme de surveillance demarre.");
Serial.println("Les valeurs cardiaques, tension et glycemie");
Serial.println("sont simulees par les commandes analogiques.");
}
// ========== BOUCLE PRINCIPALE ==========
void loop() {
gererBoutons();
lireValeursSimulees();
if (millis() - dernierDHT >= 2000) {
dernierDHT = millis();
temperatureAmbiante = capteurDHT.readTemperature();
humidite = capteurDHT.readHumidity();
temperatureNTC = lireTemperatureNTC();
}
verifierAlertes();
afficherEtatLED();
if (millis() - dernierAffichage >= 2000) {
dernierAffichage = millis();
afficherMoniteurSerie();
afficherOLED();
}
if (!mqtt.connected()) {
reconnecterMQTT();
}
mqtt.loop();
if (millis() - dernierMQTT >= 5000) {
dernierMQTT = millis();
publierMQTT();
}
delay(50);
}