Skip to Content

Deteção de Queda Interior com mmWave C1001

Deteção de Queda Interior com mmWave C1001

O Sensor de Detecção de Quedas Interior mmWave C1001 60GHz é um módulo radar compacto projetado para monitorização de presença humana e segurança. Opera na banda de ondas milimétricas de 60 GHz e pode detetar movimento, postura e até movimentos corporais muito pequenos, como a respiração.

Ao contrário dos sistemas tradicionais baseados em PIR ou câmaras, este sensor utiliza sinais radar para analisar as ondas refletidas pelo corpo humano. Isto permite detetar tanto movimento como imobilidade, incluindo casos em que uma pessoa caiu e permanece imóvel. Funciona também no escuro total e não captura imagens, tornando-o adequado para ambientes interiores sensíveis à privacidade.

O módulo inclui algoritmos incorporados para deteção de quedas, monitorização do sono, deteção de presença e medições básicas de sinais vitais. Pode medir a respiração e o batimento cardíaco a curta distância e detetar atividade humana até cerca de 11 metros. Os resultados processados são enviados diretamente por uma interface serial, pelo que não é necessário processamento complexo no microcontrolador.

Neste tutorial, aprenderás como ligar o sensor mmWave C4002 a um Arduino ou ESP32 para medir sinais vitais, detetar quedas e monitorizar a qualidade do sono.

Overview

Peças Necessárias

Podes adquirir o Sensor mmWave C1001 na DFRobot ou Amazon. Também vais precisar de um Arduino, ESP8266 ou ESP32. Neste tutorial uso um Arduino UNO e um ESP32-C3 SuperMini, mas qualquer outro Arduino, ESP32 ou ESP8266 serve desde que tenha um pino de saída de 5V. Por fim, uma breadboard e alguns cabos Dupont para as ligações serão úteis.

Sensor mmWave C1001

ESP32-C3 SuperMini

Cabo USB C

Arduino

Arduino Uno

USB Data Sync cable Arduino

Cabo USB para Arduino UNO

Dupont wire set

Conjunto de Cabos 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.

Hardware do Sensor mmWave C1001

O sensor C1001 baseia-se num front-end radar de ondas milimétricas a 60 GHz. Opera na faixa de frequência de aproximadamente 61 a 61,5 GHz e transmite ondas eletromagnéticas de baixa potência para o ambiente. O sinal transmitido é refletido por objetos e corpos humanos, e o sensor analisa o sinal retornado para extrair informações de movimento e presença. A imagem abaixo mostra a parte traseira e frontal do módulo do sensor C1001:

Back and Front of mmWave C1001 Sensor Module
Parte Traseira e Frontal do Módulo do Sensor mmWave C1001

O radar utiliza uma abordagem de imagem por nuvem de pontos para modelar a posição e o movimento de um alvo humano. Este método permite ao sensor detetar mudanças de postura e movimento espacial, em vez de depender apenas de gatilhos simples de movimento. Como resultado, pode distinguir entre posições de pé, em movimento e deitado com maior fiabilidade.

O sensor também pode detetar micro-movimentos, como o deslocamento do peito causado pela respiração e batimento cardíaco. Isto é possível porque os sinais de ondas milimétricas são sensíveis a mudanças muito pequenas na superfície, mesmo na faixa submilimétrica.

Alcance de Detecção e Campo de Visão

O sensor C1001 suporta uma distância máxima de deteção de até 11 metros em condições ótimas. Oferece um amplo campo de visão com um ângulo de cobertura aproximado de 100 graus nas direções horizontal e vertical.

Quando usado para deteção de quedas, o sensor é normalmente montado no teto. A uma altura de instalação de cerca de 2,7 metros, a área efetiva de deteção de quedas forma uma zona circular com um diâmetro de cerca de 4 metros.

Para monitorização de sinais vitais, o alcance de deteção é mais curto. As medições de respiração e batimento cardíaco são mais precisas dentro de uma distância de cerca de 0,4 a 1,5 metros. A monitorização do sono pode estender-se um pouco mais, até aproximadamente 2,5 metros do sensor.

Processamento de Sinal e Algoritmos Incorporados

O C1001 integra processamento de sinal e algoritmos de deteção a bordo. Os dados brutos do radar são processados internamente, e o utilizador recebe informações de alto nível em vez de fluxos de sinal brutos. Isto reduz a carga computacional no microcontrolador conectado.

O firmware interno implementa múltiplos modos de deteção. Estes incluem deteção de presença humana, rastreamento de movimento, deteção de quedas e monitorização do sono. O algoritmo de deteção de quedas analisa transições de postura e identifica mudanças súbitas seguidas de imobilidade. Também pode acompanhar a duração da inatividade após um evento de queda.

O algoritmo de deteção de sinais vitais extrai padrões periódicos dos sinais refletidos. Calcula taxas de respiração tipicamente na faixa de 10 a 25 respirações por minuto e frequências cardíacas entre 60 e 100 batimentos por minuto.

Características Elétricas

O sensor opera com uma tensão de alimentação de 5 V e consome tipicamente menos de 100 mA. Isto torna-o adequado para sistemas embutidos alimentados por placas de desenvolvimento padrão.

O transmissor do radar emite um sinal com um nível de potência de cerca de 6 dBm. Isto assegura força de sinal suficiente para deteção interior, mantendo baixo consumo de energia e operação segura.

O dispositivo foi projetado para operar numa faixa de temperatura de −20 °C a 60 °C. Isto permite operação estável em ambientes interiores típicos e muitas aplicações semi-industriais.

Interface e Saída de Dados

O C1001 comunica através de uma interface serial UART. Fornece quadros de dados processados que incluem estados de deteção como presença, estado de queda e informações de sinais vitais.

A alimentação (5V) é feita pelos pinos VIN e GND, enquanto os pinos TX e RX são usados para comunicação serial com um microcontrolador. Dois pinos digitais auxiliares rotulados IO1 e IO2 destinam-se a reportar eventos de queda e presença humana. A foto abaixo mostra o pinout do módulo C1001:

Pinout of the C1001 Sensor
Pinout do Sensor C1001

Note que não consegui fazer funcionar os pinos IO1 ou IO2. Não encontrei uma função na biblioteca para ativar estes pinos de saída e, por padrão, parecem não estar ativos.

Restrições de Instalação e Operação

O sensor requer um bom posicionamento para alcançar desempenho ótimo. Para deteção de quedas, recomenda-se uma configuração montada no teto. O feixe do radar forma uma área de cobertura tridimensional, e obstáculos ou objetos em movimento podem afetar a qualidade do sinal.

A precisão da deteção de sinais vitais depende da distância, orientação e estabilidade ambiental. Fontes externas de movimento, como ventiladores ou cortinas, podem introduzir ruído no sinal refletido.

Devido à natureza da deteção por radar, o módulo funciona consistentemente em ambientes com pouca luz ou completamente escuros. Não é afetado pelas condições de luz ambiente e não depende de deteção ótica.

Especificação Técnica

A tabela seguinte resume a especificação técnica do sensor mmWave C1001:

Parâmetro Valor / Descrição
Frequência de Operação 60 GHz mmWave (aprox. 61–61,5 GHz)
Tecnologia de Deteção Radar FMCW com processamento de nuvem de pontos
Alcance de Deteção Até 11 m (presença e movimento)
Alcance de Deteção de Quedas Otimizado para montagem no teto, área de ~4 m de diâmetro
Alcance de Deteção de Sinais Vitais ~0,4 m a 1,5 m (até ~2,5 m para monitorização do sono)
Campo de Visão ~100° horizontal e vertical
Capacidades de Deteção Presença, movimento, deteção de quedas, monitorização do sono
Medição de Sinais Vitais Respiração e frequência cardíaca
Faixa da Taxa de Respiração ~10–25 respirações por minuto
Faixa da Frequência Cardíaca ~60–100 bpm
Tensão de Alimentação 5 V
Corrente de Operação < 100 mA
Potência de Transmissão ~6 dBm
Interface de Comunicação UART (nível TTL)
Pinos de Saída Digital IO1 (deteção de queda), IO2 (deteção de presença)
Nível Lógico 3,3 V
Temperatura de Operação −20 °C a 60 °C
Método de Montagem Montagem no teto ou parede (teto preferido para deteção de quedas)
Saída de Dados Dados processados (não requer dados brutos do radar)
Plataformas Suportadas Arduino, ESP32, ESP8266

Ligação do Sensor mmWave C1001 ao Arduino

Ligar o sensor mmWave C1001 a um Arduino UNO é simples. Começa por ligar VIN ao 5V do Arduino. Depois liga GND ao GND. Finalmente, liga a interface UART ligando RX ao GPIO 5 e TX ao GPIO 4. A imagem abaixo mostra a ligação completa:

Connecting the mmWave C1001 Sensor to an Arduino UNO
Ligação do Sensor mmWave C1001 a um Arduino UNO

Para conveniência, aqui está uma tabela com as ligações que precisas de fazer:

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

Ligação do Sensor mmWave C1001 ao ESP32

O ESP32 tem três interfaces seriais e podes configurar os pinos e a interface que queres usar. Aqui ligo TX ao GPIO 3 e RX ao GPIO 4. Precisamos de lembrar isto ao escrever o código. Finalmente, ligamos VIN ao 5V e GND ao G. A imagem abaixo mostra a ligação completa:

Connecting the mmWave C1001 Sensor to an ESP32-C3 Supermini
Ligação do Sensor mmWave C1001 a um ESP32-C3 Supermini

Note que precisas de um ESP32 com um pino de saída de 5V e que deves ligar o VIN do C1001 ao pino de 5V e não ao comum pino de 3,3V! A imagem abaixo mostra o pinout do ESP32-C3 Supermini que estou a usar aqui.

Pinout do ESP32-C3 Supermini

Para conveniência, aqui está uma tabela com as ligações que precisas de fazer.

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

Instalação da biblioteca DFRobot_HumanDetection

Antes de escrevermos qualquer código, precisamos de instalar a DFRobot_HumanDetection biblioteca. Para instalar esta biblioteca, vai ao repositório DFRobot_HumanDetection, clica no botão verde “<> Code” e depois em “Download ZIP” para descarregar a biblioteca como um ficheiro ZIP, como mostrado abaixo:

Depois cria um novo Sketch no Arduino, vai a Sketch -> Include Library -> Add .ZIP Library … para instalar a biblioteca ZIP descarregada (DFRobot_HumanDetection-master.zip):

Código: Medições de Sinais Vitais

O exemplo de código seguinte mostra como medir sinais vitais como frequência cardíaca e respiratória com o sensor C1001. Modifiquei ligeiramente o código original da basic.ino no repositório github, removendo algumas impressões e adicionando suporte para microcontroladores Arduino e ESP866 além do 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);
}

Importações

O código começa por incluir a biblioteca necessária para o sensor. A DFRobot_HumanDetection biblioteca fornece todas as funções necessárias para comunicar com o sensor mmWave C1001 e aceder a dados processados.

#include "DFRobot_HumanDetection.h"

Esta biblioteca abstrai o protocolo UART de baixo nível. Permite trabalhar com funções de alto nível como deteção de presença, estado de movimento e sinais vitais.

Configuração Serial Específica para a Placa

O código configura a interface serial dependendo da placa alvo. O sensor C1001 comunica via UART, por isso deve ser atribuído um porto 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 ou ESP8266, é criado um porto serial por software nos pinos 4 e 5. Isto é necessário porque estas placas geralmente têm apenas um UART hardware.

Para o ESP32, o código usa Serial1, que é um UART hardware. Isto é mais fiável e suporta taxas de dados mais elevadas.

O objeto hu é criado como uma instância da classe do sensor. Recebe um ponteiro para a interface serial, usada internamente para comunicação com o sensor.

Função Setup

A função setup() inicializa a comunicação serial e prepara o sensor para operação.

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

A porta serial principal é iniciada a 115200 baud. Esta é usada para depuração e impressão dos dados do sensor no Monitor Serial.

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

No ESP32, o UART hardware é inicializado com uma taxa de 115200 baud. A configuração SERIAL_8N1 significa 8 bits de dados, sem paridade e 1 bit de paragem. Os pinos 3 e 4 são atribuídos como RX e TX. Para outras placas, a interface serial por software é iniciada com a mesma taxa.

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

É impressa uma mensagem simples para indicar que a inicialização começou:

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

A função hu.begin() inicializa a comunicação com o sensor. Retorna 0 em caso de sucesso. Se a inicialização falhar, o código imprime uma mensagem de erro e tenta novamente a cada segundo. Este ciclo garante que o sensor está pronto antes de continuar:

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

Configuração do Sensor

Após a inicialização, o sensor é configurado usando funções da biblioteca. Esta linha define o modo de funcionamento do sensor. O modo eSleepMode é otimizado para detetar humanos estacionários e monitorizar sinais vitais como respiração e frequência cardíaca.

  hu.configWorkMode(hu.eSleepMode);

Esta função controla o LED incorporado. O parâmetro eHPLed seleciona o tipo de LED, e 1 liga-o. Isto pode ser útil para depuração ou feedback visual.

  hu.configLEDLight(hu.eHPLed, 1); 

E esta função reinicia o sensor. É necessário um reset após alterar parâmetros de configuração para garantir que têm efeito.

  hu.sensorRet(); 

Função Loop

A função loop() lê continuamente dados do sensor e imprime-os no Monitor Serial.

Primeiro imprimimos um rótulo para a deteção de presença humana.

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

De seguida usamos a função smHumanData() para ler um tipo específico de dados do sensor. O parâmetro eHumanPresence seleciona a deteção de presença.

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

Um valor de retorno 0 significa que não foi detetado nenhum humano. Um valor de 1 indica que uma pessoa está presente. Qualquer outro valor indica um erro de comunicação ou leitura:

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

Estado de Movimento

A secção seguinte lê o estado de movimento da pessoa detetada. O parâmetro eHumanMovement seleciona a classificação do movimento.

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

Um valor de 0 significa que não há movimento, um valor de 1 indica que a pessoa está presente mas imóvel, e um valor de 2 indica movimento ativo.

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

Intensidade do Movimento

O código imprime depois um valor numérico que representa a intensidade ou alcance do movimento.

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

Este valor é útil para estimar o quanto a pessoa está a mover-se dentro da área de deteção. Valores mais altos indicam movimento mais forte ou maior.

Sinais Vitais

O sensor pode também medir a respiração e a frequência cardíaca. A função getBreatheValue() retorna a taxa de respiração em respirações por minuto.

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

E a função getHeartRate() retorna a frequência cardíaca em batimentos por minuto. Estas medições baseiam-se em micro-movimentos detetados pelo radar.

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

Temporização do Loop

No final do loop, é adicionada uma pausa para controlar a taxa de atualização.

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

Exemplo de Saída

A imagem seguinte mostra um exemplo de saída do código. Note que demora alguns minutos até aparecerem as medições de Respiração e Frequência Cardíaca. O sensor precisa de algum tempo para obter leituras estáveis.

Medir Respiração e Frequência Cardíaca sem contacto e a uma distância de até 1,5 metros é impressionante. Note que a precisão é limitada, no entanto. Veja o post Functional Test Report of DFRobot C1001 mmWave Sensor para mais informações sobre condições de medição, fiabilidade e precisão.

Código: Deteção de Quedas

O código seguinte demonstra como realizar a deteção de quedas com o sensor C1001. Tal como antes, é uma versão ligeiramente modificada do código fall.ino no repositório github da biblioteca DFRobot_HumanDetection. Suporta microcontroladores 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);
}

Importações e Inicialização do Objeto

A inclusão da biblioteca e a criação do objeto são idênticas ao exemplo anterior. A mesma DFRobot_HumanDetection biblioteca é usada, e o objeto sensor hu é inicializado com uma interface serial hardware ou software dependendo da placa.

A configuração UART e a configuração da comunicação seguem a mesma estrutura que antes. Podes consultar a explicação anterior para detalhes sobre a inicialização serial e construção do objeto.

Função Setup

A sequência de inicialização dentro de setup() é também a mesma. As interfaces seriais são iniciadas, e o sensor é inicializado usando hu.begin(). O ciclo que tenta novamente a inicialização garante comunicação estável antes de continuar.

A diferença neste exemplo começa com a configuração do sensor. O sensor é agora configurado explicitamente para deteção de quedas.

Configuração do Modo de Deteção de Quedas

O modo de funcionamento é alterado para um modo dedicado à deteção de quedas.

hu.configWorkMode(hu.eFallingMode);

Isto muda o firmware interno para usar algoritmos de deteção de quedas em vez de monitorização geral de presença ou sono. O sensor foca-se agora em mudanças de postura e movimentos súbitos seguidos de inatividade.

Configuração dos LEDs

Dois indicadores LED são configurados para feedback visual.

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

O eFALLLed controla o LED que indica um evento de queda detetado. O eHPLed controla o LED de deteção de presença. Definir ambos para 1 ativa-os.

Estes LEDs são controlados pela lógica interna de deteção e podem ajudar durante testes e calibração.

Altura de Instalação

A altura de instalação é um parâmetro crítico para deteção precisa de quedas. A seguinte chamada de função define a altura de montagem do sensor para 270 cm. O valor deve corresponder à altura real de instalação porque o processamento do radar depende da geometria.

hu.dmInstallHeight(270);

Valores incorretos de altura podem levar a estimativas de posição imprecisas e falsas deteções.

Temporização da Deteção de Quedas

O sensor inclui um atraso configurável antes de confirmar um evento de queda. A seguinte chamada de função define um atraso de 5 segundos. Após detetar uma possível queda, o sensor espera este tempo antes de reportar como queda válida.

hu.dmFallTime(5);

Isto ajuda a filtrar movimentos curtos ou não críticos que poderiam causar falsos positivos.

Atraso na Deteção de Ausência

O sensor também atrasa o reporte quando não há pessoa presente. A seguinte função define um atraso de 1 segundo antes de mudar para o estado “sem pessoa”.

hu.dmUnmannedTime(1);

Isto previne alternâncias rápidas quando uma pessoa sai brevemente ou se move na borda da zona de deteção.

Deteção de Permanência Imóvel

O sensor pode detetar quando uma pessoa permanece imóvel por muito tempo. A seguinte chamada de função define o tempo de permanência para 200 segundos.

hu.dmFallConfig(hu.eResidenceTime, 200);

Se uma pessoa permanecer imóvel dentro da área de deteção por mais tempo que este período, o sensor reporta um estado estacionário.

Esta funcionalidade é útil em cenários de deteção de quedas porque uma pessoa deitada imóvel após uma queda pode ser identificada.

Sensibilidade à Queda

A sensibilidade do algoritmo de deteção de quedas pode ser ajustada. Aqui a sensibilidade é definida para o nível 3, que é o valor mais alto.

hu.dmFallConfig(hu.eFallSensitivityC, 3);

Sensibilidade mais alta aumenta a probabilidade de detetar quedas, mas pode também aumentar falsos positivos. Valores mais baixos reduzem a sensibilidade e requerem mudanças de movimento mais pronunciadas.

Aplicação da Configuração

Após definir todos os parâmetros, o sensor é reiniciado.

hu.sensorRet();

Como explicado anteriormente, este passo é necessário para que a nova configuração tenha efeito. O sensor reinicia com os parâmetros atualizados.

Função Loop

O loop lê continuamente dados relacionados com quedas do sensor. Ao contrário do exemplo anterior, este código usa getFallData() em vez de smHumanData().

Deteção do Estado de Queda

A função getFallData() obtém resultados processados da deteção de quedas. O parâmetro eFallState seleciona o estado da queda:

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

Um valor de 0 significa que não foi detetada queda, e um valor de 1 indica que um evento de queda foi confirmado pelo sensor:

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

Deteção do Estado Estacionário

A constante estaticResidencyState é usada para obter o estado de permanência imóvel:

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

Um valor de 1 significa que uma pessoa permaneceu imóvel por mais tempo que o tempo de permanência configurado. Isto pode indicar uma situação crítica, especialmente quando combinado com uma queda detetada.

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

Temporização do Loop

O loop termina com uma pausa e um separador para melhor leitura.

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

Código: Monitorização do Sono

Neste último exemplo de código realizamos a monitorização do sono com o sensor C1001. O código baseia-se no exemplo sleep.ino da biblioteca DFRobot_HumanDetection. Apenas adicionei suporte para microcontroladores 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);
}

Importações e Inicialização do Objeto

A inclusão da biblioteca e a criação do objeto são idênticas aos exemplos anteriores. A mesma classe DFRobot_HumanDetection é usada, e o sensor está ligado através de uma interface UART. O objeto hu gere toda a comunicação e processamento de dados.

A configuração serial para ESP32, ESP8266 e Arduino Uno mantém-se inalterada. Consulta as explicações anteriores para detalhes sobre como a interface UART é inicializada e porque o serial hardware é preferido no ESP32.

Função Setup

A sequência de inicialização em setup() segue o mesmo padrão que antes. As portas seriais são iniciadas, e o sensor é inicializado usando hu.begin() com um ciclo de tentativas para garantir comunicação estável.

A principal diferença é o modo de funcionamento selecionado. Neste exemplo, o sensor é configurado para monitorização do sono em vez de deteção de quedas.

hu.configWorkMode(hu.eSleepMode);

Este modo ativa algoritmos para detetar presença na cama, fases do sono e sinais vitais como respiração e frequência cardíaca ao longo do tempo.

hu.configLEDLight(hu.eHPLed, 1);

O LED de presença está ativado, fornecendo feedback visual quando uma pessoa é detetada.

hu.sensorRet();

Como explicado anteriormente, o sensor deve ser reiniciado após alterações de configuração para que os novos parâmetros tenham efeito.

Visão Geral da Função Loop

A função loop() lê continuamente dados relacionados com o sono do sensor. Ao contrário dos exemplos anteriores, este código usa smSleepData() e estruturas de dados compostas adicionais para aceder a métricas mais avançadas.

A saída é mais complexa porque o sensor agrega e analisa dados ao longo do tempo.

Deteção de Entrada na Cama

A primeira secção verifica se uma pessoa está na cama.

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

A função smSleepData() funciona de forma semelhante a smHumanData(), mas acede a parâmetros relacionados com o sono.

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

Um valor de 1 indica que uma pessoa foi detetada na área da cama. Isto é determinado usando deteção de presença combinada com análise de posição.

Deteção do Estado do Sono

A secção seguinte lê a fase atual do sono.

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

O sensor classifica o sono em múltiplas fases.

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;

Estes estados são derivados de padrões de movimento e variações dos sinais vitais. O sono profundo é caracterizado por movimento mínimo e respiração estável, enquanto os estados de vigília mostram mais atividade.

Temporização e Métricas de Qualidade do Sono

O sensor fornece métricas de duração e qualidade como valores numéricos.

Com a constante eWakeDuration a função retorna quanto tempo a pessoa esteve acordada durante o período de monitorização.

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

E com a constante eDeepSleepDuration a função acompanha a duração do sono profundo.

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

A pontuação de qualidade do sono é uma métrica calculada com base no movimento, estabilidade da respiração e fases do sono.

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

Dados Compostos do Sono

De seguida, o código obtém um conjunto estruturado de dados com múltiplos parâmetros.

sSleepComposite comprehensiveState = hu.getSleepComposite();

Esta estrutura combina várias medições num único objeto. Fornece um instantâneo da condição atual do sono. O valor presence indica se uma pessoa está presente:

switch (comprehensiveState.presence) {

De seguida temos o valor sleepState, que repete a classificação da fase do sono:

switch (comprehensiveState.sleepState) {

O valor averageRespiration contém a taxa média de respiração calculada numa janela temporal:

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

Enquanto o valor averageHeartbeat contém a frequência cardíaca média:

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

O valor turnoverNumber conta quantas vezes a pessoa muda de posição durante o sono:

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

E o valor largeBodyMove representa a proporção de movimentos grandes:

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

enquanto o valor minorBodyMove indica movimentos menores, como pequenos ajustes:

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

Finalmente, temos apneaEvents, que conta eventos de apneia detetados (pausas na respiração):

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

Anomalias do Sono

O código verifica condições anormais do sono.

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

O sensor reporta estados anormais 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 condições baseiam-se em limiares definidos no firmware.

Estatísticas do Sono

O código obtém estatísticas de longo prazo para todo o período de monitorização. A estrutura seguinte fornece dados agregados, tipicamente ao longo de uma noite inteira.

sSleepStatistics statistics = hu.getSleepStatistics();

Por exemplo, esta é a pontuação geral de qualidade do sono.

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

E este valor representa a proporção do tempo passado acordado.

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

De seguida temos um indicador para a percentagem de tempo de sono profundo.

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

E este valor indica a percentagem de sono profundo.

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

“timeOutOfBed” regista quanto tempo a pessoa esteve fora da cama.

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

e “exitCount” conta quantas vezes a pessoa saiu da cama.

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

Também obtemos medições para o número total de viragens do corpo

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

a taxa média de respiração durante o período de monitorização

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

e a frequência cardíaca média:

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

Classificação da Qualidade do Sono

O sensor fornece uma classificação simplificada da qualidade do sono.

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 classificação é derivada das métricas detalhadas e fornece um resultado fácil de interpretar.

Deteção de Luta Anormal

A secção final deteta padrões de movimento incomuns.

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 funcionalidade identifica movimentos irregulares ou intensos que podem indicar desconforto ou angústia durante o sono.

Temporização do Loop

O loop termina com uma pausa e um separador, semelhante aos exemplos anteriores. O intervalo de um segundo fornece uma taxa de atualização estável, permitindo ao sensor acumular dados significativos entre leituras.

Conclusões

Neste tutorial aprendeste como ligar o sensor mmWave C1001 a um Arduino ou ESP32 para medir sinais vitais, detetar quedas e monitorizar a qualidade do sono. Note que o sensor C1001 não é um dispositivo médico certificado e não deve ser usado para diagnóstico ou tratamentos médicos!

Para mais informações sobre como instalar o sensor, seu alcance e precisão, vê o artigo Functional Test Report of DFRobot C1001 mmWave Sensor. Também consulta a página Wiki e o código repo.

Se só precisares de deteção de presença, vê os nossos tutoriais para os sensores mmWave C4001 e mmWave C4002. Estes também são sensores radar, mas não têm funções incorporadas para deteção de quedas ou monitorização do sono.

Se tiveres alguma dúvida, não hesites em deixá-la na secção de comentários.

Boas construções ; )