로라(LoRa) 기반 코로나19 환자 원격 모니터링 시스템
부품 및 소모품
| 더 씽즈 네트워크(The Things Network) 더 씽즈 우노 (LoRa 개발 보드) |
1개 |
| 더 씽즈 네트워크 더 씽즈 게이트웨이 |
1개 |
| 맥심 인터그레이티드 MAXREFDES117# 심박수 및 펄스 옥시메트리 모니터 개발 플랫폼 |
1개 |
| 씨드 그로브 온도 센서 |
1개 |
| 점퍼 와이어 (일반) |
1세트 |
| DF로봇 그래비티 디지털 푸시 버튼 (옐로우) |
1개 |
| 씨드 그로브 진동 센서 (SW-420) |
1개 |
| 부저 |
1개 |
| LED (일반) |
1개 |
| 씨드 그로브 온도, 습도, 기압, 가스 센서 (BME680) |
1개 |
필수 도구 및 기계
앱 및 온라인 서비스
- 안드로이드 스튜디오
- 아두이노 웹 에디터
- 아마존 웹 서비스 AWS IoT
- 마이크로소프트 비주얼 스튜디오 코드 아두이노 확장
프로젝트 소개
요약
센서 기반 연결 네트워크를 통해 환자 건강 상태를 자동 모니터링하는 지능형 환자 모니터링 시스템을 제안합니다. 이 시스템은 코로나19 환자를 위해 특별히 설계되었습니다. 여러 센서로 환자의 생체 정보를 수집하고, 의미 있는 생체 정보를 IoT 클라우드로 전송합니다. 시스템은 센서 데이터 처리로 환자의 위급 상황을 감지하고 의사/간호사 및 병원 담당자에게 즉각 푸시 알림을 보냅니다. 의사와 간호사는 해당 환자를 직접 방문하지 않고 원격으로 관찰할 수 있어 혜택을 봅니다. 환자 가족도 제한적 접근으로 혜택을 볼 수 있습니다.
설명
씽즈 우노(LoRa 개발 보드)를 이 모니터링 시스템의 메인 컨트롤러로 사용했습니다. 씽즈 우노 보드가 다양한 센서(하드웨어 구성품 리스트 섹션 참조)에서 환자 건강 파라미터 정보를 수집합니다. 씽즈 우노는 데이터를 로라 게이트웨이(씽즈 게이트웨이)로 전송하는 역할도 합니다. 로라 게이트웨이는 AWS 클라우드와 연결됩니다. AWS IoT 클라우드 플랫폼을 이 시스템의 IoT 클라우드로 사용했습니다.
하드웨어 구성품 리스트
이미지 참조
환자의 응급 상황은 간단한 수학 공식(식-I)으로 판단합니다:
수식 이미지 참조
임계값 레벨에 대한 수학적 표기법 세부사항은 표-1에 설명되어 있습니다.
표 이미지 참조
센서 데이터 시각화를 위한 모바일 애플리케이션을 개발했습니다. 다양한 차트와 게이지로 실시간 센서 데이터(환자의 현재 건강 파라미터/현재 건강 상태)를 표시합니다. 이 앱으로 의사나 간호사가 ICU 유닛을 직접 방문하지 않고 환자를 원격 모니터링할 수 있습니다. 시스템의 지능적 특성으로 센서 데이터 처리 후 식-I이 환자의 응급 상황을 판단하면 해당 의사/간호사에게 푸시 알림을 보냅니다. 병원 담당자(ICU 담당자)도 웹 기반 클라우드 연결 데스크톱 애플리케이션으로 여러 환자를 동시에 지속 모니터링해 ICU 효율성을 높입니다. 모든 애플리케이션이 IoT 클라우드에 연결돼 게이지, 스파크라인, 텍스트 등 다양한 차트 유형으로 실시간 데이터를 시각화합니다.
결론
이 프로젝트에서 설명한 제안 시스템으로 의사/간호사 및 병원 담당자가 ICU 환자를 실시간 모니터링할 수 있어 효율성과 서비스 품질이 향상됩니다. 이 시스템을 웨어러블 기기로 개조할 엄청난 기회가 있으며, 이를 통해 노인이나 아기를 어디서든 원격 모니터링할 수 있게 됩니다.
참고문헌
1. Uddin, M. S., Alam, J. B., & Banu, S. (2017, September). Real time patient monitoring system based on internet of things. In 2017 4th International Conference on Advances in Electrical Engineering (ICAEE) (pp. 516-521). IEEE. DOI: 10.1109/ICAEE.2017.8255410
코드
소스 (아두이노)
#include
#include
#include
#include
#include
// AppEUI와 AppKey 설정
const char *appEui = "0000000000000000";
const char *appKey = "00000000000000000000000000000000";
#define loraSerial Serial1
#define debugSerial Serial
// REPLACE_ME를 TTN_FP_EU868 또는 TTN_FP_US915로 교체
#define freqPlan REPLACE_ME
// 센서 데이터 보관 변수
int bpm;
int spo2;
float temp;
Adafruit_BME280 bme; // BME280 센서 선언
unsigned long currentMillis; // 현재 시간 보관
// 펄스 옥시미터 측정 주기
#define REPORTING_PERIOD_MS 1000
PulseOximeter pox;
uint32_t tsLastReport = 0;
// 펄스 감지 시 호출되는 콜백 (아래 등록)
void onBeatDetected() {
// Serial.println("Beat!");
}
void measured_pulse() {
pox.update();
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
bpm = pox.getHeartRate();
tsLastReport = millis();
}
}
TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan);
void setup() {
loraSerial.begin(57600);
debugSerial.begin(9600);
// 시리얼 모니터 최대 10초 대기
while (!debugSerial && millis() < 10000);
debugSerial.println("-- STATUS");
ttn.showStatus();
debugSerial.println("-- JOIN");
ttn.join(appEui, appKey);
Serial.println(F("BME280 test"));
Serial.println("Initializing MAX30100");
pox.begin();
pox.setOnBeatDetectedCallback(onBeatDetected);
bool status;
status = bme.begin();
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
pinMode(7, OUTPUT);
pinMode(A0, INPUT);
pinMode(8, INPUT);
pinMode(6, INPUT);
}
void loop() {
debugSerial.println("-- LOOP");
int h_rate = analogRead(A0);
int button = digitalRead(8);
float temperature = pox.getTemperature();
spo2 = pox.getSpO2();
bpm = bpm;
float humidity = bme.readHumidity();
int movement = digitalRead(6);
byte payload[7]; // 원본 payload[6]인데 7개 데이터 저장하므로 크기 7로 수정 필요
payload[0] = highByte(bpm);
payload[1] = lowByte(temperature);
payload[2] = highByte(humidity);
payload[3] = lowByte(movement);
payload[4] = lowByte(spo2);
payload[5] = lowByte(button);
payload[6] = lowByte(h_rate);
debugSerial.print("Temperature: ");
debugSerial.println(temperature);
debugSerial.print("Humidity: ");
debugSerial.println(humidity);
debugSerial.print("BPM: ");
debugSerial.println(bpm);
debugSerial.print("SPO2: ");
debugSerial.println(spo2);
debugSerial.print("H_rate: ");
debugSerial.println(h_rate);
debugSerial.print("Button: ");
debugSerial.println(button);
debugSerial.print("Movement: ");
debugSerial.println(movement);
ttn.sendBytes(payload, sizeof(payload));
delay(20000);
}
주의: 원본 코드에서 `payload[6]` 배열 크기가 6인데 7개 인덱스(0~6) 사용으로 버퍼 오버플로 위험. `byte payload[7]`로 수정 필요.
회로도
회로도 이미지 참조