El sensor de detección de caídas en interiores C1001 de 60 GHz mmWave es un módulo de radar compacto diseñado para la monitorización de presencia humana y seguridad. Opera en la banda de ondas milimétricas de 60 GHz y puede detectar movimiento, postura e incluso movimientos corporales muy pequeños como la respiración.
A diferencia de los sistemas tradicionales basados en PIR o cámaras, este sensor utiliza señales de radar para analizar las ondas reflejadas por el cuerpo humano. Esto le permite detectar tanto movimiento como inmovilidad, incluyendo casos en los que una persona ha caído y permanece inmóvil. También funciona en completa oscuridad y no captura imágenes, lo que lo hace adecuado para entornos interiores sensibles a la privacidad.
El módulo incluye algoritmos integrados para detección de caídas, monitorización del sueño, detección de presencia y mediciones básicas de signos vitales. Puede medir la respiración y el pulso a corta distancia y detectar actividad humana hasta aproximadamente 11 metros. Los resultados procesados se envían directamente a través de una interfaz serial, por lo que no se requiere procesamiento complejo en el microcontrolador.
En este tutorial aprenderás cómo conectar el sensor mmWave C4002 a un Arduino o un ESP32 para medir signos vitales, detectar caídas y monitorizar la calidad del sueño.
Piezas necesarias
Puedes conseguir el sensor mmWave C1001 en DFRobot o Amazon. También necesitarás un Arduino, ESP8266 o un ESP32. En este tutorial uso un Arduino UNO y un ESP32-C3 SuperMini, pero cualquier otro Arduino, ESP32 o ESP8266 funcionará siempre que tenga un pin de salida de 5V. Finalmente, una protoboard y algunos cables Dupont para las conexiones serán útiles.

Sensor mmWave C1001

ESP32-C3 SuperMini

Cable USB C

Arduino Uno

Cable USB para Arduino UNO

Set de cables Dupont

Protoboard
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 sensor mmWave C1001
El sensor C1001 está basado en un radar de ondas milimétricas de 60 GHz. Opera en un rango de frecuencia aproximado de 61 a 61.5 GHz y transmite ondas electromagnéticas de baja potencia al entorno. La señal transmitida se refleja en objetos y cuerpos humanos, y el sensor analiza la señal retornada para extraer información de movimiento y presencia. La imagen a continuación muestra la parte trasera y frontal del módulo sensor C1001:

El radar utiliza un enfoque de imagen de nube de puntos para modelar la posición y el movimiento de un objetivo humano. Este método permite al sensor detectar cambios de postura y movimiento espacial en lugar de depender solo de disparadores simples de movimiento. Como resultado, puede distinguir con mayor fiabilidad entre posiciones de pie, en movimiento y acostado.
El sensor también puede detectar micro-movimientos como el desplazamiento del pecho causado por la respiración y el latido del corazón. Esto es posible porque las señales de ondas milimétricas son sensibles a cambios muy pequeños en la superficie, incluso en el rango submilimétrico.
Alcance de detección y campo de visión
El sensor C1001 soporta una distancia máxima de detección de hasta 11 metros en condiciones óptimas. Proporciona un amplio campo de visión con un ángulo de cobertura aproximado de 100 grados tanto en dirección horizontal como vertical.
Cuando se usa para detección de caídas, el sensor se monta típicamente en el techo. A una altura de instalación de alrededor de 2.7 metros, el área efectiva de detección de caídas forma una zona circular con un diámetro de aproximadamente 4 metros.

Para la monitorización de signos vitales, el rango de detección es más corto. Las mediciones de respiración y pulso son más precisas dentro de una distancia de aproximadamente 0.4 a 1.5 metros. La monitorización del sueño puede extenderse un poco más, hasta aproximadamente 2.5 metros desde el sensor.

Procesamiento de señal y algoritmos integrados
El C1001 integra procesamiento de señal y algoritmos de detección a bordo. Los datos brutos del radar se procesan internamente, y el usuario recibe información de alto nivel en lugar de flujos de señal sin procesar. Esto reduce la carga computacional en el microcontrolador conectado.
El firmware interno implementa múltiples modos de detección. Estos incluyen detección de presencia humana, seguimiento de movimiento, detección de caídas y monitorización del sueño. El algoritmo de detección de caídas analiza transiciones de postura e identifica cambios súbitos seguidos de inmovilidad. También puede rastrear la duración de la inactividad tras un evento de caída.
El algoritmo de detección de signos vitales extrae patrones periódicos de las señales reflejadas. Calcula tasas de respiración típicamente en el rango de 10 a 25 respiraciones por minuto y frecuencias cardíacas entre 60 y 100 latidos por minuto.
Características eléctricas
El sensor opera con un voltaje de alimentación de 5 V y consume típicamente menos de 100 mA. Esto lo hace adecuado para sistemas embebidos alimentados por placas de desarrollo estándar.
El transmisor del radar emite una señal con un nivel de potencia de aproximadamente 6 dBm. Esto asegura una fuerza de señal suficiente para detección en interiores manteniendo bajo consumo y operación segura.
El dispositivo está diseñado para operar en un rango de temperatura de −20 °C a 60 °C. Esto permite una operación estable en entornos interiores típicos y muchas aplicaciones semi-industriales.
Interfaz y salida de datos
El C1001 se comunica a través de una interfaz serial UART. Proporciona tramas de datos procesados que incluyen estados de detección como presencia, estado de caída e información de signos vitales.
La alimentación (5V) se realiza a través de los pines VIN y GND, mientras que los pines TX y RX se usan para la comunicación serial con un microcontrolador. Dos pines digitales auxiliares etiquetados IO1 e IO2 están diseñados para reportar eventos de caída y presencia humana. La foto a continuación muestra el pinout del módulo C1001:

Ten en cuenta que no pude hacer funcionar IO1 ni IO2. No encontré una función en la biblioteca para activar estos pines de salida y por defecto parecen no estar activos.
Restricciones de instalación y operación
El sensor requiere una buena posición para lograr un rendimiento óptimo. Para detección de caídas, se recomienda una configuración montada en el techo. El haz del radar forma un área de cobertura tridimensional, y obstáculos u objetos en movimiento pueden afectar la calidad de la señal.
La precisión de la detección de signos vitales depende de la distancia, orientación y estabilidad ambiental. Fuentes externas de movimiento como ventiladores o cortinas pueden introducir ruido en la señal reflejada.
Debido a la naturaleza del radar, el módulo funciona consistentemente en ambientes con poca luz o completamente oscuros. No se ve afectado por las condiciones de luz ambiental y no depende de sensores ópticos.
Especificaciones técnicas
La siguiente tabla resume las especificaciones técnicas del sensor mmWave C1001:
| Parámetro | Valor / Descripción |
|---|---|
| Frecuencia de operación | 60 GHz mmWave (aprox. 61–61.5 GHz) |
| Tecnología de detección | Radar FMCW con procesamiento de nube de puntos |
| Rango de detección | Hasta 11 m (presencia y movimiento) |
| Rango de detección de caídas | Optimizado para montaje en techo, área de ~4 m de diámetro |
| Rango de detección de signos vitales | ~0.4 m a 1.5 m (hasta ~2.5 m para monitorización del sueño) |
| Campo de visión | ~100° horizontal y vertical |
| Capacidades de detección | Presencia, movimiento, detección de caídas, monitorización del sueño |
| Medición de signos vitales | Respiración y frecuencia cardíaca |
| Rango de tasa de respiración | ~10–25 respiraciones por minuto |
| Rango de frecuencia cardíaca | ~60–100 lpm |
| Voltaje de alimentación | 5 V |
| Corriente de operación | < 100 mA |
| Potencia de transmisión | ~6 dBm |
| Interfaz de comunicación | UART (nivel TTL) |
| Pines de salida digital | IO1 (detección de caída), IO2 (detección de presencia) |
| Nivel lógico | 3.3 V |
| Temperatura de operación | −20 °C a 60 °C |
| Método de montaje | Montaje en techo o pared (preferible techo para detección de caídas) |
| Salida de datos | Datos procesados (no se requieren datos brutos de radar) |
| Plataformas soportadas | Arduino, ESP32, ESP8266 |
Conexión del sensor mmWave C1001 a Arduino
Conectar el sensor mmWave C1001 a un Arduino UNO es sencillo. Comienza conectando VIN al 5V del Arduino. Luego conecta GND a GND. Finalmente, conecta la interfaz UART cableando RX a GPIO 5 y TX a GPIO 4. La imagen a continuación muestra el cableado completo:

Para mayor comodidad, aquí tienes una tabla con las conexiones que debes hacer:
| C1001 | Arduino Uno |
|---|---|
| VIN | 5V |
| GND | GND |
| RX | GPIO 5 |
| TX | GPIO 4 |
Conexión del sensor mmWave C1001 a ESP32
El ESP32 tiene tres interfaces seriales y puedes configurar los pines e interfaz que desees usar. Aquí conecto TX a GPIO 3 y RX a GPIO 4. Debemos recordar esto al escribir el código. Finalmente, conectamos VIN a 5V y GND a G. La imagen a continuación muestra el cableado completo:

Ten en cuenta que necesitas un ESP32 con un pin de salida de 5V y que debes conectar VIN del C1001 al pin de 5V y no al común pin de 3.3V. La imagen a continuación muestra el pinout del ESP32-C3 Supermini que estoy usando aquí.

Para mayor comodidad, aquí tienes una tabla con las conexiones que debes hacer.
| C1001 | ESP32-C3 Supermini |
|---|---|
| VIN | 5V |
| GND | G |
| RX | 4 |
| TX | 3 |
Instalación de la biblioteca DFRobot_HumanDetection
Antes de poder escribir código, necesitaremos instalar la DFRobot_HumanDetection biblioteca. Para instalar esta biblioteca, ve al repositorio DFRobot_HumanDetection, haz clic en el botón verde «<> Code» y luego en «Download ZIP» para descargar la biblioteca como un archivo ZIP, como se muestra a continuación:

Luego crea un nuevo Sketch de Arduino, ve a Sketch -> Include Library -> Add .ZIP Library … para instalar la biblioteca ZIP descargada (DFRobot_HumanDetection-master.zip):

Código: Medición de signos vitales
El siguiente ejemplo de código muestra cómo medir signos vitales como la frecuencia cardíaca y respiratoria con el sensor C1001. Modifiqué ligeramente el código original de la basic.ino en el repositorio github eliminando algunas impresiones y añadiendo soporte para microcontroladores Arduino y ESP866 además del 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);
}
Importaciones
El código comienza incluyendo la biblioteca necesaria para el sensor. La DFRobot_HumanDetection biblioteca proporciona todas las funciones necesarias para comunicarse con el sensor mmWave C1001 y acceder a datos procesados.
#include "DFRobot_HumanDetection.h"
Esta biblioteca abstrae el protocolo UART de bajo nivel. Permite trabajar con funciones de alto nivel como detección de presencia, estado de movimiento y signos vitales.
Configuración serial específica para la placa
Luego el código configura la interfaz serial según la placa objetivo. El sensor C1001 se comunica por UART, por lo que se debe asignar un puerto serial.
#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
Para placas como Arduino Uno o ESP8266, se crea un puerto serial por software en los pines 4 y 5. Esto es necesario porque estas placas suelen tener solo un UART hardware.
Para el ESP32, el código usa Serial1, que es un UART hardware. Esto es más fiable y soporta mayores tasas de datos.
El objeto hu se crea como una instancia de la clase del sensor. Recibe un puntero a la interfaz serial, que se usa internamente para la comunicación con el sensor.
Función Setup
La función setup() inicializa la comunicación serial y prepara el sensor para su operación.
void setup() {
Serial.begin(115200);
El puerto serial principal se inicia a 115200 baudios. Se usa para depuración e impresión de datos del sensor en el Monitor Serial.
#if defined(ESP32)
Serial1.begin(115200, SERIAL_8N1, 3, 4);
En el ESP32, el UART hardware se inicializa con una tasa de 115200 baudios. La configuración SERIAL_8N1 significa 8 bits de datos, sin paridad y 1 bit de parada. Los pines 3 y 4 se asignan como RX y TX. Para otras placas, la interfaz serial por software se inicia con la misma tasa.
#elif defined(ESP8266) || defined(ARDUINO_AVR_UNO)
mySerial.begin(115200);
#endif
Se imprime un mensaje simple para indicar que la inicialización ha comenzado:
Serial.println("Starting...");
La función hu.begin() inicializa la comunicación con el sensor. Devuelve 0 en caso de éxito. Si la inicialización falla, el código imprime un mensaje de error y reintenta cada segundo. Este bucle asegura que el sensor esté listo antes de continuar:
while (hu.begin() != 0) {
Serial.println("init error!!!");
delay(1000);
}
Configuración del sensor
Después de la inicialización, el sensor se configura usando funciones de la biblioteca. Esta línea establece el modo de trabajo del sensor. El modo eSleepMode está optimizado para detectar humanos estacionarios y monitorizar signos vitales como respiración y frecuencia cardíaca.
hu.configWorkMode(hu.eSleepMode);
Esta función controla el LED integrado. El parámetro eHPLed selecciona el tipo de LED, y 1 lo enciende. Esto puede ser útil para depuración o retroalimentación visual.
hu.configLEDLight(hu.eHPLed, 1);
Y esta función reinicia el sensor. Es necesario un reinicio tras cambiar parámetros de configuración para que tengan efecto.
hu.sensorRet();
Función Loop
La función loop() lee continuamente datos del sensor y los imprime en el Monitor Serial.
Primero imprimimos una etiqueta para la detección de presencia humana.
void loop() {
Serial.print("Presence : ");
Luego usamos la función smHumanData() para leer un tipo específico de dato del sensor. El parámetro eHumanPresence selecciona la detección de presencia.
switch (hu.smHumanData(hu.eHumanPresence)) {
Un valor de 0 significa que no se detecta ninguna persona. Un valor de 1 indica que hay una persona presente. Cualquier otro valor indica un error de comunicación o lectura:
case 0:
Serial.println("No"); break;
case 1:
Serial.println("Yes"); break;
default:
Serial.println("Read error");
Estado de movimiento
La siguiente sección lee el estado de movimiento de la persona detectada. El parámetro eHumanMovement selecciona la clasificación de movimiento.
Serial.print("Motion : ");
switch (hu.smHumanData(hu.eHumanMovement)) {
Un valor de 0 significa que no se detecta movimiento, un valor de 1 indica que la persona está presente pero inmóvil y un valor de 2 indica movimiento activo.
case 0:
Serial.println("None"); break;
case 1:
Serial.println("Still"); break;
case 2:
Serial.println("Active"); break;
Rango de movimiento
Luego el código imprime un valor numérico que representa la intensidad o rango del movimiento.
Serial.print("Movement : ");
Serial.println(hu.smHumanData(hu.eHumanMovingRange));
Este valor es útil para estimar cuánto se mueve la persona dentro del área de detección. Valores más altos indican movimientos más fuertes o amplios.
Signos vitales
El sensor también puede medir la respiración y la frecuencia cardíaca. La función getBreatheValue() devuelve la tasa de respiración en respiraciones por minuto.
Serial.print("Respiration rate: ");
Serial.println(hu.getBreatheValue());
Y la función getHeartRate() devuelve la frecuencia cardíaca en latidos por minuto. Estas mediciones se basan en micro-movimientos detectados por el radar.
Serial.print("Heart rate : ");
Serial.println(hu.getHeartRate());
Temporización del loop
Al final del loop, se añade un retardo para controlar la tasa de actualización.
Serial.println("-----------------------");
delay(1000);
}
Ejemplo de salida
La siguiente imagen muestra un ejemplo de salida del código. Ten en cuenta que pasan varios minutos hasta que aparecen las mediciones de respiración y frecuencia cardíaca. El sensor necesita tiempo para estabilizar las lecturas.

Medir respiración y frecuencia cardíaca sin contacto y a una distancia de hasta 1.5 metros es impresionante. Sin embargo, la precisión es limitada. Consulta el Functional Test Report of DFRobot C1001 mmWave Sensor artículo para más información sobre condiciones de medición, fiabilidad y precisión.
Código: Detección de caídas
El siguiente código demuestra cómo realizar detección de caídas con el sensor C1001. Como antes, es una versión ligeramente modificada del código fall.ino en el repositorio github de la biblioteca DFRobot_HumanDetection. Soporta microcontroladores Arduino, ESP866 y 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);
}
Importaciones e inicialización del objeto
La inclusión de la biblioteca y la creación del objeto son idénticas al ejemplo anterior. Se usa la misma DFRobot_HumanDetection biblioteca, y el objeto sensor hu se inicializa con una interfaz serial hardware o software según la placa.
La configuración UART y la comunicación siguen la misma estructura que antes. Puedes referirte a la explicación previa para detalles sobre la inicialización serial y construcción del objeto.
Función Setup
La secuencia de inicialización dentro de setup() también es la misma. Se inician las interfaces seriales y se inicializa el sensor usando hu.begin(). El bucle que reintenta la inicialización asegura comunicación estable antes de continuar.
La diferencia en este ejemplo comienza con la configuración del sensor. Ahora se configura explícitamente para detección de caídas.
Configuración del modo de detección de caídas
El modo de trabajo se cambia a un modo dedicado a la detección de caídas.
hu.configWorkMode(hu.eFallingMode);
Esto cambia el firmware interno para usar algoritmos de detección de caídas en lugar de presencia general o monitorización del sueño. El sensor ahora se enfoca en cambios de postura y movimientos súbitos seguidos de inactividad.
Configuración de LEDs
Se configuran dos indicadores LED para retroalimentación visual.
hu.configLEDLight(hu.eFALLLed, 1); hu.configLEDLight(hu.eHPLed, 1);
El eFALLLed controla el LED que indica un evento de caída detectado. El eHPLed controla el LED de detección de presencia. Configurar ambos a 1 los habilita.
Estos LEDs son controlados por la lógica interna de detección y pueden ayudar durante pruebas y calibración.
Altura de instalación
La altura de instalación es un parámetro crítico para una detección precisa de caídas. La siguiente llamada de función establece la altura de montaje del sensor a 270 cm. El valor debe coincidir con la altura real de instalación porque el procesamiento del radar depende de la geometría.
hu.dmInstallHeight(270);
Valores incorrectos de altura pueden llevar a estimaciones de posición inexactas y falsas detecciones.
Temporización de detección de caídas
El sensor incluye un retardo configurable antes de confirmar un evento de caída. La siguiente función establece un retardo de 5 segundos. Tras detectar una posible caída, el sensor espera este tiempo antes de reportarla como caída válida.
hu.dmFallTime(5);
Esto ayuda a filtrar movimientos cortos o no críticos que podrían generar falsos positivos.
Retardo de detección sin persona
El sensor también retrasa el reporte cuando no hay persona presente. La siguiente función establece un retardo de 1 segundo antes de cambiar al estado “sin persona”.
hu.dmUnmannedTime(1);
Esto previene cambios rápidos cuando una persona sale brevemente o se mueve en el borde de la zona de detección.
Detección de inmovilidad prolongada
El sensor puede detectar cuando una persona permanece inmóvil por mucho tiempo. La siguiente función establece el tiempo de permanencia en 200 segundos.
hu.dmFallConfig(hu.eResidenceTime, 200);
Si una persona permanece inmóvil dentro del área de detección por más tiempo que este periodo, el sensor reporta un estado estacionario.
Esta función es útil en escenarios de detección de caídas porque permite identificar a una persona acostada e inmóvil tras una caída.
Sensibilidad de detección de caídas
La sensibilidad del algoritmo de detección de caídas puede ajustarse. Aquí se establece en nivel 3, que es el valor más alto.
hu.dmFallConfig(hu.eFallSensitivityC, 3);
Mayor sensibilidad aumenta la probabilidad de detectar caídas pero también puede incrementar falsos positivos. Valores más bajos reducen la sensibilidad y requieren cambios de movimiento más pronunciados.
Aplicación de la configuración
Después de configurar todos los parámetros, el sensor se reinicia.
hu.sensorRet();
Como se explicó antes, este paso es necesario para que la nueva configuración tenga efecto. El sensor se reinicia con los parámetros actualizados.
Función Loop
El loop lee continuamente datos relacionados con caídas del sensor. A diferencia del ejemplo anterior, este código usa getFallData() en lugar de smHumanData().
Detección del estado de caída
La función getFallData() recupera resultados procesados de detección de caídas. El parámetro eFallState selecciona el estado de caída:
Serial.print("Fallen : ");
switch (hu.getFallData(hu.eFallState)) {
Un valor de 0 significa que no se detecta caída, y un valor de 1 indica que el sensor ha confirmado un evento de caída:
case 0:
Serial.println("No"); break;
case 1:
Serial.println("Yes"); break;
Detección de estado estacionario
La constante estaticResidencyState se usa para recuperar el estado de permanencia inmóvil:
Serial.print("Stationary: ");
switch (hu.getFallData(hu.estaticResidencyState)) {
Un valor de 1 significa que una persona ha permanecido inmóvil más tiempo que el configurado. Esto puede indicar una situación crítica, especialmente si se combina con una caída detectada.
case 0:
Serial.println("No"); break;
case 1:
Serial.println("Yes"); break;
Temporización del loop
El loop termina con un retardo y un separador para mejorar la legibilidad.
Serial.println("-----------------");
delay(1000);
Código: Monitorización del sueño
En este último ejemplo de código realizamos monitorización del sueño con el sensor C1001. El código está basado en el ejemplo sleep.ino de la biblioteca DFRobot_HumanDetection. Solo añadí soporte para microcontroladores Arduino y 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);
}
Importaciones e inicialización del objeto
La inclusión de la biblioteca y la creación del objeto son idénticas a los ejemplos anteriores. Se usa la misma clase DFRobot_HumanDetection, y el sensor está conectado mediante una interfaz UART. El objeto hu maneja toda la comunicación y procesamiento de datos.
La configuración serial para ESP32, ESP8266 y Arduino Uno permanece sin cambios. Consulta las explicaciones anteriores para detalles sobre la inicialización de la interfaz UART y por qué se prefiere el serial hardware en el ESP32.
Función Setup
La secuencia de inicialización en setup() sigue el mismo patrón que antes. Se inician los puertos seriales y se inicializa el sensor usando hu.begin() con un bucle de reintentos para asegurar comunicación estable.
La diferencia clave es el modo de trabajo seleccionado. En este ejemplo, el sensor se configura para monitorización del sueño en lugar de detección de caídas.
hu.configWorkMode(hu.eSleepMode);
Este modo habilita algoritmos para detectar presencia en la cama, etapas del sueño y signos vitales como respiración y frecuencia cardíaca a lo largo del tiempo.
hu.configLEDLight(hu.eHPLed, 1);
Se habilita el LED de presencia, que proporciona retroalimentación visual cuando se detecta una persona.
hu.sensorRet();
Como se explicó antes, el sensor debe reiniciarse tras cambios de configuración para que los nuevos parámetros tengan efecto.
Resumen de la función Loop
La función loop() lee continuamente datos relacionados con el sueño del sensor. A diferencia de los ejemplos anteriores, este código usa smSleepData() y estructuras de datos compuestas adicionales para acceder a métricas más avanzadas.
La salida es más compleja porque el sensor agrega y analiza datos a lo largo del tiempo.
Detección de entrada a la cama
La primera sección verifica si una persona está en la cama.
Serial.print("Bed entry status:");
switch (hu.smSleepData(hu.eInOrNotInBed)) {
La función smSleepData() funciona de manera similar a smHumanData(), pero accede a parámetros relacionados con el sueño.
case 0:
Serial.println("Out of bed"); break;
case 1:
Serial.println("In bed"); break;
Un valor de 1 indica que se detecta una persona dentro del área de la cama. Esto se determina usando detección de presencia combinada con análisis de posición.
Detección del estado de sueño
La siguiente sección lee la etapa actual del sueño.
Serial.print("Sleep status:");
switch (hu.smSleepData(hu.eSleepState)) {
El sensor clasifica el sueño en múltiples etapas.
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;
Estos estados se derivan de patrones de movimiento y variaciones en signos vitales. El sueño profundo se caracteriza por movimiento mínimo y respiración estable, mientras que los estados despiertos muestran más actividad.
Métricas de tiempo y calidad del sueño
El sensor proporciona métricas de duración y calidad como valores numéricos.
Con la constante eWakeDuration la función devuelve cuánto tiempo ha estado despierta la persona durante el periodo de monitorización.
Serial.print("Awake duration: ");
Serial.println(hu.smSleepData(hu.eWakeDuration));
Y con la constante eDeepSleepDuration la función rastrea la duración del sueño profundo.
Serial.print("Deep sleep duration: ");
Serial.println(hu.smSleepData(hu.eDeepSleepDuration));
La puntuación de calidad del sueño es una métrica calculada basada en movimiento, estabilidad respiratoria y etapas del sueño.
Serial.print("Sleep quality score: ");
Serial.println(hu.smSleepData(hu.eSleepQuality));
Datos compuestos del sueño
Luego el código recupera un conjunto estructurado de datos con múltiples parámetros.
sSleepComposite comprehensiveState = hu.getSleepComposite();
Esta estructura combina varias mediciones en un solo objeto. Proporciona una instantánea de la condición actual del sueño. El valor presence indica si hay una persona presente:
switch (comprehensiveState.presence) {
Luego tenemos el valor sleepState, que repite la clasificación de la etapa del sueño:
switch (comprehensiveState.sleepState) {
El valor averageRespiration contiene la tasa media de respiración calculada en una ventana temporal:
Serial.print("\tAverage respiration rate: ");
Serial.println(comprehensiveState.averageRespiration);
Mientras que el valor averageHeartbeat contiene la frecuencia cardíaca media:
Serial.print("\tAverage heart rate: ");
Serial.println(comprehensiveState.averageHeartbeat);
El valor turnoverNumber cuenta cuántas veces la persona cambia de posición durante el sueño:
Serial.print("\tNumber of turns: ");
Serial.println(comprehensiveState.turnoverNumber);
Y el valor largeBodyMove representa la proporción de movimientos grandes:
Serial.print("\tProportion of significant body movement: ");
Serial.println(comprehensiveState.largeBodyMove);
mientras que el valor minorBodyMove indica movimientos más pequeños como ajustes leves:
Serial.print("\tProportion of minor body movement: ");
Serial.println(comprehensiveState.minorBodyMove);
Finalmente, tenemos apneaEvents, que cuenta eventos de apnea detectados (pausas en la respiración):
Serial.print("\tNumber of apneas: ");
Serial.println(comprehensiveState.apneaEvents);
Anormalidades del sueño
El código verifica condiciones anormales del sueño.
Serial.print("Sleep abnormalities:");
switch (hu.smSleepData(hu.eSleepDisturbances)) {
El sensor reporta estados anormales predefinidos.
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;
Estas condiciones se basan en umbrales definidos en el firmware.
Estadísticas del sueño
El código recupera estadísticas a largo plazo para todo el periodo de monitorización. La siguiente estructura proporciona datos agregados, típicamente durante toda una noche.
sSleepStatistics statistics = hu.getSleepStatistics();
Por ejemplo, esta es la puntuación general de calidad del sueño.
Serial.print("\tSleep quality score: ");
Serial.println(statistics.sleepQualityScore);
Y este valor representa la proporción de tiempo despierto.
Serial.print("\tProportion of awake time: ");
Serial.println(statistics.sleepTime);
Luego tenemos un indicador para el porcentaje de tiempo en sueño profundo.
Serial.print("\tProportion of light sleep time: ");
Serial.println(statistics.shallowSleepPercentage);
Y este valor indica el porcentaje de sueño profundo.
Serial.print("\tProportion of deep sleep time: ");
Serial.println(statistics.deepSleepPercentage);
«timeOutOfBed» rastrea cuánto tiempo estuvo la persona fuera de la cama.
Serial.print("\tOut of bed duration: ");
Serial.println(statistics.timeOutOfBed);
y «exitCount» cuenta cuántas veces la persona salió de la cama.
Serial.print("\tNumber of times out of bed: ");
Serial.println(statistics.exitCount);
También obtenemos mediciones del número total de giros corporales
Serial.print("\tNumber of turns: ");
Serial.println(statistics.turnOverCount);
la tasa media de respiración durante el periodo de monitorización
Serial.print("\tAverage respiration: ");
Serial.println(statistics.averageRespiration);
y la frecuencia cardíaca media:
Serial.print("\tAverage heartbeat: ");
Serial.println(statistics.averageHeartbeat);
Clasificación de calidad del sueño
El sensor proporciona una clasificación simplificada de la calidad del sueño.
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;
Esta clasificación se deriva de las métricas detalladas y ofrece un resultado fácil de interpretar.
Detección de lucha anormal
La sección final detecta patrones de movimiento inusuales.
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;
Esta función identifica movimientos irregulares o intensos que pueden indicar incomodidad o angustia durante el sueño.
Temporización del loop
El loop termina con un retardo y un separador, similar a los ejemplos anteriores. El intervalo de un segundo proporciona una tasa de actualización constante mientras permite al sensor acumular datos significativos entre lecturas.
Conclusiones
En este tutorial aprendiste cómo conectar el sensor mmWave C1001 a un Arduino o un ESP32 para medir signos vitales, detectar caídas y monitorizar la calidad del sueño. Ten en cuenta que el sensor C1001 no es un dispositivo médico certificado y no debe usarse para diagnósticos o tratamientos médicos.
Para más información sobre cómo instalar el sensor, su alcance y precisión, consulta el artículo Functional Test Report of DFRobot C1001 mmWave Sensor. También echa un vistazo a la página Wiki y al código repo.
Si solo necesitas detección de presencia, consulta nuestros tutoriales para los sensores mmWave C4001 y mmWave C4002. Estos también son sensores de radar pero no tienen funciones integradas para detección de caídas o monitorización del sueño.
Si tienes alguna pregunta, no dudes en dejarla en la sección de comentarios.
¡Feliz bricolaje ; )

