아두이노 프로젝트 6. 심장 박동 측정: 두 판 사이의 차이

아두위키 : Arduwiki
잔글편집 요약 없음
148번째 줄: 148번째 줄:
[[파일:장치관리자 확인.png|가운데|class=coders100]]
[[파일:장치관리자 확인.png|가운데|class=coders100]]


== '''아두이노 시작''' ==
 
<syntaxhighlight lang="c++" line="1">
== '''라이브러리 설치''' ==
이번 코드를 사용하기 위한 라이브러리를 설치합니다.
 
== '''아두이노 코드''' ==
라이브러리를 모두 설치하셨다면 아래 코드를 아두이노에 업로드해주세요. '''(단축키 : CTRL + U)'''<syntaxhighlight lang="c++" line="1">
/* 스마트 지팡이 프로젝트
/* 스마트 지팡이 프로젝트
사용 부품
사용 부품
334번째 줄: 338번째 줄:
</syntaxhighlight>
</syntaxhighlight>


=== 장애물 감지 시 진동 기능 ===
[[초음파 센서(HC-SR04)]]를 상단과 하단에 각각 하나씩 부착하여 장애물 감지 거리 구간에 따라 부착된 [[소형 진동 모터 1027|소형 진동 모터]]의 세기를 조절합니다.


[[소형 진동 모터 1027|소형 진동 모터]]의 경우 진동 세기가 잘 체감될 수 있도록 지팡이의 손잡이에 부착합니다.


=== 주변 밝기 확인 및 네오픽셀 점등 ===
== '''결과''' ==
[[조도 센서(CDS)]]를 활용해 주변의 밝기를 확인한 후 주변 사람들이 인지할 수 있도록 지팡이에 부착한 네오픽셀이 점등됩니다.
OLED의 플리커링 현상으로 인해 사진 상으로 잘 담기지 않아 그림으로 대체합니다.


이를 통해 시야 불명에 의한 충돌 사고를 대비합니다.


=== 안드로이드 앱을 통한 문자 전송 ===
[[파일:심박결과.png|671x671픽셀]]
[[HC-06 블루투스 모듈]]을 활용해 스마트폰의 앱에 연결합니다.


지팡이에는 3개의 [[택트 스위치(Tact Switch)|택트 스위치]]가 부착되어 있으며 각각 "목적지로 출발", "목적지에 도착", "현재 위치" 신호의 역할을 합니다.
=== 심박수 측정 ===
 
심박 펄스 센서를 통해 심박수를 측정하여 OLED에 출력합니다.
앱에서 택트 스위치 신호를 수신했다면 미리 설정된 전화번호로 문자를 송신합니다.
 
[[파일:스마트_지팡이_어플_캡처.png]]
 
== '''결과''' ==
=== 사진 ===
[[파일:스마트_지팡이_완성_사진1.png|가운데|클래스=coders100]]


=== Comment ===
아래 파형을 통해 심박을 함께 확인할 수 있습니다.
완성된 지팡이의 모습입니다.


불을 끈 어두운 환경에서는 지팡이에 길에 부착된 [[네오픽셀(WS2812)|네오픽셀]]이 점등한 모습을 확인할 수 있습니다.
=== BPM에 따른 네오픽셀 점등 ===
심박수에 따라 네오픽셀이 점등되어 게이지의 역할을 합니다.


상단, 하단에 [[초음파 센서(HC-SR04)|초음파 센서]]가 하나씩 부착되어 장애물을 감지하며 작은 동그란 [[소형 진동 모터 1027|소형 진동 모터]]가 손잡이 끝에 부착되어 진동합니다.
심박 구간에 따라 각기 다른 색의 LED가 켜집니다.


[[택트 스위치(Tact Switch)|택트 스위치]]는 손잡이에 부착되어 사용자가 쉽게 누르고, 누르면 문자가 발송됩니다.


== '''추신''' ==
== '''추신''' ==

2025년 5월 15일 (목) 17:41 판


개요

심장 박동 측정하기

손가락에 심장 박동 측정 센서를 끼워 심장 박동을 측정하고, 파형을 그립니다.

고려사항

  • 심박 펄스 센서를 활용해 심박을 측정하고, raw data를 활용해 bpm을 계산합니다.
  • 계산된 bpm과 bpm을 활용한 파형을 OLED에 표시해 심박을 확인합니다.
  • 12bit 네오픽셀을 활용해 심박 구간에 따라 다른 색깔로 표시되는 게이지를 표현합니다.

사용 하드웨어


제작과정

1. MDF 확인

4개의 MDF 판이 준비되어 있습니다.

2. OLED 케이블

먼저 OLED에 연결된 케이블을 상판 홀에 통과시켜주세요. OLED는 아직 붙이지 않으셔도 됩니다.

3. 네오픽셀, OLED 결합

네오픽셀을 그림에 맞춰 부착(연결된 케이블이 위로 향하도록)하신 후 OLED를 네오픽셀 안에 부착해주세요. 부품마다 양면테이프가 붙어있습니다.

4. 아두이노 나노, 브레드보드 준비

회로를 구성하기에 앞서 먼저 아래 그림과 같이 아두이노 나노를 미니 브레드보드에 꽂아주세요.

손을 다치지 않게 조심하고, 나노의 평평한 면을 눌러서 꽂아주시면 됩니다.


5. 회로 구성

아무것도 없는 깨끗한 하트 판에 브레드보드를 부착해주세요.


심박 펄스 센서의 -, +, S 위치는 다음과 같습니다.


아래 표와 회로도에 따라 회로를 구성해주세요.

아두이노 나노 심박 펄스 센서 OLED 네오픽셀
A0 S
A4 SCK
A5 SCA
D6 DI
5V + VDD 5V
GND - GND GND

6. 옆 면 조립

남아있는 옆 면을 활용해 MDF판을 모두 결합해주세요.


조립 시에 케이블은 동그랗게 잘 말아서 정리해주세요. 동봉된 핀을 홀에 꽂아주면 완성입니다.


아두이노 IDE

아두이노(Arduino) IDE(통합 개발 환경)는 아두이노 마이크로컨트롤러를 프로그래밍하기 위한 소프트웨어 환경을 제공하는 툴입니다.

아두이노는 오픈 소스 하드웨어 플랫폼으로, 다양한 프로젝트에서 사용되는 간단한 컴퓨팅 장치를 제작하고 프로그래밍하는 데 사용됩니다.

C++를 기반으로 합니다.

설치

1. 아두이노 홈페이지 접속

2. Software 탭 클릭



3. 원하는 버전 다운로드

  • 2021년 아두이노 IDE 2.0 버전이 출시되면서 기존의 1.x 버전, 새로운 2.x 버전 다운로드가 가능합니다.
  • 2.x 버전에서 여러가지 편의기능들이 추가되었지만 기존의 1.x 버전이 익숙하신 분, 1.x 버전으로 수록된 책이나 참고 자료를 그대로 따라하고 싶으신 분들은 1.x 버전을 그대로 사용하셔도 무방합니다.
  • 사용 중인 운영체제에 맞는 버전으로 설치파일을 다운로드 받은 후, 실행하여 설치해주세요.


사용

1. 설치된 아두이노 IDE를 실행합니다.

2. 컴퓨터(혹은 노트북)에 아두이노 보드를 연결합니다.

3. 아두이노 정품 보드가 아닌 호환 보드의 경우 별도로 드라이버를 설치하셔야 합니다. 드라이버 설치 가이드

4. 아두이노 IDE에서 아두이노 보드와 포트를 설정합니다.


  • 보드는 현재 사용 중인 아두이노 보드의 종류에 맞게 선택해주시면 됩니다.
  • 포트 번호를 잘 모르시는 경우에는 장치 관리자에서 확인해주시면 됩니다.


라이브러리 설치

이번 코드를 사용하기 위한 라이브러리를 설치합니다.

아두이노 코드

라이브러리를 모두 설치하셨다면 아래 코드를 아두이노에 업로드해주세요. (단축키 : CTRL + U)

/* 스마트 지팡이 프로젝트
사용 부품
- Arduino nano
- 조도센서(cds)
- 저항(1k옴)
- 초음파 센서(HC-SR04) 2개
- 진동모터
- NeoPixel 바
- 버튼 3개
- 블루투스 모듈(HC-06)

기능
- 어두울 시 NeoPixel 점등
- 버튼으로 보호자 문자 발송 기능 : 블루투스 모듈로 지팡이 사용자의 스마트폰에 연결
  - 버튼 1 : 출발 문자 발송
  - 버튼 2 : 도착 문자 발송
  - 버튼 3 : 위험 및 현재 위치 문자 발송
- 초음파센서로 물체 감지
  - 초음파 센서 사양(2cm ~ 400cm 거리의 물체 감지)으로 10cm ~ 350cm 의 구간만 구별 가능하게 하였으며 350 초과시 350, 10 미만 시 10으로 측정되도록 지정
  - 알람(진동)단계별 세기 기능
  - 단위 [cm], 단계가 높아질수록 진동의 세기가 강해짐
    1단계 100 ~ 80
    2단계 80 ~ 60
    3단계 60 ~ 40
    4단계 40 ~ 20
    5단계 0 ~ 20
*/


#include <Adafruit_NeoPixel.h>

#include <SoftwareSerial.h>

#define trigPin_1 3   //1번초음파(상단) trig핀번호
#define echoPin_1 4   //1번초음파(상단) echo핀번호
#define trigPin_2 6   //2번초음파(하단) trig핀번호
#define echoPin_2 7   //2번초음파(하단) echo핀번호
#define vibratePin 5  //진동센서 핀번호(PWM)
#define cds A0        //조도센서 핀번호
#define neoPixel 2    //네오픽셀 핀번호
#define hc06Rx 10     //블루투스 rx 핀번호
#define hc06Tx 9      //블루투스 tx 핀번호
#define btn1 8        //버튼 핀번호(출발)
#define btn2 11       //버튼 핀번호(도착)
#define btn3 12       //버튼 핀번호(긴급)
#define NumPixel 23    //네오픽셀 갯수
#define bright 255    //네오픽셀 밝기

SoftwareSerial BTSerial(hc06Tx, hc06Rx);

Adafruit_NeoPixel neo(NumPixel, neoPixel, NEO_GRB + NEO_KHZ800);

int Btn1, Btn2, Btn3;

double distance_now_top = 0;  //현재 장애물과의 거리 변수
double distance_now_bot = 0;  //현재 장애물과의 거리 변수
int vibratePower = 255;       //진동 세기 변수(0~255)
int vibrateTime = 150;        //진동 유지 시간[ms]
double alert_distance = 100;  //알람작동 거리[cm]

int btnFlg1 = 0;
int btnFlg2 = 0;
int btnFlg3 = 0;
int btn1Chk() {
  if (digitalRead(btn1) == 0) {
    btnFlg1 = 1;
    return 0;
  }
  if (btnFlg1 == 1) {
    btnFlg1 = 0;
    return 1;
  }
  return 0;
}

int btn2Chk() {
  if (digitalRead(btn2) == 0) {
    btnFlg2 = 1;
    return 0;
  }
  if (btnFlg2 == 1) {
    btnFlg2 = 0;
    return 1;
  }
  return 0;
}

int btn3Chk() {
  if (digitalRead(btn3) == 0) {
    btnFlg3 = 1;
    return 0;
  }
  if (btnFlg3 == 1) {
    btnFlg3 = 0;
    return 1;
  }
  return 0;
}


void BTsignal() {
  if (btn1Chk() == 1) BTSerial.println('1');
  else if (btn2Chk() == 1) BTSerial.println('2');
  else if (btn3Chk() == 1) BTSerial.println('3');
}

void setup() {
  BTSerial.begin(9600);
  pinMode(btn1, INPUT_PULLUP);
  pinMode(btn2, INPUT_PULLUP);
  pinMode(btn3, INPUT_PULLUP);
  pinMode(cds, INPUT);
  pinMode(vibratePin, OUTPUT);
  digitalWrite(vibratePin, LOW);
  pinMode(trigPin_1, OUTPUT);
  pinMode(echoPin_1, INPUT);
  pinMode(trigPin_2, OUTPUT);
  pinMode(echoPin_2, INPUT);
  digitalWrite(trigPin_1, LOW);
  digitalWrite(trigPin_2, LOW);
  neo.begin();
  neo.setBrightness(bright);
  neo.clear();
  neo.show();
}

void loop() {
  BTsignal();                                         //블루투스 모듈
  cdsNeo(NumPixel);                                   //조도값 낮을 시 neopixel ON
  distance_now_top = distance(trigPin_1, echoPin_1);  //상단 초음파 센서 장애물 거리
  distance_now_bot = distance(trigPin_2, echoPin_2);  //하단 초음파 센서 장애물 거리

  distance_interval(distance_now_top, distance_now_bot);  //상단 초음파 센서
  distance_interval(distance_now_bot, distance_now_top);  //하단 초음파 센서
  delay(vibrateTime);
}

void distance_interval(double dis_cm, int dis_cm_otherside) {
  if (dis_cm < dis_cm_otherside) {
    if (dis_cm < alert_distance / 5) {  //0~20cm
      analogWrite(vibratePin, vibratePower);
    } else if (dis_cm < alert_distance / 5 * 2) {  //20~40cm
      analogWrite(vibratePin, vibratePower / 5 * 4);
    } else if (dis_cm < alert_distance / 5 * 3) {  //40~60cm
      analogWrite(vibratePin, vibratePower / 5 * 3);
    } else if (dis_cm < alert_distance / 5 * 4) {  //60~80cm
      analogWrite(vibratePin, vibratePower / 5 * 2);
    } else if (dis_cm < alert_distance) {  //80~100cm
      analogWrite(vibratePin, vibratePower / 5);
    } else {
      analogWrite(vibratePin, 0);
    }
  }
}

void cdsNeo(int i) {
  int val = analogRead(cds);
  if (val > 950) {
    for (int j = 0; j < i; j++)
      neo.setPixelColor(j, bright, bright, bright);
    neo.show();
  } else {
    for (int j = 0; j < i; j++)
      neo.setPixelColor(j, 0, 0, 0);
    neo.show();
  }
}


double distance(int trig, int echo) {
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  double pulseTime = pulseIn(echo, HIGH);
  double distance_cm = pulseTime * 17.33 / 1000;
  if (distance_cm > 350) {
    return 350;
  } else if (distance_cm < 10) {
    return 10;
  }
  return distance_cm;
}


결과

OLED의 플리커링 현상으로 인해 사진 상으로 잘 담기지 않아 그림으로 대체합니다.


심박수 측정

심박 펄스 센서를 통해 심박수를 측정하여 OLED에 출력합니다.

아래 파형을 통해 심박을 함께 확인할 수 있습니다.

BPM에 따른 네오픽셀 점등

심박수에 따라 네오픽셀이 점등되어 게이지의 역할을 합니다.

심박 구간에 따라 각기 다른 색의 LED가 켜집니다.


추신

공집사의 아두이노 프로젝트 결과물은 판매되는 제품이 아니며, 프로젝트 수준에서 간단하게 진행되었습니다.

문의 및 의뢰는 크몽 공집사로 연락주시면 감사하겠습니다.