Skip to Content

Détection de chute en intérieur avec mmWave C1001

Détection de chute en intérieur avec mmWave C1001

Le capteur intérieur de détection de chute C1001 60GHz mmWave est un module radar compact conçu pour la surveillance de la présence humaine et de la sécurité. Il fonctionne dans la bande des ondes millimétriques à 60 GHz et peut détecter les mouvements, la posture, ainsi que de très petits mouvements corporels comme la respiration.

Contrairement aux systèmes traditionnels à PIR ou basés sur caméra, ce capteur utilise des signaux radar pour analyser les ondes réfléchies par le corps humain. Cela lui permet de détecter à la fois le mouvement et l’immobilité, y compris les cas où une personne est tombée et reste immobile. Il fonctionne également dans l’obscurité totale et ne capture pas d’images, ce qui le rend adapté aux environnements intérieurs sensibles à la vie privée.

Le module intègre des algorithmes intégrés pour la détection de chute, la surveillance du sommeil, la détection de présence et les mesures basiques des signes vitaux. Il peut mesurer la respiration et le rythme cardiaque à courte portée et détecter l’activité humaine jusqu’à environ 11 mètres. Les résultats traités sont directement transmis via une interface série, ce qui évite un traitement complexe du signal sur le microcontrôleur.

Dans ce tutoriel, vous apprendrez comment connecter le capteur mmWave C4002 à un Arduino ou un ESP32 pour mesurer les signes vitaux, détecter les chutes et surveiller la qualité du sommeil.

Overview

Pièces requises

Vous pouvez vous procurer le capteur mmWave C1001 chez DFRobot ou Amazon. Vous aurez également besoin d’un Arduino, ESP8266 ou ESP32. J’utilise un Arduino UNO et un ESP32-C3 SuperMini dans ce tutoriel, mais tout autre Arduino, ESP32 ou ESP8266 fonctionnera tant qu’il dispose d’une sortie 5V. Enfin, une breadboard et quelques câbles Dupont pour le câblage seront utiles.

Capteur mmWave C1001

ESP32-C3 SuperMini

Câble USB C

Arduino

Arduino Uno

USB Data Sync cable Arduino

Câble USB pour Arduino UNO

Dupont wire set

Jeu de fils Dupont

Half_breadboard56a

Breadboard

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Matériel du capteur mmWave C1001

Le capteur C1001 est basé sur un front-end radar à ondes millimétriques 60 GHz. Il fonctionne dans une plage de fréquences d’environ 61 à 61,5 GHz et émet des ondes électromagnétiques à faible puissance dans l’environnement. Le signal transmis est réfléchi par les objets et les corps humains, et le capteur analyse le signal retourné pour extraire des informations sur le mouvement et la présence. L’image ci-dessous montre l’arrière et l’avant du module capteur C1001 :

Back and Front of mmWave C1001 Sensor Module
Arrière et avant du module capteur mmWave C1001

Le radar utilise une approche d’imagerie par nuage de points pour modéliser la position et le mouvement d’une cible humaine. Cette méthode permet au capteur de détecter les changements de posture et les déplacements spatiaux plutôt que de se baser uniquement sur des déclencheurs de mouvement simples. En conséquence, il peut distinguer avec plus de fiabilité les positions debout, en mouvement et allongée.

Le capteur peut aussi détecter des micro-mouvements tels que le déplacement de la poitrine causé par la respiration et le battement cardiaque. Cela est possible car les signaux millimétriques sont sensibles à de très petits changements de surface, même dans la gamme submillimétrique.

Portée de détection et champ de vision

Le capteur C1001 supporte une distance maximale de détection allant jusqu’à 11 mètres dans des conditions optimales. Il offre un large champ de vision avec un angle de couverture d’environ 100 degrés à la fois horizontalement et verticalement.

Lorsqu’il est utilisé pour la détection de chute, le capteur est généralement monté au plafond. À une hauteur d’installation d’environ 2,7 mètres, la zone effective de détection de chute forme une zone circulaire d’environ 4 mètres de diamètre.

Pour la surveillance des signes vitaux, la portée de détection est plus courte. Les mesures de respiration et de rythme cardiaque sont les plus précises dans une distance d’environ 0,4 à 1,5 mètre. La surveillance du sommeil peut s’étendre un peu plus loin, jusqu’à environ 2,5 mètres du capteur.

Traitement du signal et algorithmes embarqués

Le C1001 intègre un traitement du signal et des algorithmes de détection embarqués. Les données radar brutes sont traitées en interne, et l’utilisateur reçoit des informations de haut niveau au lieu de flux de signaux bruts. Cela réduit la charge de calcul sur le microcontrôleur connecté.

Le firmware interne implémente plusieurs modes de détection. Ceux-ci incluent la détection de présence humaine, le suivi de mouvement, la détection de chute et la surveillance du sommeil. L’algorithme de détection de chute analyse les transitions de posture et identifie les changements soudains suivis d’immobilité. Il peut aussi suivre la durée d’inactivité après un événement de chute.

L’algorithme de détection des signes vitaux extrait des motifs périodiques à partir des signaux réfléchis. Il calcule les fréquences respiratoires généralement dans la plage de 10 à 25 respirations par minute et les fréquences cardiaques entre 60 et 100 battements par minute.

Caractéristiques électriques

Le capteur fonctionne avec une tension d’alimentation de 5 V et consomme typiquement moins de 100 mA. Cela le rend adapté aux systèmes embarqués alimentés par des cartes de développement standard.

L’émetteur radar délivre un signal avec un niveau de puissance d’environ 6 dBm. Cela assure une puissance suffisante pour la détection en intérieur tout en maintenant une faible consommation et une opération sûre.

L’appareil est conçu pour fonctionner dans une plage de température de −20 °C à 60 °C. Cela permet une opération stable dans des environnements intérieurs typiques et de nombreuses applications semi-industrielles.

Interface et sortie des données

Le C1001 communique via une interface série UART. Il fournit des trames de données traitées incluant des états de détection tels que la présence, le statut de chute et les informations sur les signes vitaux.

L’alimentation (5V) se fait via les broches VIN et GND, tandis que les broches TX et RX sont utilisées pour la communication série avec un microcontrôleur. Deux broches de sortie numérique auxiliaires nommées IO1 et IO2 sont conçues pour signaler les événements de chute et la présence humaine. La photo ci-dessous montre le brochage du module C1001 :

Pinout of the C1001 Sensor
Brochage du capteur C1001

Notez que je n’ai pas réussi à faire fonctionner IO1 ou IO2. Je n’ai pas trouvé de fonction dans la bibliothèque pour activer ces broches de sortie et par défaut elles semblent inactives.

Contraintes d’installation et d’utilisation

Le capteur nécessite un bon positionnement pour atteindre des performances optimales. Pour la détection de chute, une configuration en montage plafond est recommandée. Le faisceau radar forme une zone de couverture tridimensionnelle, et les obstacles ou objets en mouvement peuvent affecter la qualité du signal.

La précision de la détection des signes vitaux dépend de la distance, de l’orientation et de la stabilité de l’environnement. Des sources de mouvement externes comme des ventilateurs ou des rideaux peuvent introduire du bruit dans le signal réfléchi.

En raison de la nature de la détection radar, le module fonctionne de manière constante dans des environnements peu éclairés ou totalement sombres. Il n’est pas affecté par les conditions de lumière ambiante et ne dépend pas de la détection optique.

Spécifications techniques

Le tableau suivant résume les spécifications techniques du capteur mmWave C1001 :

Paramètre Valeur / Description
Fréquence de fonctionnement 60 GHz mmWave (env. 61–61,5 GHz)
Technologie de détection Radar FMCW avec traitement par nuage de points
Portée de détection Jusqu’à 11 m (présence et mouvement)
Portée de détection de chute Optimisée pour montage plafond, zone d’environ 4 m de diamètre
Portée de détection des signes vitaux ~0,4 m à 1,5 m (jusqu’à ~2,5 m pour la surveillance du sommeil)
Champ de vision ~100° horizontal et vertical
Capacités de détection Présence, mouvement, détection de chute, surveillance du sommeil
Mesure des signes vitaux Respiration et rythme cardiaque
Plage de fréquence respiratoire ~10–25 respirations par minute
Plage de fréquence cardiaque ~60–100 bpm
Tension d’alimentation 5 V
Courant de fonctionnement < 100 mA
Puissance d’émission ~6 dBm
Interface de communication UART (niveau TTL)
Broches de sortie numérique IO1 (détection de chute), IO2 (détection de présence)
Niveau logique 3,3 V
Température de fonctionnement −20 °C à 60 °C
Méthode de montage Montage plafond ou mural (plafond préféré pour détection de chute)
Sortie des données Données traitées (pas de données radar brutes requises)
Plateformes supportées Arduino, ESP32, ESP8266

Connexion du capteur mmWave C1001 à Arduino

Connecter le capteur mmWave C1001 à un Arduino UNO est simple. Commencez par connecter VIN au 5V de l’Arduino. Ensuite, connectez GND à GND. Enfin, connectez l’interface UART en reliant RX à GPIO 5 et TX à GPIO 4. L’image ci-dessous montre le câblage complet :

Connecting the mmWave C1001 Sensor to an Arduino UNO
Connexion du capteur mmWave C1001 à un Arduino UNO

Pour plus de commodité, voici un tableau des connexions à réaliser :

C1001 Arduino Uno
VIN 5V
GND GND
RX GPIO 5
TX GPIO 4

Connexion du capteur mmWave C1001 à ESP32

L’ESP32 dispose de trois interfaces série et vous pouvez configurer les broches et l’interface que vous souhaitez utiliser. Ici, je connecte TX à GPIO 3 et RX à GPIO 4. Il faudra s’en souvenir lors de l’écriture du code. Enfin, nous connectons VIN au 5V et GND à G. L’image ci-dessous montre le câblage complet :

Connecting the mmWave C1001 Sensor to an ESP32-C3 Supermini
Connexion du capteur mmWave C1001 à un ESP32-C3 Supermini

Notez que vous avez besoin d’un ESP32 avec une broche de sortie 5V et que vous devez connecter VIN du C1001 à la broche 5V et non à la broche commune 3,3V ! L’image ci-dessous montre le brochage de l’ESP32-C3 Supermini que j’utilise ici.

Brochage de l’ESP32-C3 Supermini

Pour plus de commodité, voici un tableau des connexions à réaliser.

C1001 ESP32-C3 Supermini
VIN 5V
GND G
RX 4
TX 3

Installation de la bibliothèque DFRobot_HumanDetection

Avant de pouvoir écrire du code, il faudra installer la DFRobot_HumanDetection bibliothèque. Pour installer cette bibliothèque, allez sur le dépôt DFRobot_HumanDetection, cliquez sur le bouton vert « <> Code » puis sur « Download ZIP » pour télécharger la bibliothèque au format ZIP comme montré ci-dessous :

Ensuite, créez un nouveau sketch Arduino, allez dans Sketch -> Include Library -> Add .ZIP Library … pour installer la bibliothèque ZIP téléchargée (DFRobot_HumanDetection-master.zip) :

Code : Mesures des signes vitaux

L’exemple de code suivant montre comment mesurer les signes vitaux tels que le rythme cardiaque et la respiration avec le capteur C1001. J’ai légèrement modifié le code original de la basic.ino dans le dépôt github en supprimant quelques impressions et en ajoutant le support pour les microcontrôleurs Arduino et ESP866 en plus de l’ESP32.

// Libraries:
// - DFRobot_HumanDetection V 1.0.0
//   https://github.com/DFRobot/DFRobot_HumanDetection
// - ESP32 Core V 3.3.8

#include "DFRobot_HumanDetection.h"

#if defined(ESP8266) || defined(ARDUINO_AVR_UNO)
  #include <SoftwareSerial.h>
  SoftwareSerial mySerial(4, 5);
  DFRobot_HumanDetection hu(&mySerial);
#elif defined(ESP32)
  DFRobot_HumanDetection hu(&Serial1);
#else
  #error "Unsupported board."
#endif


void setup() {
  Serial.begin(115200);

  #if defined(ESP32)
    Serial1.begin(115200, SERIAL_8N1, 3, 4);
  #elif defined(ESP8266) || defined(ARDUINO_AVR_UNO)
    mySerial.begin(115200);
  #endif

  Serial.println("Starting...");
  while (hu.begin() != 0) {
    Serial.println("init error!!!");
    delay(1000);
  }

  hu.configWorkMode(hu.eSleepMode);
  hu.configLEDLight(hu.eHPLed, 1); 

  // Sensor needs reset after parameters change
  hu.sensorRet();    
}

void loop() {
  Serial.print("Presence        : ");
  switch (hu.smHumanData(hu.eHumanPresence)) {
    case 0:
      Serial.println("No"); break;
    case 1:
      Serial.println("Yes"); break;
    default:
      Serial.println("Read error");
  }

  Serial.print("Motion          : ");
  switch (hu.smHumanData(hu.eHumanMovement)) {
    case 0:
      Serial.println("None"); break;
    case 1:
      Serial.println("Still"); break;
    case 2:
      Serial.println("Active"); break;
    default:
      Serial.println("Read error");
  }

  Serial.print("Movement        : ");
  Serial.println(hu.smHumanData(hu.eHumanMovingRange));
  Serial.print("Respiration rate: ");
  Serial.println(hu.getBreatheValue());
  Serial.print("Heart rate      : ");
  Serial.println(hu.getHeartRate());
  Serial.println("-----------------------");
  delay(1000);
}

Importations

Le code commence par inclure la bibliothèque requise pour le capteur. La DFRobot_HumanDetection bibliothèque fournit toutes les fonctions nécessaires pour communiquer avec le capteur mmWave C1001 et accéder aux données traitées.

#include "DFRobot_HumanDetection.h"

Cette bibliothèque abstrait le protocole UART bas niveau. Elle permet de travailler avec des fonctions de haut niveau telles que la détection de présence, le statut de mouvement et les signes vitaux.

Configuration série spécifique à la carte

Le code configure ensuite l’interface série selon la carte cible. Le capteur C1001 communique via UART, donc un port série doit être assigné.

#if defined(ESP8266) || defined(ARDUINO_AVR_UNO)
  #include <SoftwareSerial.h>
  SoftwareSerial mySerial(4, 5);
  DFRobot_HumanDetection hu(&mySerial);
#elif defined(ESP32)
  DFRobot_HumanDetection hu(&Serial1);
#else
  #error "Unsupported board."
#endif

Pour des cartes comme Arduino Uno ou ESP8266, un port série logiciel est créé sur les broches 4 et 5. Cela est nécessaire car ces cartes ont souvent un seul UART matériel.

Pour l’ESP32, le code utilise Serial1, qui est un UART matériel. C’est plus fiable et supporte des débits plus élevés.

L’objet hu est créé comme instance de la classe capteur. Il reçoit un pointeur vers l’interface série utilisée en interne pour la communication avec le capteur.

Fonction setup

La fonction setup() initialise la communication série et prépare le capteur à fonctionner.

void setup() {
  Serial.begin(115200);

Le port série principal est démarré à 115200 bauds. Il est utilisé pour le débogage et l’affichage des données du capteur dans le moniteur série.

  #if defined(ESP32)
    Serial1.begin(115200, SERIAL_8N1, 3, 4);

Sur l’ESP32, l’UART matériel est initialisé à 115200 bauds. La configuration SERIAL_8N1 signifie 8 bits de données, pas de parité, 1 bit d’arrêt. Les broches 3 et 4 sont assignées comme RX et TX. Pour les autres cartes, l’interface série logicielle est démarrée au même débit.

  #elif defined(ESP8266) || defined(ARDUINO_AVR_UNO)
    mySerial.begin(115200);
  #endif

Un message simple est affiché pour indiquer que l’initialisation a commencé :

  Serial.println("Starting...");

La fonction hu.begin() initialise la communication avec le capteur. Elle retourne 0 en cas de succès. Si l’initialisation échoue, le code affiche un message d’erreur et réessaie chaque seconde. Cette boucle garantit que le capteur est prêt avant de continuer :

  while (hu.begin() != 0) {
    Serial.println("init error!!!");
    delay(1000);
  }

Configuration du capteur

Après l’initialisation, le capteur est configuré via des fonctions de la bibliothèque. Cette ligne définit le mode de fonctionnement du capteur. Le mode eSleepMode est optimisé pour détecter des humains immobiles et surveiller les signes vitaux comme la respiration et le rythme cardiaque.

  hu.configWorkMode(hu.eSleepMode);

Cette fonction contrôle la LED embarquée. Le paramètre eHPLed sélectionne le type de LED, et 1 l’allume. Cela peut être utile pour le débogage ou un retour visuel.

  hu.configLEDLight(hu.eHPLed, 1); 

Et cette fonction réinitialise le capteur. Un reset est nécessaire après modification des paramètres pour qu’ils prennent effet.

  hu.sensorRet(); 

Fonction loop

La fonction loop() lit continuellement les données du capteur et les affiche dans le moniteur série.

D’abord, on affiche une étiquette pour la détection de présence humaine.

void loop() {
  Serial.print("Presence        : ");

Ensuite, on utilise la fonction smHumanData() pour lire un type spécifique de données du capteur. Le paramètre eHumanPresence sélectionne la détection de présence.

  switch (hu.smHumanData(hu.eHumanPresence)) {

Une valeur de 0 signifie qu’aucun humain n’est détecté. Une valeur de 1 signifie qu’une personne est présente. Toute autre valeur indique une erreur de communication ou de lecture :

    case 0:
      Serial.println("No"); break;
    case 1:
      Serial.println("Yes"); break;
    default:
      Serial.println("Read error");

Statut de mouvement

La section suivante lit l’état de mouvement de la personne détectée. Le paramètre eHumanMovement sélectionne la classification du mouvement.

  Serial.print("Motion          : ");
  switch (hu.smHumanData(hu.eHumanMovement)) {

Une valeur de 0 signifie qu’aucun mouvement n’est détecté, une valeur de 1 signifie que la personne est présente mais immobile, et une valeur de 2 indique un mouvement actif.

    case 0:
      Serial.println("None"); break;
    case 1:
      Serial.println("Still"); break;
    case 2:
      Serial.println("Active"); break;

Amplitude du mouvement

Le code affiche ensuite une valeur numérique représentant l’intensité ou l’amplitude du mouvement.

  Serial.print("Movement        : ");
  Serial.println(hu.smHumanData(hu.eHumanMovingRange));

Cette valeur est utile pour estimer l’importance du mouvement de la personne dans la zone de détection. Des valeurs plus élevées indiquent un mouvement plus fort ou plus étendu.

Signes vitaux

Le capteur peut aussi mesurer la respiration et le rythme cardiaque. La fonction getBreatheValue() retourne la fréquence respiratoire en respirations par minute.

  Serial.print("Respiration rate: ");
  Serial.println(hu.getBreatheValue());

Et la fonction getHeartRate() retourne le rythme cardiaque en battements par minute. Ces mesures sont basées sur les micro-mouvements détectés par le radar.

  Serial.print("Heart rate      : ");
  Serial.println(hu.getHeartRate());

Temporisation de la boucle

À la fin de la boucle, un délai est ajouté pour contrôler la fréquence de mise à jour.

  Serial.println("-----------------------");
  delay(1000);
}

Exemple de sortie

L’image suivante montre un exemple de sortie du code. Notez qu’il faut plusieurs minutes avant que les mesures de respiration et de rythme cardiaque apparaissent. Le capteur a besoin d’un certain temps pour stabiliser les lectures.

Mesurer la respiration et le rythme cardiaque sans contact et à une distance allant jusqu’à 1,5 mètre est impressionnant. Notez cependant que la précision est limitée. Voir l’article Functional Test Report of DFRobot C1001 mmWave Sensor pour plus d’informations sur les conditions de mesure, la fiabilité et la précision.

Code : Détection de chute

Le code suivant montre comment réaliser la détection de chute avec le capteur C1001. Comme précédemment, il s’agit d’une version légèrement modifiée du code fall.ino dans le dépôt github de la bibliothèque DFRobot_HumanDetection. Il supporte les microcontrôleurs Arduino, ESP866 et ESP32.

// Libraries:
// - DFRobot_HumanDetection V 1.0.0
//   https://github.com/DFRobot/DFRobot_HumanDetection
// - ESP32 Core V 3.3.8

#include "DFRobot_HumanDetection.h"

#if defined(ESP8266) || defined(ARDUINO_AVR_UNO)
  #include <SoftwareSerial.h>
  SoftwareSerial mySerial(4, 5);
  DFRobot_HumanDetection hu(&mySerial);
#elif defined(ESP32)
  DFRobot_HumanDetection hu(&Serial1);
#else
  #error "Unsupported board."
#endif


void setup() {
  Serial.begin(115200);

  #if defined(ESP32)
    Serial1.begin(115200, SERIAL_8N1, 3, 4);
  #elif defined(ESP8266) || defined(ARDUINO_AVR_UNO)
    mySerial.begin(115200);
  #endif

  Serial.println("Starting...");
  while (hu.begin() != 0) {
    Serial.println("init error!!!");
    delay(1000);
  }

  hu.configWorkMode(hu.eFallingMode);        // Set working mode to fall detection
  hu.configLEDLight(hu.eFALLLed, 1);         // Set HP LED switch, it will not light up even if the sensor detects a person present when set to 0.
  hu.configLEDLight(hu.eHPLed, 1);           // Set FALL LED switch, it will not light up even if the sensor detects a person falling when set to 0.
  hu.dmInstallHeight(270);                   // Set installation height, it needs to be set according to the actual height of the surface from the sensor, unit: CM.
  hu.dmFallTime(5);                          // Set fall time, the sensor needs to delay the current set time after detecting a person falling before outputting the detected fall, this can avoid false triggering, unit: seconds.
  hu.dmUnmannedTime(1);                      // Set unattended time, when a person leaves the sensor detection range, the sensor delays a period of time before outputting a no person status, unit: seconds.
  hu.dmFallConfig(hu.eResidenceTime, 200);    // Set dwell time, when a person remains still within the sensor detection range for more than the set time, the sensor outputs a stationary dwell status. Unit: seconds.
  hu.dmFallConfig(hu.eFallSensitivityC, 3);  // Set fall sensitivity, range 0~3, the larger the value, the more sensitive.
  hu.sensorRet();                            // Module reset, must perform sensorRet after setting data.
}

void loop() {
  Serial.print("Fallen    : ");
  switch (hu.getFallData(hu.eFallState)) {
    case 0:
      Serial.println("No"); break;
    case 1:
      Serial.println("Yes"); break;
    default:
      Serial.println("Read error");
  }

  Serial.print("Stationary: ");
  switch (hu.getFallData(hu.estaticResidencyState)) {
    case 0:
      Serial.println("No"); break;
    case 1:
      Serial.println("Yes"); break;
    default:
      Serial.println("Read error");
  }

  Serial.println("-----------------");
  delay(1000);
}

Importations et initialisation de l’objet

L’inclusion de la bibliothèque et la création de l’objet sont identiques à l’exemple précédent. La même bibliothèque DFRobot_HumanDetection est utilisée, et l’objet capteur hu est initialisé avec une interface série matérielle ou logicielle selon la carte.

La configuration UART et la mise en place de la communication suivent la même structure qu’avant. Vous pouvez vous référer à l’explication précédente pour les détails sur l’initialisation série et la construction de l’objet.

Fonction setup

La séquence d’initialisation dans setup() est aussi la même. Les interfaces série sont démarrées, et le capteur est initialisé avec hu.begin(). La boucle de réessai garantit une communication stable avant de continuer.

La différence dans cet exemple commence avec la configuration du capteur. Le capteur est maintenant explicitement configuré pour la détection de chute.

Configuration du mode détection de chute

Le mode de fonctionnement est changé pour un mode dédié à la détection de chute.

hu.configWorkMode(hu.eFallingMode);

Cela bascule le firmware interne pour utiliser des algorithmes de détection de chute au lieu de la détection générale de présence ou de la surveillance du sommeil. Le capteur se concentre maintenant sur les changements de posture et les mouvements soudains suivis d’inactivité.

Configuration des LED

Deux indicateurs LED sont configurés pour un retour visuel.

hu.configLEDLight(hu.eFALLLed, 1);
hu.configLEDLight(hu.eHPLed, 1);

La eFALLLed contrôle la LED qui indique un événement de chute détecté. La eHPLed contrôle la LED de détection de présence. Les régler toutes deux à 1 les active.

Ces LED sont pilotées par la logique interne de détection et peuvent aider lors des tests et calibrations.

Hauteur d’installation

La hauteur d’installation est un paramètre critique pour une détection de chute précise. L’appel de fonction suivant définit la hauteur de montage du capteur à 270 cm. La valeur doit correspondre à la hauteur réelle d’installation car le traitement radar dépend de la géométrie.

hu.dmInstallHeight(270);

Des valeurs de hauteur incorrectes peuvent entraîner une estimation de position inexacte et des fausses détections.

Temporisation de la détection de chute

Le capteur inclut un délai configurable avant de confirmer un événement de chute. L’appel de fonction suivant définit un délai de 5 secondes. Après avoir détecté une chute potentielle, le capteur attend ce délai avant de la signaler comme chute valide.

hu.dmFallTime(5);

Cela aide à filtrer les mouvements courts ou non critiques qui pourraient autrement déclencher des faux positifs.

Délai de détection sans présence

Le capteur retarde aussi le signalement lorsqu’aucune personne n’est présente. La fonction suivante définit un délai de 1 seconde avant de passer à l’état « pas de personne ».

hu.dmUnmannedTime(1);

Cela évite les basculements rapides lorsque la personne quitte brièvement ou se déplace à la limite de la zone de détection.

Détection d’immobilité prolongée

Le capteur peut détecter quand une personne reste immobile longtemps. L’appel de fonction suivant définit le temps d’immobilité à 200 secondes.

hu.dmFallConfig(hu.eResidenceTime, 200);

Si une personne reste immobile dans la zone de détection plus longtemps que cette période, le capteur signale un état stationnaire.

Cette fonction est utile dans les scénarios de détection de chute car une personne allongée immobile après une chute peut être identifiée.

Sensibilité de détection de chute

La sensibilité de l’algorithme de détection de chute peut être ajustée. Ici, la sensibilité est réglée au niveau 3, qui est la valeur la plus élevée.

hu.dmFallConfig(hu.eFallSensitivityC, 3);

Une sensibilité plus élevée augmente la probabilité de détecter les chutes mais peut aussi accroître les faux positifs. Des valeurs plus basses réduisent la sensibilité et nécessitent des changements de mouvement plus marqués.

Application de la configuration

Après avoir défini tous les paramètres, le capteur est réinitialisé.

hu.sensorRet();

Comme expliqué précédemment, cette étape est nécessaire pour que la nouvelle configuration prenne effet. Le capteur redémarre avec les paramètres mis à jour.

Fonction loop

La boucle lit continuellement les données liées à la chute depuis le capteur. Contrairement à l’exemple précédent, ce code utilise getFallData() au lieu de smHumanData().

Détection de l’état de chute

La fonction getFallData() récupère les résultats traités de détection de chute. Le paramètre eFallState sélectionne le statut de chute :

Serial.print("Fallen    : ");
switch (hu.getFallData(hu.eFallState)) {

Une valeur de 0 signifie qu’aucune chute n’est détectée, et une valeur de 1 indique qu’un événement de chute a été confirmé par le capteur :

case 0:
  Serial.println("No"); break;
case 1:
  Serial.println("Yes"); break;

Détection d’état stationnaire

La constante estaticResidencyState est utilisée pour récupérer le statut d’immobilité prolongée :

Serial.print("Stationary: ");
switch (hu.getFallData(hu.estaticResidencyState)) {

Une valeur de 1 signifie qu’une personne est restée immobile plus longtemps que le temps d’immobilité configuré. Cela peut indiquer une situation critique, surtout combinée à une chute détectée.

case 0:
  Serial.println("No"); break;
case 1:
  Serial.println("Yes"); break;

Temporisation de la boucle

La boucle se termine par un délai et un séparateur pour la lisibilité.

Serial.println("-----------------");
delay(1000);

Code : Surveillance du sommeil

Dans ce dernier exemple de code, nous réalisons la surveillance du sommeil avec le capteur C1001. Le code est basé sur l’exemple sleep.ino dans la bibliothèque DFRobot_HumanDetection. J’ai simplement ajouté le support pour les microcontrôleurs Arduino et ESP866.

// Libraries:
// - DFRobot_HumanDetection V 1.0.0
//   https://github.com/DFRobot/DFRobot_HumanDetection
// - ESP32 Core V 3.3.8

#include "DFRobot_HumanDetection.h"

#if defined(ESP8266) || defined(ARDUINO_AVR_UNO)
  #include <SoftwareSerial.h>
  SoftwareSerial mySerial(4, 5);
  DFRobot_HumanDetection hu(&mySerial);
#elif defined(ESP32)
  DFRobot_HumanDetection hu(&Serial1);
#else
  #error "Unsupported board."
#endif

void setup() {
  Serial.begin(115200);

  #if defined(ESP32)
    Serial1.begin(115200, SERIAL_8N1, 3, 4);
  #elif defined(ESP8266) || defined(ARDUINO_AVR_UNO)
    mySerial.begin(115200);
  #endif

  Serial.println("Starting...");
  while (hu.begin() != 0) {
    Serial.println("init error!!!");
    delay(1000);
  }

  hu.configWorkMode(hu.eSleepMode);
  hu.configLEDLight(hu.eHPLed, 1); 

  // Sensor needs reset after parameters change
  hu.sensorRet();    
}

void loop() {
  Serial.print("Bed entry status:");
  switch (hu.smSleepData(hu.eInOrNotInBed)) {
    case 0:
      Serial.println("Out of bed"); break;
    case 1:
      Serial.println("In bed"); break;
    default:
      Serial.println("Read error");
  }

  Serial.print("Sleep status:");
  switch (hu.smSleepData(hu.eSleepState)) {
    case 0:
      Serial.println("Deep sleep"); break;
    case 1:
      Serial.println("Light sleep"); break;
    case 2:
      Serial.println("Awake"); break;
    case 3:
      Serial.println("None"); break;
    default:
      Serial.println("Read error");
  }
  Serial.print("Awake duration: ");
  Serial.println(hu.smSleepData(hu.eWakeDuration));
  Serial.print("Deep sleep duration: ");
  Serial.println(hu.smSleepData(hu.eDeepSleepDuration));
  Serial.print("Sleep quality score: ");
  Serial.println(hu.smSleepData(hu.eSleepQuality));

  sSleepComposite comprehensiveState = hu.getSleepComposite();
  Serial.println("Comprehensive sleep status:{");

  Serial.print("\tExistence status: ");
  switch (comprehensiveState.presence) {
    case 0:
      Serial.println("No one"); break;
    case 1:
      Serial.println("Someone is present"); break;
    default:
      Serial.println("Read error");
  }

  Serial.print("\tSleep status:");
  switch (comprehensiveState.sleepState) {
    case 0:
      Serial.println("Deep sleep"); break;
    case 1:
      Serial.println("Light sleep"); break;
    case 2:
      Serial.println("Awake"); break;
    case 3:
      Serial.println("None"); break;
    default:
      Serial.println("Read error");
  }

  Serial.print("\tAverage respiration rate: ");
  Serial.println(comprehensiveState.averageRespiration);
  Serial.print("\tAverage heart rate: ");
  Serial.println(comprehensiveState.averageHeartbeat);
  Serial.print("\tNumber of turns: ");
  Serial.println(comprehensiveState.turnoverNumber);
  Serial.print("\tProportion of significant body movement: ");
  Serial.println(comprehensiveState.largeBodyMove);
  Serial.print("\tProportion of minor body movement: ");
  Serial.println(comprehensiveState.minorBodyMove);
  Serial.print("\tNumber of apneas: ");
  Serial.println(comprehensiveState.apneaEvents);
  Serial.println("}");

  Serial.print("Sleep abnormalities:");
  switch (hu.smSleepData(hu.eSleepDisturbances)) {
    case 0:
      Serial.println("Sleep duration less than 4 hours"); break;
    case 1:
      Serial.println("Sleep duration more than 12 hours"); break;
    case 2:
      Serial.println("Long time abnormal absence of person"); break;
    case 3:
      Serial.println("None"); break;
    default:
      Serial.println("Read error");
  }

  sSleepStatistics statistics = hu.getSleepStatistics();  // Get sleep statistics, for whole night
  Serial.print("\tSleep quality score: ");
  Serial.println(statistics.sleepQualityScore);
  Serial.print("\tProportion of awake time: ");
  Serial.println(statistics.sleepTime);
  Serial.print("\tProportion of light sleep time: ");
  Serial.println(statistics.wakeDuration);
  Serial.print("\tProportion of light sleep time: ");
  Serial.println(statistics.shallowSleepPercentage);
  Serial.print("\tProportion of deep sleep time: ");
  Serial.println(statistics.deepSleepPercentage);
  Serial.print("\tOut of bed duration: ");
  Serial.println(statistics.timeOutOfBed);
  Serial.print("\tNumber of times out of bed: ");
  Serial.println(statistics.exitCount);
  Serial.print("\tNumber of turns: ");
  Serial.println(statistics.turnOverCount);
  Serial.print("\tAverage respiration: ");
  Serial.println(statistics.averageRespiration);
  Serial.print("\tAverage heartbeat: ");
  Serial.println(statistics.averageHeartbeat);
  Serial.println("}");

  Serial.print("Sleep quality rating: ");
  switch (hu.smSleepData(hu.eSleepQualityRating)) {
    case 0:
      Serial.println("None"); break;
    case 1:
      Serial.println("Good sleep quality"); break;
    case 2:
      Serial.println("Average sleep quality"); break;
    case 3:
      Serial.println("Poor sleep quality"); break;
    default:
      Serial.println("Read error");
  }

  Serial.print("Abnormal struggle status: ");
  switch (hu.smSleepData(hu.eAbnormalStruggle)) {
    case 0:
      Serial.println("None"); break;
    case 1:
      Serial.println("Normal status"); break;
    case 2:
      Serial.println("Abnormal struggle status"); break;
    default:
      Serial.println("Read error");
  }

  Serial.println("-----------------------------------");
  delay(1000);
}

Importations et initialisation de l’objet

L’inclusion de la bibliothèque et la création de l’objet sont identiques aux exemples précédents. La même classe DFRobot_HumanDetection est utilisée, et le capteur est connecté via une interface UART. L’objet hu gère toute la communication et le traitement des données.

La configuration série pour ESP32, ESP8266 et Arduino Uno reste inchangée. Reportez-vous aux explications précédentes pour les détails sur l’initialisation de l’interface UART et pourquoi le port série matériel est préféré sur l’ESP32.

Fonction setup

La séquence d’initialisation dans setup() suit le même schéma qu’avant. Les ports série sont démarrés, et le capteur est initialisé avec hu.begin() avec une boucle de réessai pour garantir une communication stable.

La différence clé est le mode de fonctionnement sélectionné. Dans cet exemple, le capteur est configuré pour la surveillance du sommeil au lieu de la détection de chute.

hu.configWorkMode(hu.eSleepMode);

Ce mode active les algorithmes pour détecter la présence au lit, les phases de sommeil et les signes vitaux tels que la respiration et le rythme cardiaque au fil du temps.

hu.configLEDLight(hu.eHPLed, 1);

La LED de présence est activée, fournissant un retour visuel lorsqu’une personne est détectée.

hu.sensorRet();

Comme expliqué précédemment, le capteur doit être réinitialisé après les changements de configuration pour que les nouveaux paramètres prennent effet.

Aperçu de la fonction loop

La fonction loop() lit continuellement les données liées au sommeil depuis le capteur. Contrairement aux exemples précédents, ce code utilise smSleepData() et des structures de données composites supplémentaires pour accéder à des métriques plus avancées.

La sortie est plus complexe car le capteur agrège et analyse les données sur la durée.

Détection d’entrée au lit

La première section vérifie si une personne est au lit.

Serial.print("Bed entry status:");
switch (hu.smSleepData(hu.eInOrNotInBed)) {

La fonction smSleepData() fonctionne de manière similaire à smHumanData(), mais elle accède aux paramètres liés au sommeil.

case 0:
  Serial.println("Out of bed"); break;
case 1:
  Serial.println("In bed"); break;

Une valeur de 1 indique qu’une personne est détectée dans la zone du lit. Cela est déterminé en combinant la détection de présence et l’analyse de position.

Détection de l’état de sommeil

La section suivante lit la phase de sommeil actuelle.

Serial.print("Sleep status:");
switch (hu.smSleepData(hu.eSleepState)) {

Le capteur classe le sommeil en plusieurs phases.

case 0:
  Serial.println("Deep sleep"); break;
case 1:
  Serial.println("Light sleep"); break;
case 2:
  Serial.println("Awake"); break;
case 3:
  Serial.println("None"); break;

Ces états sont dérivés des motifs de mouvement et des variations des signes vitaux. Le sommeil profond se caractérise par un mouvement minimal et une respiration stable, tandis que les états éveillés montrent plus d’activité.

Durée et qualité du sommeil

Le capteur fournit des métriques de durée et de qualité sous forme de valeurs numériques.

Avec la constante eWakeDuration, la fonction retourne la durée pendant laquelle la personne est restée éveillée durant la période de surveillance.

Serial.print("Awake duration: ");
Serial.println(hu.smSleepData(hu.eWakeDuration));

Et avec la constante eDeepSleepDuration, la fonction suit la durée du sommeil profond.

Serial.print("Deep sleep duration: ");
Serial.println(hu.smSleepData(hu.eDeepSleepDuration));

Le score de qualité du sommeil est une métrique calculée basée sur le mouvement, la stabilité de la respiration et les phases de sommeil.

Serial.print("Sleep quality score: ");
Serial.println(hu.smSleepData(hu.eSleepQuality));

Données composites du sommeil

Ensuite, le code récupère un ensemble structuré de données avec plusieurs paramètres.

sSleepComposite comprehensiveState = hu.getSleepComposite();

Cette structure combine plusieurs mesures en un seul objet. Elle fournit un instantané de la condition de sommeil actuelle. La valeur presence indique si une personne est présente :

switch (comprehensiveState.presence) {

Ensuite, nous avons la valeur sleepState, qui répète la classification de la phase de sommeil :

switch (comprehensiveState.sleepState) {

La valeur averageRespiration contient la fréquence respiratoire moyenne calculée sur une fenêtre temporelle :

Serial.print("\tAverage respiration rate: ");
Serial.println(comprehensiveState.averageRespiration);

Tandis que la valeur averageHeartbeat contient la fréquence cardiaque moyenne :

Serial.print("\tAverage heart rate: ");
Serial.println(comprehensiveState.averageHeartbeat);

La valeur turnoverNumber compte combien de fois la personne change de position pendant le sommeil :

Serial.print("\tNumber of turns: ");
Serial.println(comprehensiveState.turnoverNumber);

Et la valeur largeBodyMove représente la proportion de mouvements importants :

Serial.print("\tProportion of significant body movement: ");
Serial.println(comprehensiveState.largeBodyMove);

tandis que la valeur minorBodyMove indique les mouvements plus petits comme des ajustements légers :

Serial.print("\tProportion of minor body movement: ");
Serial.println(comprehensiveState.minorBodyMove);

Enfin, nous avons apneaEvents, qui compte les événements d’apnée détectés (pauses respiratoires) :

Serial.print("\tNumber of apneas: ");
Serial.println(comprehensiveState.apneaEvents);

Anomalies du sommeil

Le code vérifie les conditions anormales du sommeil.

Serial.print("Sleep abnormalities:");
switch (hu.smSleepData(hu.eSleepDisturbances)) {

Le capteur signale des états anormaux prédéfinis.

case 0:
  Serial.println("Sleep duration less than 4 hours"); break;
case 1:
  Serial.println("Sleep duration more than 12 hours"); break;
case 2:
  Serial.println("Long time abnormal absence of person"); break;
case 3:
  Serial.println("None"); break;

Ces conditions sont basées sur des seuils définis dans le firmware.

Statistiques du sommeil

Le code récupère des statistiques à long terme pour toute la période de surveillance. La structure suivante fournit des données agrégées, typiquement sur une nuit complète.

sSleepStatistics statistics = hu.getSleepStatistics();

Par exemple, voici le score global de qualité du sommeil.

Serial.print("\tSleep quality score: ");
Serial.println(statistics.sleepQualityScore);

Et cette valeur représente la proportion de temps passé éveillé.

Serial.print("\tProportion of awake time: ");
Serial.println(statistics.sleepTime);

Ensuite, nous avons un indicateur pour le pourcentage de temps en sommeil profond.

Serial.print("\tProportion of light sleep time: ");
Serial.println(statistics.shallowSleepPercentage);

Et cette valeur indique le pourcentage de sommeil profond.

Serial.print("\tProportion of deep sleep time: ");
Serial.println(statistics.deepSleepPercentage);

« timeOutOfBed » suit la durée pendant laquelle la personne était hors du lit.

Serial.print("\tOut of bed duration: ");
Serial.println(statistics.timeOutOfBed);

et « exitCount » compte combien de fois la personne a quitté le lit.

Serial.print("\tNumber of times out of bed: ");
Serial.println(statistics.exitCount);

Nous obtenons aussi les mesures du nombre total de rotations corporelles

Serial.print("\tNumber of turns: ");
Serial.println(statistics.turnOverCount);

la fréquence respiratoire moyenne sur la période de surveillance

Serial.print("\tAverage respiration: ");
Serial.println(statistics.averageRespiration);

et la fréquence cardiaque moyenne :

Serial.print("\tAverage heartbeat: ");
Serial.println(statistics.averageHeartbeat);

Évaluation de la qualité du sommeil

Le capteur fournit une classification simplifiée de la qualité du sommeil.

Serial.print("Sleep quality rating: ");
switch (hu.smSleepData(hu.eSleepQualityRating)) {

case 1:
  Serial.println("Good sleep quality"); break;
case 2:
  Serial.println("Average sleep quality"); break;
case 3:
  Serial.println("Poor sleep quality"); break;

Cette évaluation est dérivée des métriques détaillées et fournit un résultat facile à interpréter.

Détection de lutte anormale

La dernière section détecte des schémas de mouvement inhabituels.

Serial.print("Abnormal struggle status: ");
switch (hu.smSleepData(hu.eAbnormalStruggle)) {

case 0:
  Serial.println("None"); break;
case 1:
  Serial.println("Normal status"); break;
case 2:
  Serial.println("Abnormal struggle status"); break;

Cette fonction identifie des mouvements irréguliers ou intenses qui peuvent indiquer un inconfort ou une détresse pendant le sommeil.

Temporisation de la boucle

La boucle se termine par un délai et un séparateur, comme dans les exemples précédents. L’intervalle d’une seconde assure un taux de mise à jour stable tout en permettant au capteur d’accumuler des données significatives entre les lectures.

Conclusions

Dans ce tutoriel, vous avez appris comment connecter le capteur mmWave C1001 à un Arduino ou un ESP32 pour mesurer les signes vitaux, détecter les chutes et surveiller la qualité du sommeil. Notez que le capteur C1001 n’est pas un dispositif médical certifié et ne doit pas être utilisé pour des diagnostics ou traitements médicaux !

Pour plus d’informations sur l’installation du capteur, sa portée et sa précision, consultez l’article Functional Test Report of DFRobot C1001 mmWave Sensor. Jetez aussi un œil à la page Wiki et au code repo.

Si vous avez seulement besoin de détection de présence, consultez nos tutoriels pour les capteurs mmWave C4001 et mmWave C4002. Ce sont aussi des capteurs radar mais sans fonctions intégrées pour la détection de chute ou la surveillance du sommeil.

Si vous avez des questions, n’hésitez pas à les poser dans la section commentaires.

Bon bricolage ; )