귀엽고 심플한 심박수&산소포화도 측정기 만들기

by 조혜인 | 2017-02-28 19:12
healthcare smart 산소 스마트 심박수 측정 헬스케어

재료

  • 점퍼케이블 (해외) 1개 (1000원)
  • 0.91" OLED display with I2C interface (해외) 1개 (8000원)
  • 점퍼케이블 (국내) 1개 (1210원)
  • Heart Rate / Pulse Oximetry Sensor breakout (국내) 1개 (7700원)
  • 아두이노 나노 (해외) 1개 (1000원)
  • 0.91" OLED display with I2C interface (국내) 1개 (12100원)
  • 아두이노 나노 (국내) 1개 (5190원)

간단하고 저비용으로 만들 수 있는 심박수 측정기 레퍼런스를 발견해 소개해 드립니다.

(Arduino Heart Rate Monitor)

이 간단하고 저렴한 프로젝트는 MAX30100 센서 브레이크 아웃 보드 이용합니다.  작은 0.91 "OLED 디스플레이를 사용하여 심박수 및 산소 수준을 표시합니다. 모듈들이 I2C 인터페이스를 가지고 있어서 배선도 최소화 할 수 있습니다. 심장박동을 재는 데, 전자부품이 너무 크다거나 전선이 너덜너덜하면 불편하겠죠? 아주 앙증맞고 간편한 심박수 제조기를 만들 수 있을 것 같습니다. Enclosure는 없는 프로젝트 입니다.


1. 준비물

- 아두이노 나노 1$ 
- 0.91" OLED display with I2C interface 7.50$
- Heart Rate / Pulse Oximetry Sensor breakout 9.95$
- Dupont Cable 0.99$



2. 만드는 과정

STEP 1. 회로 구성하기

다음과 같이 회로를 구성합니다. 

- OLED 디스플레이 & MAX30100 모듈 (GND, VCC, SDA, SCL) ----- 아두이노

- I2C 인터페이스의 데이터 라인은 사용중인 Arduino 보드의 버전에 따라 달라집니다.
Nano는 SDA에는 A4, SCL에는 A5를 사용하고 있습니다.




STEP 2. 코드 업로드

다음 코드를 이용하세요. Github에서 직접 다운로드 받으셔도 됩니다.

// Sample implementation of the MAX30100 PulseOximeter
// Using the following module
// http://www.ebay.com/itm/-/391709438817?ssPageName=STRK:MESE:IT
// can not gaurantee if the app will work with other implementations of the module.

#include "MAX30100_PulseOximeter.h"
#include <U8g2lib.h>
#include <Wire.h>

#define REPORTING_PERIOD_MS 500
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0);

// PulseOximeter is the higher level interface to the sensor
// it offers:
// * beat detection reporting
// * heart rate calculation
// * SpO2 (oxidation level) calculation
PulseOximeter pox;

const int numReadings=10;
float filterweight=0.5;
uint32_t tsLastReport = 0;
uint32_t last_beat=0;
int readIndex=0;
int average_beat=0;
int average_SpO2=0;
bool calculation_complete=false;
bool calculating=false;
bool initialized=false;
byte beat=0;

// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
show_beat();
last_beat=millis();
}

void show_beat()
{
u8g2.setFont(u8g2_font_cursor_tf);
u8g2.setCursor(8,10);
if (beat==0) {
u8g2.print("_");
beat=1;
}
else
{
u8g2.print("^");
beat=0;
}
u8g2.sendBuffer();
}

void initial_display()
{
if (not initialized)
{
u8g2.clearBuffer();
show_beat();
u8g2.setCursor(24,12);
u8g2.setFont(u8g2_font_smart_patrol_nbp_tf);
u8g2.print("Place finger");
u8g2.setCursor(0,30);
u8g2.print("on the sensor");
u8g2.sendBuffer();
initialized=true;
}
}

void display_calculating(int j)
{
if (not calculating) {
u8g2.clearBuffer();
calculating=true;
initialized=false;
}
show_beat();
u8g2.setCursor(24,12);
u8g2.setFont(u8g2_font_smart_patrol_nbp_tf);
u8g2.print("Measuring");
u8g2.setCursor(0,30);
for (int i=0;i<=j;i++) {
u8g2.print(". ");
}
u8g2.sendBuffer();
}
void display_values()
{
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_smart_patrol_nbp_tf);

u8g2.setCursor(65,12);
u8g2.print(average_beat);
u8g2.print(" Bpm");
u8g2.setCursor(0,30);
u8g2.print("SpO2 ");
u8g2.setCursor(65,30);
u8g2.print(average_SpO2);
u8g2.print("%");
u8g2.sendBuffer();
}

void calculate_average(int beat, int SpO2)
{
if (readIndex==numReadings) {
calculation_complete=true;
calculating=false;
initialized=false;
readIndex=0;
display_values();
}

if (not calculation_complete and beat>30 and beat<220 and SpO2>50) {
average_beat = filterweight * (beat) + (1 - filterweight ) * average_beat;
average_SpO2 = filterweight * (SpO2) + (1 - filterweight ) * average_SpO2;
readIndex++;
display_calculating(readIndex);
}
}

void setup()
{
Serial.begin(115200);
u8g2.begin();
pox.begin();
pox.setOnBeatDetectedCallback(onBeatDetected);
initial_display();
}

void loop()
{
// Make sure to call update as fast as possible
pox.update();
if ((millis() - tsLastReport > REPORTING_PERIOD_MS) and (not calculation_complete)) {
calculate_average(pox.getHeartRate(),pox.getSpO2());
tsLastReport = millis();
}
if ((millis()-last_beat>10000)) {
calculation_complete=false;
average_beat=0;
average_SpO2=0;
initial_display();
}
}

















































































































































3. 이용방법

1) 시작시, 디스플레이는 사용자에게 손가락을 센서에 놓으라는 메시지를 표시합니다. 심박수를 감지하면 이를 표시하기 위해 디스플레이의 하트 심볼을 업데이트하고 판독 값 기록을 시작합니다.

2) 내 구현에서는 임계 값을 벗어나는 모든 측정 값을 필터링 한 다음 심박수와 SpO2 값의 평균을 계산하고 마지막으로 OLED에 표시합니다.

3) 손가락이 센서에 남아 있고 센서가 하트 비트를 감지하면 디스플레이에 결과가 계속 표시됩니다.

4) 센서가 10 초 동안 하트 비트를 감지하지 못하면 센서는 프로세스를 다시 시작하고 사용자에게 다시 읽도록 요청합니다.


4. 결과

정말 간단하고 귀여운 심박수 측정기가 완성되었네요. 교육용으로 이용해도 좋을 듯합니다. 간단한 Enclosure를 만들어 목걸이나 팔찌같은 악세서리로 만들어도 좋을 것 같네요!

댓글 0

스마트 헬스케어

귀엽고 심플한 심박수&산소포화도 측정기 만들기

by 조혜인

MADE BY

조혜인

arduino, processing, rhino, sketchup, 아두이노, 에프터이펙트, 포토샵, 프리미어
귀엽고 심플한 심박수&산소포화도 측정기 만들기현재글