Sistema de monitoramento remoto de pacientes baseado em IoT para medir sinais vitais do corpo

Tempo de leitura: 10 minutes

Quando falamos sobre os principais sinais vitais de um corpo humano, existem quatro parâmetros principais dos quais precisamos estar cientes: temperatura corporal, frequência cardíaca, frequência respiratória, pressão arterial e, devido ao COVID, a saturação de oxigênio tornou-se um parâmetro principal que precisamos estar cientes. Neste tutorial, faremos um dispositivo simples baseado em Arduino Nano 33 IoT com vários sensores. O dispositivo pode medir alguns parâmetros vitais do corpo humano. O dispositivo será como um monitor multi-para DIY que você vê em UTIs, muito mais simples e feito de sensores baratos não destinados ao uso médico real. Estaremos usando o novo Arduino Nano 33 IOT para essa finalidade e tentaremos tornar este dispositivo o mais simples possível.

 

Componentes necessários para nosso sistema de monitoramento remoto de pacientes

Os componentes necessários para o projeto são muito simples e podem ser encontrados em uma loja local de hobby. Para construir este sistema de monitoramento de saúde específico usando IoT, você precisará dos seguintes componentes.

  • Arduino Nano 33 IOT
  • MLX90614 (termômetro infravermelho digital sem contato)
  • AD8232 (monitor de frequência cardíaca)
  • MAX30100 (oxímetro de pulso e sensor de frequência cardíaca)
  • Áudio (opcional)
  • ProtoBoard
  • Jumper Wires.

 

Arduino Nano 33 IoT

Arduino Nano 33 IoT é uma placa Arduino relativamente nova e falaremos um pouco sobre ela. É uma atualização direta para o Arduino Nano original e atualmente disponível na Loja do Arduino. É mais barato do que um Arduino Nano original, mas o Nano está amplamente disponível a preços muito mais baratos como um clone. Então, você deveria comprar esta nova placa quando poderia obter um clone da geração anterior? As atualizações valem a pena?

Para ser honesto, depende dos seus requisitos. Se você quiser fazer um protótipo com Wi-Fi e BT com alguns sensores em um formato compacto, é recomendável ir em frente. Desse ponto de vista, comprar todos os itens separadamente e fazer a interface deles provavelmente custará mais tempo e dinheiro do que o Nano 33 IoT.

Então, quais atualizações a nova placa tem? Grande quantidade! O Nano original não tinha sensores, conectividade, nada. Em contraste, o Nano 33 IoT atualizado reúne muitos recursos e potência no mesmo formato.

  • O processador principal da placa é um Arm Cortex-M0 SAMD21 de 32 bits de baixo consumo.
  • A conectividade Wi-Fi 2.4G e Bluetooth é fornecida pelo chipset de baixa potência U-Blox NINA-W102.
  • A antena do módulo Wi-Fi/BT é feita em forma de encaixe de metal, protegida de antivibração por uma gota de cola térmica.
  • Microchip ATECC608A crypto chip garante comunicação segura, 6 eixos IMU LSM6DS3

MAX30100 – Oxímetro de pulso e sensor de frequência cardíaca

O MAX30100 também é um módulo sensor baseado em Microchip. Ele usa um conceito chamado PhotoPlethysmography para medir estatísticas vitais e, como saída, fornece um gráfico PPG. Funciona conforme mostrado na figura abaixo.

Como você pode ver, um LED IV/Vermelho/Verde brilha no dedo do sujeito. Dependendo dos batimentos cardíacos, da difusão do oxigênio no sangue e de alguns outros parâmetros, o valor ou a taxa de absorção da onda incidente muda. Ao identificar essas alterações, podemos determinar o nível de oxigênio.

A onda transmitida é então medida por um receptor que fornece um sinal de tensão dependendo da quantidade de luz recebida. Quando a luz viaja através dos tecidos biológicos, é absorvida pelos ossos, pigmentos da pele e sangue venoso e arterial. Uma vez que a luz é mais fortemente absorvida pelo sangue do que pelos tecidos circundantes, as mudanças no fluxo sanguíneo podem ser detectadas pelos sensores PPG como mudanças na intensidade da luz.

O sinal de voltagem do PPG é proporcional à quantidade de sangue que flui através dos vasos sanguíneos. Mesmo pequenas alterações no volume sanguíneo podem ser detectadas usando este método, embora ele não possa ser usado para quantificar a quantidade de sangue. Um sinal PPG tem vários componentes, incluindo mudanças volumétricas no sangue arterial que estão associadas à atividade cardíaca, variações no volume de sangue venoso que modula o sinal PPG, um componente DC mostrando a propriedade óptica dos tecidos e mudanças sutis de energia no corpo.

O sensor MAX30100 possui um infravermelho e um LED vermelho. Geralmente, os parâmetros de freqüência cardíaca e SPO2 são medidos, tentaremos medir um parâmetro adicional – VFC ou variabilidade da freqüência cardíaca.

 

MLX90614 – Sensor de temperatura corporal

O sensor de temperatura corporal MLX90614 é da Melexis, que usa tecnologia IR para medir a temperatura corporal de uma pessoa. Comumente conhecido como pirometria, esse sensor é como uma câmera térmica de pixel único, mas tem um alcance muito pequeno de menos de 3 cm. Além disso, como outros dispositivos IR, o erro de leitura do sensor aumenta com a distância entre o assunto e o sensor. A imagem do sensor é fornecida abaixo.

Sensor de ECG AD8232

O AD8232 é um sensor de frequência cardíaca simples que pode ser mapeado como um ECG. ECG significa eletrocardiograma. Este sensor emite seu sinal como um sinal analógico. O conector de 3,5 mm é usado para conexão de pad biomédico.

 

Módulo MIC Analógico

Este é um sensor simples que registra a amplitude do áudio e os produz como variações analógicas. Isso é útil para medir sinais respiratórios, mas requer muito processamento e filtragem de sinal. Portanto, será abordado em um blog separado. Cuidado, há muitos módulos que não possuem saída analógica (geralmente chamados de sensores de palmas). Eles podem identificar sons acima de uma amplitude particular, mas não são úteis além disso.

 

Display OLED 128X64

Usaremos um display OLED I2C de 1,3 ”para este projeto. Existem muitos genéricos no mercado, então é possível que seu OLED seja um pouco diferente do meu. A biblioteca Uglib2 que usaremos tem suporte para quase todos os monitores que você encontrar, portanto, é muito simples fazer a interface de qualquer monitor OLED com esta biblioteca.

 

Diagrama de circuito para sistema de monitoramento remoto de paciente

O diagrama esquemático completo para construir o Sistema de Monitoramento Remoto de Saúde é mostrado abaixo.

O esquema acima mostra todas as conexões necessárias com o Arduino Nano 33 IoT. Os dois tipos de sensores usados são analógicos (microfone, display OLED e AD8232) e I2C (mlx90614 e MAX3010X). Os pinos Arduino Nano 33 IoT usados são:

A0 – Saída analógica do módulo de ECG AD8232
A1 – Saída analógica do módulo de microfone
A4 – SDA
A5 – SCL

Ao trabalhar com o sensor e esta placa, você precisa manter algumas coisas em mente. A tensão de trabalho no esquema acima é 3V3, já que o módulo de ECG opera a 3V3 e não queremos conversões de tensão desnecessárias. Os resistores usados no esquema acima são 4,7k. Eles devem ser suficientes até mesmo para a tensão de trabalho 3V3. Não usaremos os pinos extras LO +, LO- ou SDN Pin para reduzir a complexidade desnecessária, uma vez que este projeto já possui muitos sensores trabalhando juntos. Você pode consultar o blog do SparkFun ECG para saber como usá-los. O MLX90614 está disponível como sensor ou módulo sensor. Se você usar o sensor vazio, terá que puxar as linhas SCL e SDA como feito no esquema. Além disso, verifique qual série de sensores MLX90614 você está comprando, pois há muitas variantes disponíveis, com base na entrada de energia, tipo, etc., conforme mostrado abaixo.

Após a montagem da placa conforme o esquema, a placa se parece com a imagem abaixo. Por conveniência, desenvolvi uma placa GP simples para este projeto, pois havia muitos módulos para a interface e trabalhar em vários projetos usando uma única placa de ensaio é difícil. Também é útil ter uma placa GP para os microcontroladores que você usa com frequência para economizar tempo e retrabalho desnecessário em projetos que usam sensores com os quais você já fez interface antes.

Eu recomendo que você coloque os sensores MLX90614 e MAX3010X de forma que eles coincidam e você possa cobrir os dois juntos com um único dedo ao mesmo tempo. Quanto à parte de codificação, tentarei o meu melhor para explicá-la de forma concisa.

 

Código Arduino para medir e monitorar sinais vitais

O código completo para construir o detector de sinais visuais de corpo humano é mostrado abaixo, mas antes de prosseguir com o código, precisamos instalar as bibliotecas necessárias, e você pode encontrar quase todas essas bibliotecas necessárias no gerenciador de placa Arduino e instalaremos o bibliotecas a partir daí, precisamos instalar as seguintes bibliotecas.

  • Placas Arduino SAMD
  • Arduino_LSM6DS3 ou Sparkfun LSM6DS3 Breakout (para uso avançado)
  • Arduino WifiNINA
  • Arduino BLE

Agora vamos instalar as bibliotecas.

Além disso, também estamos usando o Módulo OLED. Portanto, também precisamos instalar as bibliotecas OLED. O sensor do oxímetro de pulso calcula SPO2, freqüência cardíaca e HRV usando um conceito chamado PPG ou PhotoPlethysmoGraphy conforme explicado anteriormente. A biblioteca MAX3010X pode identificar pulso ou alterações na refletividade usando uma função de retorno de chamada. Essa função é uma interrupção que é chamada sempre que um batimento cardíaco é detectado. O intervalo entre dois batimentos cardíacos consecutivos é armazenado para calcular o parâmetro HRV. A frequência cardíaca é calculada a cada intervalo REPORTING_PERIOD_MS. Como o dedo é usado para medir a temperatura corporal, adicionamos compensação ao valor medido pelo sensor MLX90614.

 

Função SETUP:

// display conectado
    u8x8.begin();
    u8x8.setPowerSave(0);
    u8x8.setFont(u8x8_font_chroma48medium8_r);
    Serial.begin(115200);
// Inicializa a instância do PulseOximeter
    if (!pox.begin(PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES)) {
        //Serial.println("FAILED");
        for(;;);
    } else {
        //Serial.println("SUCCESS");
    }
    // A corrente padrão para o LED IV é 50mA e pode ser alterada conforme mostrado abaixo.
    // Verifique MAX30100_Registers.h para todas as opções disponíveis.
    pox.setIRLedCurrent(MAX30100_LED_CURR_11MA);
    // Registra um retorno de chamada para a detecção de batida
    pox.setOnBeatDetectedCallback(onBeatDetected);
// inicializar o sensor MLX90614
   mlx.begin();
   time2 = micros(); // cronômetro para uso futuro.

 

Função LOOP:

A função de loop leva continuamente variáveis de sinal (IR, RED, ECG e valores de microfone) e calcula variáveis de parâmetro (HR, SPO2, HRV, temperatura ambiente, temperatura do objeto) em intervalos regulares (armazenados como REPORTING_PERIOD_MS). Depois que todas as variáveis e valores de sinal são calculados, eles são exibidos no OLED. Como as variáveis HR e HRV são extremamente sensíveis ao tempo e dependem de quão rápido a função de interrupção do batimento cardíaco é chamada após o batimento cardíaco real, não podemos atualizar a tela continuamente. Portanto, nós o atualizamos após intervalos regulares (= DISPLAY_INTERVAL*REPORTING_PERIOD_MS). Todas as variáveis e valores de sinal também são enviados em série no formato CSV para coleta de dados, plotagem e armazenamento. O exemplo de saída é mostrado abaixo. Formato de telemetria: hr, spo2, hrv, object_temp, ambient_temp, ir_signal/100, red_signal/100.

A saída da plotadora serial para o mesmo é mostrada abaixo. A chave de cor é mostrada no canto superior direito e está na ordem da telemetria (hr, spo2, hrv, object_temp, ambient_temp, ir_signal/100, red_signal/100) da esquerda para a direita. Depois de plotar os dados, a janela da plotadora serial se parece com a imagem abaixo.

É assim que funciona o nosso sistema de monitoramento de pacientes baseado em IoT. Espero que tenha gostado do artigo e aprendido algo novo. Se você tiver alguma dúvida em relação ao artigo, comente abaixo.

#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include "MAX30100.h"
#include <Adafruit_MLX90614.h>
#include <Adafruit_GFX.h>
#include <U8x8lib.h>
#include <avr/dtostrf.h>
#define REPORTING_PERIOD_MS     500   //taxa de atualização dos parâmetros hr, spo2, ambient, object, hrv, etc. em milissegundos
#define DISPLAY_INTERVAL        5     //taxa de atualização para a tela i2c = REPORTING_PERIOD_MS*DISPLAY_INTERVAL
#define COMPENSATION            5     //compensação na temperatura do objeto. Diferentes partes do corpo têm diferentes temperaturas. Os dedos estão cerca de 5 graus abaixo da temperatura corporal central
// objetos
PulseOximeter pox;    //this offers spo2 and hr calculation 
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
MAX30100 sensor;
//variaveis
uint32_t tsLastReport = 0;
int hr, spo2, count = 0, flag = 0, PatientID = 0;
float ambient, object, hrv;
long time1 = 0, time2 = 0; 
uint16_t ir = 0, red = 0, ecg = 0, mic; ;
char str_hrv[10], str_object[10], str_ambient[10], str_ir[10], str_red[10];
// Callback (registrado abaixo) disparado quando um pulso é detectado
void onBeatDetected()
{
    time1 = micros() - time2;
    time2 = micros();
}
void setup()
{
    // display conectado
    u8x8.begin();
    u8x8.setPowerSave(0);
    u8x8.setFont(u8x8_font_chroma48medium8_r);
    //pinMode(10, INPUT); // Configuração para detecção de derivações LO +
    //pinMode(11, INPUT); // Configuração para detecção de derivações desligadas LO -
    Serial.begin(115200);
    /*
    while (!Serial) {
      ; // wait for serial port to connect. Needed for native USB port only
    }
    */
    // Inicializa a instância do PulseOximeter
    // As falhas são geralmente devido a uma ligação I2C inadequada, fonte de alimentação ausente
    // ou chip alvo errado
    if (!pox.begin(PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES)) {
        //Serial.println("FAILED");
        for(;;);
    } else {
        //Serial.println("SUCCESS");
    }
    // A corrente padrão para o LED IV é 50mA e pode ser alterada
    //   removendo o comentário da seguinte linha. Verifique MAX30100_Registers.h para todos os
    //   Opções disponíveis.
    pox.setIRLedCurrent(MAX30100_LED_CURR_11MA);
    // Registra um retorno de chamada para a detecção de batida
    pox.setOnBeatDetectedCallback(onBeatDetected);
    mlx.begin();
    time2 = micros();
}
void loop()
{
    // Certifique-se de chamar update o mais rápido possível
    pox.update();
    sensor.update();
    // lendo funções contínuas (sinais) a cada loop
    while (sensor.getRawValues(&ir, &red)) {}
    ecg = analogRead(A0);
    ecg = map(ecg, 250, 500, 0, 100);
    mic = analogRead(A1);
    delay(1);
    // Calcular de forma assíncrona outras variáveis a cada REPORTING_PERIOD_MS
    // Para hr e spo2, um valor de 0 significa "inválido", para objetos e temperaturas ambiente, um valor inferior a 70 degF ou superior a 110 degF pode ser considerado anormal
    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        hr = pox.getHeartRate();
        spo2 = pox.getSpO2();
        ambient = mlx.readAmbientTempF();
        object = mlx.readObjectTempF() + COMPENSATION;
        hrv = (60000000/hr - (float)time1)/1000;
        //send_serial();
        tsLastReport = millis();
        count++;
        flag = 0;
    }
    // Mostra todas as variáveis no display após DISPLAY_INTERVAL segundos
    if ((count%DISPLAY_INTERVAL == 0) && (flag != 1)) {
      flag = 1;  // Este sinalizador garante que a exibição seja atualizada apenas uma vez a cada DISPLAY_INTERVAL segundos
      Wire.end();
      send_display();
      Wire.begin();     
    }
    Telemetry();
}
// função de impressão do monitor serial.
// Na verdade não é necessário, pois a função de telemetria imprime todos os valores em formato csv no monitor serial
void send_serial() {
  Serial.print("bpm / SpO2:");
  Serial.print("Heart rate:");
  Serial.print(hr);
  Serial.print(spo2);
  Serial.print("% / hrv:");
  Serial.print(hrv);
  Serial.print("ms / Ambient:");
  Serial.print(ambient); 
  Serial.print("*F / tObject = "); 
  Serial.print(object); 
  Serial.println("*F");
}
// exibe a função de impressão
void send_display() {
  u8x8.clearDisplay();
  u8x8.setCursor(0,1);
  u8x8.print("HRV:"); 
  u8x8.print(hrv);
  u8x8.print(" ms");
  u8x8.setCursor(0,2);
  u8x8.print("SpO2:");
  u8x8.print(spo2);
  u8x8.print(" %");
  u8x8.setCursor(0,3);
  u8x8.print("HR:");
  u8x8.print(hr);
  u8x8.print(" bpm");
  u8x8.setCursor(0,4);
  u8x8.print("Temp:");
  u8x8.print(object);
  u8x8.print(" degF");
  u8x8.setCursor(0,5);
  u8x8.print("ecg:");
  u8x8.print(ecg);
  u8x8.setCursor(0,6);
  u8x8.print("mic");
  u8x8.print(mic);
  //delay(200); 
}
// telemetria serial para forwarder de dados de impulso de borda
void Telemetry() {
  char buffer[150];
  dtostrf(hrv, 4, 2, str_hrv);
  dtostrf(object, 4, 2, str_object);
  dtostrf(ambient, 4, 2, str_ambient);
  dtostrf((float)ir/100, 5, 2, str_ir);
  dtostrf((float)red/100, 5, 2, str_red);
  sprintf(buffer,"%d,%d,%d,%d,%s,%s,%s,%s,%s,%d,%d",PatientID,count/10,hr,spo2,str_hrv,str_object,str_ambient,str_ir,str_red,ecg,mic);
  Serial.println(buffer);
}