Мониторинг сердечного пульса на Arduino через интернет

В данной статье мы рассмотрим устройство для мониторинга сердечного ритма (пульса) на основе платы Arduino через сеть интернет, которое будет измерять пульс с помощью датчика импульсов и показывать измеренное значение пульса в BPM (Beats Per Minute – число ударов сердца в минуту). Также измеренные значения пульса мы с помощью Wi-Fi модуля ESP8266 будем передавать на сервер ThingSpeak, на котором их можно будет посмотреть из любой точки мира. Сервис ThingSpeak отлично подходит для подобных проектов, ранее мы рассматривали работу с ним в статье про мониторинг температуры через интернет.

Внешний вид устройства для мониторинга сердечного пульса на Arduino через интернет

Также ранее на нашем сайте мы рассматривали простой монитор сердечного ритма на основе Arduino, без передачи данных в сеть интернет. Рассматриваемый же в данной статье проект можно отнести к так называемой категории интернета вещей (IOT – Internet of Things).

Необходимые компоненты

Плата Arduino Uno
Датчик импульсов (Pulse sensor)
Wi-Fi модуль ESP8266
ЖК дисплей 16х2
Макетная плата
Потенциометр 10 кОм
Резисторы 1 кОм
Резисторы 220 Ом
Светодиод
Соединительные провода

Работа схемы

Вначале нам необходимо подключить модуль ESP8266 к плате Arduino. Модуль ESP8266 работает от напряжения 3.3V, поэтому если его подключить к контакту 5V платы Arduino, то его можно повредить. Поэтому следует подсоединить контакты VCC и CH_PD модуля ESP8266 к контакту 3.3V платы Arduino. Контакт RX модуля ESP8266 также работает от 3.3V и он также не будет взаимодействовать с платой Arduino если его подключить к ней непосредственно. Поэтому в нашей схеме мы будем использовать делитель напряжения чтобы конвертировать 5V в 3.3V. Подобный делитель напряжения можно сделать с помощью последовательного соединения 3-х резисторов как показано на схеме ниже. Соедините контакт TX модуля ESP8266 к контакту 9 платы Arduino, а контакт RX модуля ESP8266 к контакту 10 платы Arduino при помощи резисторов.
Wi-Fi модуль ESP8266 обеспечивает нашему устройству доступ в сеть интернет. Это достаточно дешевое устройство, которое можно подключить практически к любому микроконтроллеру, поэтому его так часто используют в проектах интернета вещей.

Внешний вид Wi-Fi модуля ESP8266

Затем необходимо подключить датчик импульсов к плате Arduino. Датчик импульсов имеет три контакта. Подсоедините контакт 5V и землю датчика к контактам 5V и земли платы Arduino, а информационный (сигнальный) контакт датчика – к контакту A0 платы Arduino.

Внешний вид датчика импульсов для измерения сердечного пульса

После этого подсоедините светодиод к контакту 13 платы Arduino. Вам не нужно в данном случае использовать резистор поскольку плата Arduino имеет встроенный резистор на контакте 13.

И, наконец, нам останется только подключить ЖК дисплей к плате Arduino. В схеме необходимо будет сделать следующие соединения ЖК дисплея с платой Arduino:

— pin 1 (VEE) – на землю.
— pin 2 (VDD или VCC) — к 5V.
— pin 3 (V0) – к среднему контакту потенциометра 10 кОм, а остальные 2 контакта потенциометра – к контактам VCC и GND. Потенциометр будет использоваться для управления контрастностью ЖК дисплея. Можно использовать потенциометр с сопротивлением больше чем 10 кОм.
— pin 4 (RS) — к pin 12 платы Arduino.
— pin 5 (Read/Write) – к земле платы Arduino. Он используется редко, поэтому мы и замыкаем его на землю.
— pin 6 (E) – к pin 11 платы Arduino. Контакты RS и E являются управляющими контактами ЖК дисплея и используются для передачи данных и символов.
— далее соединяем 4 контакта данных ЖК дисплея:
pin 11 (D4) — к pin 5 платы Arduino.
pin 12 (D5) — к pin 4 платы Arduino.
pin 13 (D6) — к pin 3 платы Arduino.
pin 14 (D7) — к pin 2 платы Arduino.
— pin 15 — к VCC при помощи резистора 220 Ом. Резистор используется для установки яркости черного цвета ЖК дисплея. Чем больше сопротивление резистора, тем более темным будет черный цвет.
— pin 16 – на землю.

Получившаяся схема устройства представлена на следующем рисунке.

Схема устройства для мониторинга сердечного пульса на Arduino через интернетКонфигурирование сервиса ThingSpeak

Сервис ThingSpeak является очень удобным для проектов из категории интернета вещей. С его помощью можно мониторить данные и управлять нашей системой через сеть интернет, используя каналы и веб-страницы, предоставляемые данным сервисом. Более подробно мы его уже рассматривали в статье про мониторинг состояния погоды через сеть интернет, здесь же ограничимся более кратким его описанием.

Для начала зайдите на ThingSpeak.com и создайте там себе аккаунт (Get Started).

Внешний вид главной страницы сайта thingspeak.comПосле создания аккаунта идите на вкладку каналы (channels) и создайте там себе новый канал. Заполните имя канала другие необходимые поля. Также поставьте галочку напротив ‘Make Public’ (сделать публичным, общедоступным) и сохраните канал (Save the Channel). После этого ваш канал создан.

Создание нового канала в ThingSpeak.com

После этого переключитесь на вкладку API keys и скопируйте оттуда ваш API key – он вам потребуется при написании кода программы.

Получение API ключа в ThingSpeak.com

Принцип работы проекта

Сначала необходимо прикрепить датчик импульсов (Pulse Sensor) к любой части вашего тела в которой можно обнаружить пульс, например, к пальцу. После этого датчик импульсов будет измерять изменения в объеме крови, которые происходят во время каждого сокращения сердечной мышцы. Эти изменения в объеме крови приводят к изменению интенсивности света через эту часть тела. Затем с помощью платы Arduino необходимо всего лишь конвертировать эти изменения в BPM (число ударов сердца в минуту). Светодиод, подключенный к контакту 13, также будет мигать в соответствии с частотой сердечного ритма.

Далее плата Arduino с помощью модуля ESP8266 будет передавать эти данные на сервис ThingSpeak. На сервисе ThingSpeak эти данные будут отображаться в виде графика, который можно будет посмотреть из любой точки мира. Также измеренный пульс (в BPM) будет отображаться на ЖК дисплее нашего устройства.

График сердечного ритма на ThingSpeak.com Отображение частоты сердечного ритма на ЖК дисплее

Исходный код программы

Первым делом при написании программы необходимо подключить все используемые библиотеки. Библиотека последовательной связи (Software serial library) используется для задействования режима последовательной связи (то есть последовательного порта) на контактах 9 и 10 платы Arduino. По умолчанию в плате Arduino для последовательной связи используются контакты 0 и 1, но с помощью Software serial library последовательную связь можно организовать и на других контактах платы Arduino. Также необходимо подключить библиотеку для работы с ЖК дисплеем (LiquidCrystal.h) и указать, к каким контактам платы Arduino подключен ЖК дисплей.

#include <SoftwareSerial.h>
#define DEBUG true
SoftwareSerial esp8266(9,10);
#include <LiquidCrystal.h>
#include <stdlib.h>
LiquidCrystal lcd(12,11,5,4,3,2);

Затем необходимо ввести имя пользователя Wi-Fi, пароль и IP адрес модуля ESP8266. Затем введите API key, который вы получили на сервисе ThingSpeak.

#define SSID "Your Wifi Name"
#define PASS "Your Wifi Password"
#define IP "184.106.153.149"
String msg = "GET /update?key=9YS21NU0HY5YS1IKU";

Следующая часть кода инициализирует ЖК дисплей и устанавливает бодовую скорость передачи. Скорость передачи необходимо установить в соответствии с тем, какую скорость поддерживает ваш модуль ESP8266. Некоторые модули ESP8266 поддерживают скорость передачи 9600 бод/с, некоторые 115200, а некоторые – другую.

void setup()
{
lcd.begin(16, 2);
lcd.print("circuitdigest.com");
delay(100);
lcd.setCursor(0,1);
lcd.print("Connecting...");
Serial.begin(9600); //or use default 115200.
esp8266.begin(9600);
Serial.println("AT");
esp8266.println("AT");
delay(5000);
if(esp8266.find("OK")){
connectWiFi();
}
interruptSetup();
}

Следующая функция void updatebeat() будет передавать данные по IP адресу, который вы ввели, а также устанавливать необходимые значения полей для пульса.

void updatebeat(){
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
Serial.println(cmd);
esp8266.println(cmd);
delay(2000);
if(esp8266.find("Error")){
return;
}
cmd = msg ;
cmd += "&field1=";
cmd += BPM;
..... .....
...... .....

Следующая часть кода соединяет ESP8266 с сетью Wi-Fi, данные для которой вы ввели ранее. Затем эта Wi-Fi сеть будет использоваться для передачи данных на ThingSpeak.

boolean connectWiFi(){
Serial.println("AT+CWMODE=1");
esp8266.println("AT+CWMODE=1");
delay(2000);
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
.... .....
..... .....

Следующая часть кода будет считывать значения с датчика импульсов и конвертировать их в BPM (число ударов в минуту). Также она будет управлять миганием светодиода, подключенного к контакту 13, в соответствии с частотой сердечного ритма.

ISR(TIMER2_COMPA_vect){
cli();
Signal = analogRead(pulsePin);
sampleCounter += 2;
int N = sampleCounter - lastBeatTime;
if(Signal < thresh && N > (IBI/5)*3){
if (Signal < T){
T = Signal;
... ....
...... ..

Далее приведен полный текст программы.

#include <SoftwareSerial.h>
#define DEBUG true
SoftwareSerial esp8266(9,10);
#include <LiquidCrystal.h>
#include <stdlib.h>
LiquidCrystal lcd(12,11,5,4,3,2);
#define SSID "Your Wifi Name" // "SSID-WiFiname" (имя пользователя)
#define PASS "Your Wifi Password" // "password" (пароль)
#define IP "184.106.153.149"// thingspeak.com ip
String msg = "GET /update?key=9YS21NU0HY5YS1IKU"; //change it with your api key like "GET /update?key=Your Api Key" - здесь запишите свой API key с сервиса Thingspeak
//объявление переменных
float temp;
int hum;
String tempC;
int error;
int pulsePin = 0; // датчик импульсов подосоединен к аналоговому контакту 0
int blinkPin = 13; // светодиод подключен к контакту 13
int fadePin = 5;
int fadeRate = 0;
// Volatile Variables, used in the interrupt service routine!
volatile int BPM; // int that holds raw Analog in 0. updated every 2mS
volatile int Signal; // holds the incoming raw data
volatile int IBI = 600; // int that holds the time interval between beats! Must be seeded!
volatile boolean Pulse = false; // "True" when heartbeat is detected. "False" when not a "live beat".
volatile boolean QS = false; // becomes true when Arduino finds a beat.
// Regards Serial OutPut -- Set This Up to your needs
static boolean serialVisual = true; // Set to 'false' by Default. Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse
volatile int rate[10]; // array to hold last ten IBI values
volatile unsigned long sampleCounter = 0; // used to determine pulse timing
volatile unsigned long lastBeatTime = 0; // used to find IBI
volatile int P =512; // used to find peak in pulse wave, seeded
volatile int T = 512; // used to find trough in pulse wave, seeded
volatile int thresh = 525; // used to find instant moment of heart beat, seeded
volatile int amp = 100; // used to hold amplitude of pulse waveform, seeded
volatile boolean firstBeat = true; // used to seed rate array so we startup with reasonable BPM
volatile boolean secondBeat = false; // used to seed rate array so we startup with reasonable BPM
void setup()
{
lcd.begin(16, 2);
lcd.print("circuitdigest.com");
delay(100);
lcd.setCursor(0,1);
lcd.print("Connecting...");
Serial.begin(9600); //или использовать скорость по умолчанию 115200.
esp8266.begin(9600);
Serial.println("AT");
esp8266.println("AT");
delay(5000);
if(esp8266.find("OK")){
connectWiFi();
}
interruptSetup();
}
void loop(){
lcd.clear();
start: //label
error=0;
lcd.setCursor(0, 0);
lcd.print("BPM = ");
lcd.print(BPM);
delay (100);
lcd.setCursor(0, 1); // установим курсор в столбец 0, строку 2
delay(1000);
updatebeat();
//повторно передаем если передача не завершена
if (error==1){
goto start; //переход к метке "start"
}
delay(1000);
}
void updatebeat(){
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += IP;
cmd += "\",80";
Serial.println(cmd);
esp8266.println(cmd);
delay(2000);
if(esp8266.find("Error")){
return;
}
cmd = msg ;
cmd += "&field1=";
cmd += BPM;
cmd += "\r\n";
Serial.print("AT+CIPSEND=");
esp8266.print("AT+CIPSEND=");
Serial.println(cmd.length());
esp8266.println(cmd.length());
if(esp8266.find(">")){
Serial.print(cmd);
esp8266.print(cmd);
}
else{
Serial.println("AT+CIPCLOSE");
esp8266.println("AT+CIPCLOSE");
//Resend...
error=1;
}
}
boolean connectWiFi(){
Serial.println("AT+CWMODE=1");
esp8266.println("AT+CWMODE=1");
delay(2000);
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
Serial.println(cmd);
esp8266.println(cmd);
delay(5000);
if(esp8266.find("OK")){
Serial.println("OK");
return true;
}else{
return false;
}
}
void interruptSetup(){
TCCR2A = 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE
TCCR2B = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER
OCR2A = 0X7C; // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE
TIMSK2 = 0x02; // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A
sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED
}
ISR(TIMER2_COMPA_vect){ // triggered when Timer2 counts to 124
cli(); // disable interrupts while we do this
Signal = analogRead(pulsePin); // read the Pulse Sensor
sampleCounter += 2; // keep track of the time in mS
int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise
// find the peak and trough of the pulse wave
if(Signal < thresh && N > (IBI/5)*3){ // avoid dichrotic noise by waiting 3/5 of last IBI
if (Signal < T){ // T is the trough
T = Signal; // keep track of lowest point in pulse wave
}
}
if(Signal > thresh && Signal > P){ // thresh condition helps avoid noise
P = Signal; // P is the peak
} // keep track of highest point in pulse wave
// NOW IT'S TIME TO LOOK FOR THE HEART BEAT
// signal surges up in value every time there is a pulse
if (N > 250){ // avoid high frequency noise
if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){
Pulse = true; // set the Pulse flag when there is a pulse
digitalWrite(blinkPin,HIGH); // включаем светодиод, подключенный к контакту 13
IBI = sampleCounter - lastBeatTime; // время между ударами в mS
lastBeatTime = sampleCounter; // keep track of time for next pulse
if(secondBeat){ // if this is the second beat
secondBeat = false; // clear secondBeat flag
for(int i=0; i<=9; i++){ // seed the running total to get a realistic BPM at startup
rate[i] = IBI;
}
}
if(firstBeat){ // if it's the first time beat is found
firstBeat = false; // clear firstBeat flag
secondBeat = true; // set the second beat flag
sei(); // разрешаем прерывания
return; // IBI value is unreliable so discard it
}
word runningTotal = 0; // clear the runningTotal variable
for(int i=0; i<=8; i++){ // shift data in the rate array
rate[i] = rate[i+1]; // and drop the oldest IBI value
runningTotal += rate[i]; // add up the 9 oldest IBI values
}
rate[9] = IBI; // add the latest IBI to the rate array
runningTotal += rate[9]; // add the latest IBI to runningTotal
runningTotal /= 10; // average the last 10 IBI values
BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM!
QS = true; // set Quantified Self flag
// QS FLAG IS NOT CLEARED INSIDE THIS ISR
}
}
if (Signal < thresh && Pulse == true){ // when the values are going down, the beat is over
digitalWrite(blinkPin,LOW); // turn off pin 13 LED
Pulse = false; // reset the Pulse flag so we can do it again
amp = P - T; // get amplitude of the pulse wave
thresh = amp/2 + T; // set thresh at 50% of the amplitude
P = thresh; // reset these for next time
T = thresh;
}
if (N > 2500){ // if 2.5 seconds go by without a beat
thresh = 512; // set thresh default
P = 512; // set P default
T = 512; // set T default
lastBeatTime = sampleCounter; // bring the lastBeatTime up to date
firstBeat = true; // set these to avoid noise
secondBeat = false; // when we get the heartbeat back
}
sei();
// разрешаем прерывания когда все сделано
}// end isr

Видео, демонстрирующее работу схемы

(1 голосов, оценка: 5,00 из 5)
Загрузка...
61 просмотров

Комментарии

Мониторинг сердечного пульса на Arduino через интернет — 1 комментарий

  1. Статья переведена с иностранного сайта, комментарии к основному тексту программы почти не переводил. Но если статья вызовет интерес (напишите об этом в комментариях здесь), то готов перевести их. Ну и если есть какие-либо вопросы по теме статьи, также готов помочь разобраться в них

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *