Moniteur ECG RFID MQTT - ayaabidghozy13/Syst-me-Embarqu-Biom-dicaux GitHub Wiki

Moniteur ECG connecté avec RFID et MQTT (Arduino UNO R4 WiFi + Node-RED)

Dans ce projet, vous allez construire un moniteur ECG connecté : un patient s'identifie avec un badge RFID, appuie sur un bouton pour démarrer la mesure, et son électrocardiogramme s'affiche en temps réel sur un tableau de bord Node-RED. Le système estime le rythme cardiaque (BPM) et déclenche une lampe et un buzzer si le BPM dépasse un seuil réglable depuis le dashboard.

1

Le prototype complet : Arduino UNO R4 WiFi, module ECG AD8232 avec électrodes, lecteur RFID RC522, bouton, lampe et buzzer.

⚠️ Avertissement : ce projet est pédagogique. L'estimation du BPM est simplifiée et ne remplace en aucun cas un appareil médical certifié.


Sommaire

  1. Aperçu du projet
  2. Prérequis
  3. Composants nécessaires
  4. Schéma électrique
  5. Topics et format des messages MQTT
  6. Le firmware Arduino
  7. Le flow Node-RED
  8. Le tableau de bord
  9. Démonstration
  10. Conclusion

1. Aperçu du projet

Avant de commencer, voici comment le système fonctionne dans son ensemble.

flowchart LR
    subgraph Arduino["Arduino UNO R4 WiFi"]
        RFID["Lecteur RFID RC522"]
        BTN["Bouton"]
        ECG["Module ECG AD8232"]
        LAMP["Lampe (LED)"]
        BUZ["Buzzer"]
    end
    Broker(("Broker MQTT<br/>broker.emqx.io"))
    NR["Node-RED<br/>(traitement + alarme)"]
    DASH["Dashboard 2.0<br/>(navigateur)"]

    RFID -- "health/rfid" --> Broker
    BTN -- "health/button" --> Broker
    ECG -- "health/ecg (50 Hz)" --> Broker
    Arduino -- "health/status (2 s)" --> Broker
    Broker --> NR --> DASH
    NR -- "health/command" --> Broker
    Broker -- "lamp / buzzer" --> LAMP & BUZ
Loading

En résumé :

  • L'Arduino UNO R4 WiFi se connecte au Wi-Fi puis au broker MQTT public broker.emqx.io.
  • Il publie sur plusieurs topics : l'identifiant du badge RFID, les événements du bouton, les échantillons ECG (50 par seconde) et son état (heartbeat toutes les 2 s).
  • Node-RED est abonné à ces topics. Il traite le signal ECG, estime le BPM, gère l'alarme et alimente le tableau de bord.
  • Node-RED publie les commandes de la lampe et du buzzer sur health/command, auxquelles l'Arduino est abonné.

Déroulement d'une session

La logique de l'Arduino repose sur une machine à trois états : la mesure ne peut démarrer que si un patient est identifié.

stateDiagram-v2
    [*] --> ATTENTE_BADGE
    ATTENTE_BADGE --> PATIENT_IDENTIFIE : badge RFID lu
    ATTENTE_BADGE --> ATTENTE_BADGE : bouton → "refused" (bip grave)
    PATIENT_IDENTIFIE --> ACQUISITION : bouton → "start"
    PATIENT_IDENTIFIE --> ATTENTE_BADGE : 60 s sans appui
    ACQUISITION --> ATTENTE_BADGE : bouton → "stop"
Loading
État Ce qui se passe
Attente badge Aucun ECG n'est envoyé. Un appui sur le bouton est refusé (bip grave).
Patient identifié L'UID du badge est publié et un bip confirme la lecture. Le patient a 60 s pour appuyer sur le bouton.
Acquisition L'ECG est envoyé à 50 Hz. Les badges sont ignorés. Un nouvel appui arrête la mesure et le patient suivant doit se badger.

2. Prérequis

Avant de suivre ce projet, assurez-vous d'avoir les éléments suivants. Les liens mènent vers les tutoriels d'installation et de prise en main.

Environnement de développement

Node-RED et dashboard

MQTT

Tutoriels sur les capteurs

Librairies

Librairie Auteur Équivalent PlatformIO (lib_deps)
MFRC522 GithubCommunity (miguelbalboa) miguelbalboa/MFRC522
PubSubClient Nick O'Leary knolleary/PubSubClient

WiFiS3 et SPI sont fournies avec le paquet de cartes Arduino UNO R4.


3. Composants nécessaires

jj

Modules et circuits

Composant Référence Rôle
Carte microcontrôleur Arduino UNO R4 WiFi (ABX00087) Acquisition, logique de session, Wi-Fi + MQTT
Module ECG AD8232 Single Lead Heart Rate Monitor (ex. SparkFun SEN-12650) Amplification et filtrage du signal cardiaque
Électrodes Câble 3 dérivations jack 3,5 mm + électrodes adhésives Ag/AgCl jetables Captation du signal sur la peau
Lecteur RFID MFRC522 / RC522 13,56 MHz (SPI) Identification du patient
Badges RFID Cartes ou porte-clés MIFARE Classic 1K Un badge par patient

Autres composants

Composant Quantité Remarque
Bouton poussoir 1 Câblé sur le pull-up interne, donc aucune résistance externe
Buzzer passif 1 Passif obligatoire : la fréquence est générée par tone()
LED (lampe d'alarme) 1 Ou module Grove LED
Résistance 220 Ω 1 En série avec la LED
Breadboard 1
Fils de connexion ~20 Mâle-mâle et mâle-femelle
Câble USB-C 1 Programmation et alimentation

4. Schéma électrique

La conception du circuit électrique a été réalisée avec deux outils différents :

  • Un schéma statique illustré (à gauche) : une vue claire et simplifiée du câblage, où chaque module est numéroté (alimentation, lampe, bouton, lecteur RFID, capteur ECG, haut-parleur). Il permet de comprendre le montage en un coup d'œil.
  • Cirkit Designer (à droite) : le circuit complet avec les vrais composants (Arduino UNO R4 WiFi, AD8232, RC522, bouton, LED, buzzer). Contrairement au schéma statique, Cirkit Designer permet aussi de simuler le circuit directement dans le navigateur.

Copie de Challenges Finding ways to keep the team motivated Not enough time for new hobbies Creative blocks (2)

À gauche : schéma statique illustré. À droite : circuit réalisé avec Cirkit Designer.

🔗 Ouvrir le projet Cirkit Designer : app.cirkitdesigner.com/project/a811d282-9870-4226-afa9-fd8e530f53ca

Les deux schémas utilisent exactement le même brochage, détaillé dans le tableau ci-dessous.

Tableau de câblage

Lecteur RFID RC522 (bus SPI)

RC522 Arduino UNO R4 WiFi
SDA (SS) D10
SCK D13
MOSI D11
MISO D12
RST D7
3.3V 3.3V
GND GND
IRQ non connecté

Module ECG AD8232

AD8232 Arduino UNO R4 WiFi
OUTPUT A0
LO+ D5
LO− D4
3.3V 3.3V
GND GND
SDN non connecté

Bouton, buzzer et lampe

Composant Broche Câblage
Bouton D2 Une patte sur D2, l'autre sur GND (INPUT_PULLUP, actif à l'état bas)
Buzzer passif D3 + sur D3, − sur GND
LED D9 D9 → résistance 220 Ω → anode, cathode → GND

💡 Attention : le RC522 et l'AD8232 s'alimentent en 3,3 V, jamais en 5 V.

Placement des électrodes

05-placement-electrodes

Le placement suit le guide SparkFun : électrode rouge (RA) sous la clavicule droite, électrode jaune (LA) sous la clavicule gauche, électrode verte (RL) en bas à droite de l'abdomen (référence). Les sorties LO+ / LO− passent à l'état haut quand une électrode est décollée : c'est ce qui permet d'afficher « Vérifier les électrodes » sur le dashboard.


5. Topics et format des messages MQTT

Topic Sens Exemple de contenu Fréquence
health/ecg Arduino → Node-RED {"raw":512,"lo_plus":0,"lo_moins":0,"time":123456} 50 Hz, uniquement en acquisition
health/rfid Arduino → Node-RED AC:C9:6B:04 À chaque badge accepté
health/button Arduino → Node-RED start, stop ou refused À chaque appui
health/status Arduino → Node-RED Attente badge, Patient identifie, Acquisition en cours Toutes les 2 s + à chaque changement d'état
health/status (Last Will) Broker → Node-RED Arduino deconnecte Si l'Arduino disparaît brutalement
health/command Node-RED → Arduino lamp=1;buzzer=1;frequency=1200 À chaque changement d'alarme ou commande manuelle

Le message de commande contient toujours l'état complet des deux actionneurs : l'Arduino n'a jamais besoin de « deviner » l'état précédent.


6. Le firmware Arduino

Le code complet se trouve sur la page Code source (firmware/cardiotrack/cardiotrack.ino). Seules les parties essentielles sont expliquées ici.

Configuration Wi-Fi et MQTT

Remplacez ces valeurs par celles de votre réseau :

const char* WIFI_SSID = "VOTRE_SSID";
const char* WIFI_PASSWORD = "VOTRE_MOT_DE_PASSE";
const char* MQTT_SERVER = "broker.emqx.io";
const int MQTT_PORT = 1883;

Une boucle entièrement non bloquante

Aucune fonction n'utilise de delay() dans la boucle. Le Wi-Fi et le MQTT se reconnectent tout seuls à intervalles réguliers (DELAI_WIFI = 10 s, DELAI_MQTT = 3 s) grâce à millis(). C'est indispensable pour ne pas manquer d'échantillons ECG ou d'appuis sur le bouton.

void loop() {
  gererWiFi();
  gererMQTT();
  if (mqtt.connected()) {
    mqtt.loop();
    envoyerHeartbeat();
  }
  lireRFID();
  lireBouton();
  verifierDelaiIdentification();
  envoyerECG();
}

La machine à états

Le cœur du programme est l'énumération EtatSysteme. La fonction actionBouton() donne au même bouton un rôle différent selon l'état courant :

enum EtatSysteme { ATTENTE_BADGE, PATIENT_IDENTIFIE, ACQUISITION };

void actionBouton() {
  switch (etat) {
    case ATTENTE_BADGE:       // pas de badge : refus
      mqtt.publish(TOPIC_BUTTON, "refused");
      bip(400, 300);
      break;
    case PATIENT_IDENTIFIE:   // patient connu : démarrage
      mqtt.publish(TOPIC_BUTTON, "start");
      changerEtat(ACQUISITION);
      break;
    case ACQUISITION:         // mesure en cours : arrêt
      mqtt.publish(TOPIC_BUTTON, "stop");
      changerEtat(ATTENTE_BADGE);
      break;
  }
}

(Version simplifiée ; le code réel vérifie aussi la connexion MQTT et joue un bip à chaque étape.)

Envoi de l'ECG

L'ECG est échantillonné toutes les 20 ms (50 Hz), uniquement en acquisition, et envoyé en JSON avec l'état des électrodes :

void envoyerECG() {
  if (etat != ACQUISITION) return;
  if (millis() - dernierEchantillon < PERIODE_ECG) return;
  ...
  snprintf(message, sizeof(message),
           "{\"raw\":%d,\"lo_plus\":%d,\"lo_moins\":%d,\"time\":%lu}",
           valeurECG, loPlus, loMoins, maintenant);
  mqtt.publish(TOPIC_ECG, message);
}

Heartbeat et Last Will

Deux mécanismes permettent au dashboard de savoir si l'Arduino est en ligne :

  • un heartbeat : l'état courant est publié sur health/status toutes les 2 s, même quand aucun ECG n'est envoyé ;
  • un Last Will MQTT : à la connexion, l'Arduino demande au broker de publier Arduino deconnecte s'il disparaît sans prévenir.
mqtt.connect(clientId, TOPIC_STATUS, 0, false, "Arduino deconnecte");

Réception des commandes

La fonction recevoirCommande() découpe le message lamp=1;buzzer=0;frequency=800 avec strstr() et atoi(), puis applique l'état à la lampe (digitalWrite) et au buzzer (tone / noTone).


7. Le flow Node-RED

06-flow-node-red

Le flow (node-red/flows.json) s'importe via Menu → Import. Il est organisé en blocs :

Bloc Nœuds principaux Rôle
ECG mqtt in health/ecg → ECG processing + BPM estimate Graphe ECG, estimation BPM, état des électrodes
Alarme BPM alarm — lamp + buzzer → mqtt out health/command Compare le BPM au seuil et pilote lampe et buzzer
Bouton mqtt in health/button → Button event Affiche start/stop/refused, remet tout à zéro au stop
Connexion mqtt in health/status + Watchdog 2 s → Arduino connection + session État en ligne/hors ligne et étape de la session
Patient 3 × mqtt in → Patient card state → ui-template Carte patient avec l'UID du badge
Commandes Slider + 5 boutons → Manual command Seuil d'alarme et commandes manuelles
Bandeau ui-template Titre CardioTrack, horloge, illustration

Estimation du BPM

C'est la partie la plus importante du flow. La fonction suit la ligne de base du signal avec un filtre passe-bas très lent, puis détecte chaque front montant au-dessus d'un seuil (pic R) :

s.base = s.base * 0.98 + raw * 0.02;   // ligne de base lente
const ac = raw - s.base;               // composante variable du signal

if (prevAc < threshold && ac >= threshold && s.armed) {
    const interval = now - s.lastPeak;              // temps entre deux pics
    if (interval >= 300 && interval <= 2000)        // 30 à 200 BPM
        bpm = Math.round(60000 / interval);
    s.lastPeak = now;
    s.armed = false;                                // évite de compter 2 fois le même pic
}
if (ac < threshold * 0.4) s.armed = true;           // réarmement (hystérésis)

La valeur threshold = 18 est à calibrer selon votre capteur et le placement des électrodes.

Alarme

L'alarme ne publie une commande que lorsque son état change (inactive → active ou l'inverse), pour ne pas inonder le broker. Les commandes manuelles du dashboard restent prioritaires : si l'utilisateur a éteint le buzzer pendant une alarme, il ne se rallume pas.


8. Le tableau de bord

07-dashboard-simulation

Le dashboard est accessible sur http://<adresse-node-red>:1880/dashboard/live. Il contient :

  • Bandeau CardioTrack : titre, ligne ECG animée, horloge.
  • Vital Signs : jauge du BPM estimé et état de l'alarme.
  • Patient : icône et numéro RFID du patient, avec l'état de la session.
  • Live ECG : signal brut sur les 10 dernières secondes.
  • Events & Connectivity : session, badge, électrodes, bouton, état de l'Arduino.
  • Remote Controls : seuil d'alarme (40–180 BPM), lampe et buzzer ON/OFF, « Tout arrêter ».

9. Conclusion

Ce projet montre comment combiner identification, acquisition temps réel et supervision à distance avec un seul microcontrôleur, un broker MQTT et Node-RED. Les points clés à retenir :

  • une machine à états simple garantit qu'aucune mesure ne démarre sans patient identifié ;
  • une boucle non bloquante permet de gérer RFID, bouton, ECG et réseau en parallèle ;
  • le heartbeat et le Last Will MQTT rendent l'état de connexion fiable ;
  • le traitement lourd (BPM, alarme) est fait côté Node-RED, ce qui garde le firmware léger.

Pour aller plus loin, consultate la page Home Trainer, ouverture et critique.

⚠️ **GitHub.com Fallback** ⚠️