Il sensore interno di rilevamento cadute C1001 a onde millimetriche da 60 GHz è un modulo radar compatto progettato per il monitoraggio della presenza umana e della sicurezza. Opera nella banda delle onde millimetriche a 60 GHz e può rilevare movimenti, posture e persino movimenti corporei molto piccoli come la respirazione.
A differenza dei tradizionali sistemi PIR o basati su telecamere, questo sensore utilizza segnali radar per analizzare le onde riflesse dal corpo umano. Ciò gli consente di rilevare sia il movimento che l’immobilità, inclusi i casi in cui una persona è caduta e rimane immobile. Funziona anche al buio completo e non cattura immagini, rendendolo adatto ad ambienti interni sensibili alla privacy.
Il modulo include algoritmi integrati per il rilevamento delle cadute, il monitoraggio del sonno, il rilevamento della presenza e misurazioni di base dei segni vitali. Può misurare la respirazione e il battito cardiaco a breve distanza e rilevare l’attività umana fino a circa 11 metri. I risultati elaborati vengono inviati direttamente tramite un’interfaccia seriale, quindi non è necessaria una complessa elaborazione del segnale sul microcontrollore.
In questo tutorial imparerai come collegare il sensore mmWave C4002 a un Arduino o a un ESP32 per misurare i segni vitali, rilevare cadute e monitorare la qualità del sonno.
Parti necessarie
Puoi acquistare il sensore mmWave C1001 su DFRobot o Amazon. Ti serviranno anche un Arduino, ESP8266 o un ESP32. In questo tutorial uso un Arduino UNO e un ESP32-C3 SuperMini, ma qualsiasi altro Arduino, ESP32 o ESP8266 funzionerà purché abbia un pin di uscita a 5V. Infine, una breadboard e alcuni cavi Dupont per i collegamenti saranno utili.

Sensore mmWave C1001

ESP32-C3 SuperMini

Cavo USB C

Arduino Uno

Cavo USB per Arduino UNO

Set di cavi Dupont

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.
Hardware del sensore mmWave C1001
Il sensore C1001 si basa su un front-end radar a onde millimetriche da 60 GHz. Opera nella gamma di frequenza approssimativa da 61 a 61,5 GHz e trasmette onde elettromagnetiche a bassa potenza nell’ambiente. Il segnale trasmesso viene riflesso da oggetti e corpi umani, e il sensore analizza il segnale di ritorno per estrarre informazioni su movimento e presenza. L’immagine sottostante mostra il retro e il fronte del modulo sensore C1001:

Il radar utilizza un approccio di imaging a nuvola di punti per modellare la posizione e il movimento di un bersaglio umano. Questo metodo permette al sensore di rilevare cambiamenti di postura e movimenti spaziali invece di basarsi solo su semplici trigger di movimento. Di conseguenza, può distinguere con maggiore affidabilità tra posizioni in piedi, in movimento e sdraiate.
Il sensore può anche rilevare micro-movimenti come lo spostamento del torace causato dalla respirazione e dal battito cardiaco. Ciò è possibile perché i segnali a onde millimetriche sono sensibili a variazioni superficiali molto piccole, anche nell’ordine del sub-millimetro.
Portata di rilevamento e campo visivo
Il sensore C1001 supporta una distanza massima di rilevamento fino a 11 metri in condizioni ottimali. Offre un ampio campo visivo con un angolo di copertura approssimativo di 100 gradi sia in orizzontale che in verticale.
Quando usato per il rilevamento delle cadute, il sensore viene tipicamente montato sul soffitto. A un’altezza di installazione di circa 2,7 metri, l’area efficace di rilevamento cadute forma una zona circolare con un diametro di circa 4 metri.

Per il monitoraggio dei segni vitali, la portata di rilevamento è più breve. Le misurazioni di respirazione e battito cardiaco sono più accurate entro una distanza di circa 0,4 a 1,5 metri. Il monitoraggio del sonno può estendersi leggermente oltre, fino a circa 2,5 metri dal sensore.

Elaborazione del segnale e algoritmi integrati
Il C1001 integra l’elaborazione del segnale a bordo e algoritmi di rilevamento. I dati radar grezzi vengono elaborati internamente e l’utente riceve informazioni di alto livello invece di flussi di segnale grezzi. Questo riduce il carico computazionale sul microcontrollore collegato.
Il firmware interno implementa molteplici modalità di rilevamento. Queste includono il rilevamento della presenza umana, il tracciamento del movimento, il rilevamento delle cadute e il monitoraggio del sonno. L’algoritmo di rilevamento cadute analizza le transizioni di postura e identifica cambiamenti improvvisi seguiti da immobilità. Può anche monitorare la durata dell’inattività dopo un evento di caduta.
L’algoritmo di rilevamento dei segni vitali estrae schemi periodici dai segnali riflessi. Calcola i tassi di respirazione tipicamente nell’intervallo di 10-25 respiri al minuto e i battiti cardiaci tra 60 e 100 battiti al minuto.
Caratteristiche elettriche
Il sensore funziona con una tensione di alimentazione di 5 V e consuma tipicamente meno di 100 mA. Questo lo rende adatto per sistemi embedded alimentati da schede di sviluppo standard.
Il trasmettitore radar emette un segnale con un livello di potenza di circa 6 dBm. Ciò garantisce una potenza del segnale sufficiente per il rilevamento indoor mantenendo basso consumo energetico e operazione sicura.
Il dispositivo è progettato per operare in un intervallo di temperatura da −20 °C a 60 °C. Questo consente un funzionamento stabile in ambienti interni tipici e in molte applicazioni semi-industriali.
Interfaccia e uscita dati
Il C1001 comunica tramite un’interfaccia seriale UART. Fornisce frame di dati elaborati che includono stati di rilevamento come presenza, stato di caduta e informazioni sui segni vitali.
L’alimentazione (5V) avviene tramite i pin VIN e GND, mentre i pin TX e RX sono usati per la comunicazione seriale con un microcontrollore. Due pin digitali ausiliari etichettati IO1 e IO2 sono progettati per segnalare eventi di caduta e presenza umana. La foto sottostante mostra il pinout del modulo C1001:

Nota che non sono riuscito a far funzionare IO1 o IO2. Non ho trovato una funzione nella libreria per attivare questi pin di uscita e di default sembrano non essere attivi.
Vincoli di installazione e funzionamento
Il sensore richiede un buon posizionamento per ottenere prestazioni ottimali. Per il rilevamento delle cadute, si raccomanda una configurazione montata in alto. Il fascio radar forma un’area di copertura tridimensionale e ostacoli o oggetti in movimento possono influenzare la qualità del segnale.
L’accuratezza del rilevamento dei segni vitali dipende da distanza, orientamento e stabilità ambientale. Fonti di movimento esterne come ventilatori o tende possono introdurre rumore nel segnale riflesso.
A causa della natura del rilevamento radar, il modulo funziona in modo consistente in ambienti con scarsa illuminazione o completamente bui. Non è influenzato dalle condizioni di luce ambientale e non si basa su sensori ottici.
Specifiche tecniche
La tabella seguente riassume le specifiche tecniche del sensore mmWave C1001:
| Parametro | Valore / Descrizione |
|---|---|
| Frequenza operativa | 60 GHz mmWave (circa 61–61,5 GHz) |
| Tecnologia di rilevamento | Radar FMCW con elaborazione a nuvola di punti |
| Portata di rilevamento | Fino a 11 m (presenza e movimento) |
| Portata rilevamento cadute | Ottimizzato per montaggio a soffitto, area di circa 4 m di diametro |
| Portata rilevamento segni vitali | ~0,4 m a 1,5 m (fino a ~2,5 m per monitoraggio sonno) |
| Campo visivo | ~100° orizzontale e verticale |
| Capacità di rilevamento | Presenza, movimento, rilevamento cadute, monitoraggio sonno |
| Misurazione segni vitali | Respirazione e frequenza cardiaca |
| Intervallo frequenza respiratoria | ~10–25 respiri al minuto |
| Intervallo frequenza cardiaca | ~60–100 bpm |
| Tensione di alimentazione | 5 V |
| Corrente operativa | < 100 mA |
| Potenza di trasmissione | ~6 dBm |
| Interfaccia di comunicazione | UART (livello TTL) |
| Pin di uscita digitale | IO1 (rilevamento caduta), IO2 (rilevamento presenza) |
| Livello logico | 3,3 V |
| Temperatura operativa | −20 °C a 60 °C |
| Metodo di montaggio | Montaggio a soffitto o parete (preferito soffitto per rilevamento cadute) |
| Uscita dati | Dati elaborati (non necessari dati radar grezzi) |
| Piattaforme supportate | Arduino, ESP32, ESP8266 |
Collegare il sensore mmWave C1001 ad Arduino
Collegare il sensore mmWave C1001 a un Arduino UNO è semplice. Inizia collegando VIN al 5V dell’Arduino. Poi collega GND a GND. Infine, collega l’interfaccia UART cablando RX a GPIO 5 e TX a GPIO 4. L’immagine sottostante mostra il cablaggio completo:

Per comodità, ecco una tabella con i collegamenti da effettuare:
| C1001 | Arduino Uno |
|---|---|
| VIN | 5V |
| GND | GND |
| RX | GPIO 5 |
| TX | GPIO 4 |
Collegare il sensore mmWave C1001 a ESP32
L’ESP32 ha tre interfacce seriali e puoi configurare i pin e l’interfaccia che vuoi usare. Qui collego TX a GPIO 3 e RX a GPIO 4. Dovremo ricordarlo quando scriviamo il codice. Infine, colleghiamo VIN a 5V e GND a G. L’immagine sottostante mostra il cablaggio completo:

Nota che ti serve un ESP32 con un pin di uscita a 5V e che devi collegare VIN del C1001 al pin 5V e non al comune pin da 3,3V! L’immagine sottostante mostra il pinout dell’ESP32-C3 Supermini che sto usando qui.

Per comodità, ecco una tabella con i collegamenti da effettuare.
| C1001 | ESP32-C3 Supermini |
|---|---|
| VIN | 5V |
| GND | G |
| RX | 4 |
| TX | 3 |
Installazione della libreria DFRobot_HumanDetection
Prima di poter scrivere codice, dobbiamo installare la DFRobot_HumanDetection libreria. Per installarla vai al DFRobot_HumanDetection repository, clicca sul pulsante verde “<> Code” e poi su “Download ZIP” per scaricare la libreria come file ZIP come mostrato sotto:

Poi crea un nuovo sketch Arduino, vai su Sketch -> Include Library -> Add .ZIP Library … per installare la libreria ZIP scaricata (DFRobot_HumanDetection-master.zip):

Codice: Misurazione dei segni vitali
Il seguente esempio di codice mostra come misurare i segni vitali come frequenza cardiaca e respiratoria con il sensore C1001. Ho leggermente modificato il codice originale della basic.ino nel repository github rimuovendo alcune stampe e aggiungendo supporto per microcontrollori Arduino e ESP866 oltre all’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);
}
Importazioni
Il codice inizia includendo la libreria necessaria per il sensore. La DFRobot_HumanDetection libreria fornisce tutte le funzioni necessarie per comunicare con il sensore mmWave C1001 e accedere ai dati elaborati.
#include "DFRobot_HumanDetection.h"
Questa libreria astrae il protocollo UART a basso livello. Permette di lavorare con funzioni di alto livello come il rilevamento della presenza, lo stato del movimento e i segni vitali.
Configurazione seriale specifica per scheda
Il codice configura poi l’interfaccia seriale a seconda della scheda target. Il sensore C1001 comunica via UART, quindi deve essere assegnata una porta seriale.
#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
Per schede come Arduino Uno o ESP8266, viene creata una porta seriale software sui pin 4 e 5. Questo è necessario perché queste schede spesso hanno una sola UART hardware.
Per l’ESP32, il codice usa Serial1, che è una UART hardware. Questo è più affidabile e supporta velocità dati più elevate.
L’oggetto hu viene creato come istanza della classe sensore. Riceve un puntatore all’interfaccia seriale, usata internamente per comunicare con il sensore.
Funzione di setup
La funzione setup() inizializza la comunicazione seriale e prepara il sensore per l’uso.
void setup() {
Serial.begin(115200);
La porta seriale principale viene avviata a 115200 baud. Questa è usata per il debug e per stampare i dati del sensore sul Serial Monitor.
#if defined(ESP32)
Serial1.begin(115200, SERIAL_8N1, 3, 4);
Sull’ESP32, la UART hardware è inizializzata a 115200 baud. La configurazione SERIAL_8N1 significa 8 bit dati, nessuna parità e 1 bit di stop. I pin 3 e 4 sono assegnati come RX e TX. Per altre schede, l’interfaccia seriale software è avviata con la stessa velocità.
#elif defined(ESP8266) || defined(ARDUINO_AVR_UNO)
mySerial.begin(115200);
#endif
Viene stampato un semplice messaggio per indicare che l’inizializzazione è iniziata:
Serial.println("Starting...");
La funzione hu.begin() inizializza la comunicazione con il sensore. Restituisce 0 in caso di successo. Se l’inizializzazione fallisce, il codice stampa un messaggio di errore e riprova ogni secondo. Questo ciclo assicura che il sensore sia pronto prima di continuare:
while (hu.begin() != 0) {
Serial.println("init error!!!");
delay(1000);
}
Configurazione del sensore
Dopo l’inizializzazione, il sensore viene configurato usando funzioni della libreria. Questa riga imposta la modalità di lavoro del sensore. La modalità eSleepMode è ottimizzata per rilevare umani fermi e monitorare segni vitali come respirazione e battito cardiaco.
hu.configWorkMode(hu.eSleepMode);
Questa funzione controlla il LED a bordo. Il parametro eHPLed seleziona il tipo di LED, e 1 lo accende. Può essere utile per il debug o come feedback visivo.
hu.configLEDLight(hu.eHPLed, 1);
Questa funzione resetta il sensore. Un reset è necessario dopo aver cambiato parametri di configurazione per assicurarne l’effetto.
hu.sensorRet();
Funzione loop
La funzione loop() legge continuamente i dati dal sensore e li stampa sul Serial Monitor.
Prima stampiamo un’etichetta per il rilevamento della presenza umana.
void loop() {
Serial.print("Presence : ");
Poi usiamo la funzione smHumanData() per leggere un tipo specifico di dato del sensore. Il parametro eHumanPresence seleziona il rilevamento della presenza.
switch (hu.smHumanData(hu.eHumanPresence)) {
Un valore di ritorno 0 significa che non è stato rilevato nessun umano. Un valore di 1 indica che una persona è presente. Qualsiasi altro valore indica un errore di comunicazione o lettura:
case 0:
Serial.println("No"); break;
case 1:
Serial.println("Yes"); break;
default:
Serial.println("Read error");
Stato del movimento
La sezione successiva legge lo stato del movimento della persona rilevata. Il parametro eHumanMovement seleziona la classificazione del movimento.
Serial.print("Motion : ");
switch (hu.smHumanData(hu.eHumanMovement)) {
Un valore di 0 significa nessun movimento rilevato, un valore di 1 significa che la persona è presente ma ferma e un valore di 2 indica movimento attivo.
case 0:
Serial.println("None"); break;
case 1:
Serial.println("Still"); break;
case 2:
Serial.println("Active"); break;
Intensità del movimento
Il codice stampa poi un valore numerico che rappresenta l’intensità o l’ampiezza del movimento.
Serial.print("Movement : ");
Serial.println(hu.smHumanData(hu.eHumanMovingRange));
Questo valore è utile per stimare quanto la persona si muove nell’area di rilevamento. Valori più alti indicano movimenti più forti o ampi.
Segni vitali
Il sensore può anche misurare respirazione e battito cardiaco. La funzione getBreatheValue() restituisce la frequenza respiratoria in respiri al minuto.
Serial.print("Respiration rate: ");
Serial.println(hu.getBreatheValue());
La funzione getHeartRate() restituisce la frequenza cardiaca in battiti al minuto. Queste misurazioni si basano su micro-movimenti rilevati dal radar.
Serial.print("Heart rate : ");
Serial.println(hu.getHeartRate());
Tempi del loop
Alla fine del loop viene aggiunto un ritardo per controllare la frequenza di aggiornamento.
Serial.println("-----------------------");
delay(1000);
}
Esempio di output
L’immagine seguente mostra un esempio di output del codice. Nota che ci vogliono diversi minuti prima che appaiano le misurazioni di respirazione e battito cardiaco. Il sensore ha bisogno di tempo per stabilizzare le letture.

Misurare respirazione e battito cardiaco senza contatto e fino a 1,5 metri di distanza è impressionante. Nota però che l’accuratezza è limitata. Vedi il Functional Test Report of DFRobot C1001 mmWave Sensor articolo per maggiori informazioni sulle condizioni di misurazione, affidabilità e precisione.
Codice: Rilevamento cadute
Il codice seguente dimostra come eseguire il rilevamento cadute con il sensore C1001. Come prima, è una versione leggermente modificata del codice fall.ino nel repository github della libreria DFRobot_HumanDetection. Supporta microcontrollori Arduino, ESP866 e 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);
}
Importazioni e inizializzazione oggetto
L’inclusione della libreria e la creazione dell’oggetto sono identiche all’esempio precedente. Viene usata la stessa libreria DFRobot_HumanDetection e l’oggetto sensore hu è inizializzato con un’interfaccia seriale hardware o software a seconda della scheda.
La configurazione UART e l’impostazione della comunicazione seguono la stessa struttura di prima. Puoi fare riferimento alla spiegazione precedente per i dettagli sull’inizializzazione seriale e la costruzione dell’oggetto.
Funzione di setup
La sequenza di inizializzazione dentro setup() è anch’essa la stessa. Le interfacce seriali sono avviate e il sensore è inizializzato usando hu.begin(). Il ciclo di retry dell’inizializzazione assicura una comunicazione stabile prima di continuare.
La differenza in questo esempio inizia con la configurazione del sensore. Ora il sensore è esplicitamente configurato per il rilevamento cadute.
Configurazione modalità rilevamento cadute
La modalità di lavoro viene cambiata in una modalità dedicata al rilevamento cadute.
hu.configWorkMode(hu.eFallingMode);
Questo commuta il firmware interno per usare algoritmi di rilevamento cadute invece di monitoraggio generale della presenza o del sonno. Il sensore ora si concentra su cambiamenti di postura e movimenti improvvisi seguiti da inattività.
Configurazione LED
Due indicatori LED sono configurati per feedback visivo.
hu.configLEDLight(hu.eFALLLed, 1); hu.configLEDLight(hu.eHPLed, 1);
Il eFALLLed controlla il LED che indica un evento di caduta rilevato. Il eHPLed controlla il LED di rilevamento presenza. Impostando entrambi a 1 li abilita.
Questi LED sono pilotati dalla logica interna di rilevamento e possono aiutare durante test e calibrazione.
Altezza di installazione
L’altezza di installazione è un parametro critico per un rilevamento cadute accurato. La seguente chiamata di funzione imposta l’altezza di montaggio del sensore a 270 cm. Il valore deve corrispondere all’altezza reale perché l’elaborazione radar dipende dalla geometria.
hu.dmInstallHeight(270);
Valori di altezza errati possono portare a stime di posizione inaccurate e falsi rilevamenti.
Tempi di rilevamento cadute
Il sensore include un ritardo configurabile prima di confermare un evento di caduta. La seguente chiamata imposta un ritardo di 5 secondi. Dopo aver rilevato una potenziale caduta, il sensore attende questo tempo prima di segnalarla come caduta valida.
hu.dmFallTime(5);
Questo aiuta a filtrare movimenti brevi o non critici che altrimenti potrebbero causare falsi positivi.
Ritardo rilevamento assenza persona
Il sensore ritarda anche la segnalazione quando non è presente nessuna persona. La seguente funzione imposta un ritardo di 1 secondo prima di passare allo stato “nessuna persona”.
hu.dmUnmannedTime(1);
Questo previene commutazioni rapide quando una persona lascia brevemente o si muove al bordo della zona di rilevamento.
Rilevamento immobilità prolungata
Il sensore può rilevare quando una persona rimane ferma a lungo. La seguente chiamata imposta il tempo di permanenza a 200 secondi.
hu.dmFallConfig(hu.eResidenceTime, 200);
Se una persona rimane immobile nell’area di rilevamento per più a lungo di questo periodo, il sensore segnala uno stato di immobilità.
Questa funzione è utile negli scenari di rilevamento cadute perché una persona sdraiata immobile dopo una caduta può essere identificata.
Sensibilità caduta
La sensibilità dell’algoritmo di rilevamento cadute può essere regolata. Qui la sensibilità è impostata al livello 3, che è il valore più alto.
hu.dmFallConfig(hu.eFallSensitivityC, 3);
Una sensibilità più alta aumenta la probabilità di rilevare cadute ma può anche aumentare i falsi positivi. Valori più bassi riducono la sensibilità e richiedono cambiamenti di movimento più marcati.
Applicazione della configurazione
Dopo aver impostato tutti i parametri, il sensore viene resettato.
hu.sensorRet();
Come spiegato prima, questo passaggio è necessario affinché la nuova configurazione abbia effetto. Il sensore si riavvia con i parametri aggiornati.
Funzione loop
Il loop legge continuamente i dati relativi alle cadute dal sensore. A differenza dell’esempio precedente, questo codice usa getFallData() invece di smHumanData().
Rilevamento stato caduta
La funzione getFallData() recupera i risultati elaborati del rilevamento cadute. Il parametro eFallState seleziona lo stato di caduta:
Serial.print("Fallen : ");
switch (hu.getFallData(hu.eFallState)) {
Un valore di 0 significa che non è stata rilevata alcuna caduta, e un valore di 1 indica che un evento di caduta è stato confermato dal sensore:
case 0:
Serial.println("No"); break;
case 1:
Serial.println("Yes"); break;
Rilevamento stato immobilità
La costante estaticResidencyState è usata per recuperare lo stato di immobilità prolungata:
Serial.print("Stationary: ");
switch (hu.getFallData(hu.estaticResidencyState)) {
Un valore di 1 significa che una persona è rimasta ferma più a lungo del tempo di permanenza configurato. Questo può indicare una situazione critica, specialmente se combinato con una caduta rilevata.
case 0:
Serial.println("No"); break;
case 1:
Serial.println("Yes"); break;
Tempi del loop
Il loop termina con un ritardo e un separatore per la leggibilità.
Serial.println("-----------------");
delay(1000);
Codice: Monitoraggio del sonno
In questo ultimo esempio di codice eseguiamo il monitoraggio del sonno con il sensore C1001. Il codice si basa sull’esempio sleep.ino nella libreria DFRobot_HumanDetection. Ho solo aggiunto il supporto per microcontrollori Arduino e 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);
}
Importazioni e inizializzazione oggetto
L’inclusione della libreria e la creazione dell’oggetto sono identiche agli esempi precedenti. Viene usata la stessa classe DFRobot_HumanDetection e il sensore è collegato tramite un’interfaccia UART. L’oggetto hu gestisce tutta la comunicazione e l’elaborazione dei dati.
La configurazione seriale per ESP32, ESP8266 e Arduino Uno è invariata. Consulta le spiegazioni precedenti per i dettagli su come viene inizializzata l’interfaccia UART e perché si preferisce la seriale hardware su ESP32.
Funzione di setup
La sequenza di inizializzazione in setup() segue lo stesso schema di prima. Le porte seriali sono avviate e il sensore è inizializzato usando hu.begin() con un ciclo di retry per garantire una comunicazione stabile.
La differenza principale è la modalità di lavoro selezionata. In questo esempio il sensore è configurato per il monitoraggio del sonno invece che per il rilevamento cadute.
hu.configWorkMode(hu.eSleepMode);
Questa modalità abilita algoritmi per rilevare la presenza a letto, le fasi del sonno e i segni vitali come respirazione e battito cardiaco nel tempo.
hu.configLEDLight(hu.eHPLed, 1);
Il LED di presenza è abilitato, fornendo un feedback visivo quando una persona è rilevata.
hu.sensorRet();
Come spiegato prima, il sensore deve essere resettato dopo modifiche di configurazione affinché i nuovi parametri abbiano effetto.
Panoramica funzione loop
La funzione loop() legge continuamente i dati relativi al sonno dal sensore. A differenza degli esempi precedenti, questo codice usa smSleepData() e strutture dati composite aggiuntive per accedere a metriche più avanzate.
L’output è più complesso perché il sensore aggrega e analizza i dati nel tempo.
Rilevamento ingresso a letto
La prima sezione verifica se una persona è a letto.
Serial.print("Bed entry status:");
switch (hu.smSleepData(hu.eInOrNotInBed)) {
La funzione smSleepData() funziona in modo simile a smHumanData(), ma accede a parametri relativi al sonno.
case 0:
Serial.println("Out of bed"); break;
case 1:
Serial.println("In bed"); break;
Un valore di 1 indica che una persona è rilevata nell’area del letto. Questo è determinato usando il rilevamento della presenza combinato con l’analisi della posizione.
Rilevamento stato del sonno
La sezione successiva legge la fase attuale del sonno.
Serial.print("Sleep status:");
switch (hu.smSleepData(hu.eSleepState)) {
Il sensore classifica il sonno in più fasi.
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;
Questi stati sono derivati da schemi di movimento e variazioni dei segni vitali. Il sonno profondo è caratterizzato da movimento minimo e respirazione stabile, mentre gli stati di veglia mostrano più attività.
Tempi e metriche di qualità del sonno
Il sensore fornisce metriche di durata e qualità come valori numerici.
Con la costante eWakeDuration la funzione restituisce quanto tempo la persona è stata sveglia durante il periodo di monitoraggio.
Serial.print("Awake duration: ");
Serial.println(hu.smSleepData(hu.eWakeDuration));
Con la costante eDeepSleepDuration la funzione traccia la durata del sonno profondo.
Serial.print("Deep sleep duration: ");
Serial.println(hu.smSleepData(hu.eDeepSleepDuration));
Il punteggio di qualità del sonno è una metrica calcolata basata su movimento, stabilità della respirazione e fasi del sonno.
Serial.print("Sleep quality score: ");
Serial.println(hu.smSleepData(hu.eSleepQuality));
Dati compositi sul sonno
Successivamente il codice recupera un dataset strutturato con più parametri.
sSleepComposite comprehensiveState = hu.getSleepComposite();
Questa struttura combina diverse misurazioni in un unico oggetto. Fornisce un’istantanea della condizione attuale del sonno. Il valore presence indica se una persona è presente:
switch (comprehensiveState.presence) {
Segue il valore sleepState, che ripete la classificazione della fase del sonno:
switch (comprehensiveState.sleepState) {
Il valore averageRespiration contiene la frequenza respiratoria media calcolata su una finestra temporale:
Serial.print("\tAverage respiration rate: ");
Serial.println(comprehensiveState.averageRespiration);
Il valore averageHeartbeat contiene la frequenza cardiaca media:
Serial.print("\tAverage heart rate: ");
Serial.println(comprehensiveState.averageHeartbeat);
Il valore turnoverNumber conta quante volte la persona cambia posizione durante il sonno:
Serial.print("\tNumber of turns: ");
Serial.println(comprehensiveState.turnoverNumber);
Il valore largeBodyMove rappresenta la proporzione di movimenti ampi:
Serial.print("\tProportion of significant body movement: ");
Serial.println(comprehensiveState.largeBodyMove);
mentre il valore minorBodyMove indica movimenti più piccoli come piccoli aggiustamenti:
Serial.print("\tProportion of minor body movement: ");
Serial.println(comprehensiveState.minorBodyMove);
Infine, abbiamo apneaEvents, che conta gli eventi di apnea rilevati (pause nella respirazione):
Serial.print("\tNumber of apneas: ");
Serial.println(comprehensiveState.apneaEvents);
Anomalie del sonno
Il codice verifica condizioni anomale del sonno.
Serial.print("Sleep abnormalities:");
switch (hu.smSleepData(hu.eSleepDisturbances)) {
Il sensore segnala stati anomali predefiniti.
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;
Queste condizioni si basano su soglie definite nel firmware.
Statistiche sul sonno
Il codice recupera statistiche a lungo termine per l’intero periodo di monitoraggio. La seguente struttura fornisce dati aggregati, tipicamente su una notte intera.
sSleepStatistics statistics = hu.getSleepStatistics();
Ad esempio, questo è il punteggio complessivo di qualità del sonno.
Serial.print("\tSleep quality score: ");
Serial.println(statistics.sleepQualityScore);
Questo valore rappresenta la proporzione di tempo trascorso svegli.
Serial.print("\tProportion of awake time: ");
Serial.println(statistics.sleepTime);
Segue un indicatore per la percentuale di tempo di sonno profondo.
Serial.print("\tProportion of light sleep time: ");
Serial.println(statistics.shallowSleepPercentage);
E questo valore indica la percentuale di sonno profondo.
Serial.print("\tProportion of deep sleep time: ");
Serial.println(statistics.deepSleepPercentage);
“timeOutOfBed” traccia quanto tempo la persona è stata fuori dal letto.
Serial.print("\tOut of bed duration: ");
Serial.println(statistics.timeOutOfBed);
e “exitCount” conta quante volte la persona ha lasciato il letto.
Serial.print("\tNumber of times out of bed: ");
Serial.println(statistics.exitCount);
Otteniamo anche misurazioni per il numero totale di rotazioni del corpo
Serial.print("\tNumber of turns: ");
Serial.println(statistics.turnOverCount);
la frequenza respiratoria media durante il periodo di monitoraggio
Serial.print("\tAverage respiration: ");
Serial.println(statistics.averageRespiration);
e la frequenza cardiaca media:
Serial.print("\tAverage heartbeat: ");
Serial.println(statistics.averageHeartbeat);
Valutazione della qualità del sonno
Il sensore fornisce una classificazione semplificata della qualità del sonno.
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;
Questa valutazione deriva dalle metriche dettagliate e fornisce un risultato facile da interpretare.
Rilevamento di movimenti anomali
L’ultima sezione rileva schemi di movimento insoliti.
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;
Questa funzione identifica movimenti irregolari o intensi che possono indicare disagio o stress durante il sonno.
Tempi del loop
Il loop termina con un ritardo e un separatore, simile agli esempi precedenti. L’intervallo di un secondo fornisce un aggiornamento costante permettendo al sensore di accumulare dati significativi tra una lettura e l’altra.
Conclusioni
In questo tutorial hai imparato come collegare il sensore mmWave C1001 a un Arduino o a un ESP32 per misurare i segni vitali, rilevare cadute e monitorare la qualità del sonno. Nota che il sensore C1001 non è un dispositivo medico certificato e non deve essere usato per diagnosi o trattamenti medici!
Per maggiori informazioni su come installare il sensore, la sua portata e precisione, vedi l’articolo Functional Test Report of DFRobot C1001 mmWave Sensor. Dai anche un’occhiata alla pagina Wiki e al codice repo.
Se ti serve solo il rilevamento della presenza, consulta i nostri tutorial per i sensori mmWave C4001 e mmWave C4002. Questi sono anch’essi sensori radar ma non hanno funzioni integrate per il rilevamento cadute o il monitoraggio del sonno.
Se hai domande, sentiti libero di lasciarle nella sezione commenti.
Buon divertimento con il tinkering ; )

