아두이노, 블루투스, 센서를 활용한 스마트 건강 모니터링 스테이션
부품 및 소모품
| 부품 |
수량 |
| 아두이노 우노 (Arduino UNO) |
1 |
| 점퍼 와이어 (일반) |
1 |
| DHT11 온도 및 습도 센서 (3핀) |
1 |
| 온도 센서 (LM35 등) |
1 |
| 저항 10kΩ |
2 |
| HC-05 블루투스 모듈 |
1 |
| 심박수 센서 |
1 |
앱 및 온라인 서비스
- MIT App Inventor 2 - 안드로이드 앱 개발
- 아두이노 IDE - 코드 작성 및 업로드
프로젝트 개요
센서와 블루투스 통신, 전용 앱을 결합하여 건강 상태와 주변 환경 파라미터를 손쉽게 모니터링할 수 있는 스마트 건강 스테이션을 구축합니다. 아두이노 우노를 메인 컨트롤러로 사용하며, 온도, 습도, 심박수 데이터를 실시간으로 수집하여 블루투스를 통해 스마트폰 앱으로 전송합니다.
회로도 및 연결
제공된 회로도 이미지들을 참고하여 다음과 같이 연결합니다:
- DHT11 센서: 데이터 핀을 디지털 핀 7에 연결, VCC와 GND 연결
- 온도 센서 (LM35): 출력 핀을 아날로그 핀에 연결
- 심박수 센서: 아날로그 핀 0 (A0)에 연결
- HC-05 블루투스 모듈: TX→디지털 10, RX→디지털 9 (SoftwareSerial 사용)
- LED (핀 13): 심박 감지 표시용
작동 원리
아두이노는 타이머 인터럽트(Timer2)를 사용하여 심박수 센서 신호를 2ms 간격으로 샘플링합니다. 피크 검출 알고리즘으로 심박 간격(IBI)을 계산하고 BPM(분당 박동수)을 도출합니다. 동시에 DHT11에서 온습도, LM35에서 온도를 읽어옵니다. 모든 데이터는 시리얼 모니터와 블루투스를 통해 동시 출력됩니다.
소스 코드
#include <SoftwareSerial.h>
#include <cactus_io_AM2302.h>
#define AM2302_PIN 7
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
AM2302 dht(AM2302_PIN);
SoftwareSerial Bluetooth(10, 9); // RX, TX
String Data;
int pulsePin = 0;
int blinkPin = 13;
volatile int BPM;
volatile int Signal;
volatile int IBI = 600;
volatile boolean Pulse = false;
volatile boolean QS = false;
volatile int rate[10];
volatile unsigned long sampleCounter = 0;
volatile unsigned long lastBeatTime = 0;
volatile int P = 512;
volatile int T = 512;
volatile int thresh = 512;
volatile int amp = 100;
volatile boolean firstBeat = true;
volatile boolean secondBeat = false;
void interruptSetup() {
TCCR2A = 0x02;
TCCR2B = 0x06;
OCR2A = 0X7C;
TIMSK2 = 0x02;
sei();
}
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;
}
if (Signal > thresh && Signal > P) P = Signal;
if (N > 250) {
if ((Signal > thresh) && (Pulse == false) && (N > (IBI / 5) * 3)) {
Pulse = true;
digitalWrite(blinkPin, HIGH);
IBI = sampleCounter - lastBeatTime;
lastBeatTime = sampleCounter;
if (secondBeat) {
secondBeat = false;
for (int i = 0; i <= 9; i++) rate[i] = IBI;
}
if (firstBeat) {
firstBeat = false;
secondBeat = true;
sei();
return;
}
word runningTotal = 0;
for (int i = 0; i <= 8; i++) {
rate[i] = rate[i + 1];
runningTotal += rate[i];
}
rate[9] = IBI;
runningTotal += rate[9];
runningTotal /= 10;
BPM = 60000 / runningTotal;
QS = true;
}
}
if (Signal < thresh && Pulse == true) {
digitalWrite(blinkPin, LOW);
Pulse = false;
amp = P - T;
thresh = amp / 2 + T;
P = thresh;
T = thresh;
}
if (N > 2500) {
thresh = 512;
P = 512;
T = 512;
lastBeatTime = sampleCounter;
firstBeat = true;
secondBeat = false;
}
sei();
}
void setup() {
Bluetooth.begin(9600);
Serial.begin(9600);
dht.begin();
sensors.begin();
interruptSetup();
}
void loop() {
sensors.requestTemperatures();
dht.readHumidity();
dht.readTemperature();
if (isnan(dht.humidity) || isnan(dht.temperature_C)) return;
if (QS == true) {
Serial.print(sensors.getTempCByIndex(0));
Serial.print(" ");
Serial.print(dht.temperature_C);
Serial.print(" ");
Serial.print(dht.humidity);
Serial.print(" ");
Serial.println(BPM);
Bluetooth.print(sensors.getTempCByIndex(0));
Bluetooth.print(" ");
Bluetooth.print(dht.temperature_C);
Bluetooth.print(" ");
Bluetooth.print(dht.humidity);
Bluetooth.print(" ");
Bluetooth.println(BPM);
QS = false;
}
delay(1500);
}
앱 개발 (MIT App Inventor 2)
블루투스 클라이언트 컴포넌트를 사용하여 아두이노로부터 수신한 데이터를 파싱하여 화면에 표시합니다. 수신 문자열을 공백 기준으로 분할하여 체온, 주변 온도, 습도, 심박수를 각각 라벨에 업데이트합니다.
GitHub 저장소
전체 코드와 앱 소스: github.com/dikhalipina/Tutorials-for-arduino