techrmc’s blog

ICT大好きな中小企業診断士のブログです

Arduinoを用いた心拍計

Arduino UNO R4 Minimaをベースとした心拍計を作成してみました。写真は心拍センサを指に取り付けた場合の様子です。センサを指に取り付けた直後や、指を動かしたりすると、波形が乱れますが、安定状態になるとそれっぽく波形が表示できています。

作成した心拍計

全体構成

心拍センサで心拍を計測し、Arduinoで波形に変換するとともに、心拍数を算出します。計測結果は、波形や心拍数として有機ELディスプレイに表示します。心拍センサや有機ELディスプレイは、Arduino用のシールドとしてユニバーサル基板に実装しました。

心拍センサ

World Famous Electronicsのセンサをスイッチサイエンスから購入しました。センサを指に固定するためのマジックテープや耳に固定するためのクリップも同梱されていて便利です。このセンサは販売元のホームページGitHubに豊富な情報やサンプルコードが掲載されています。
心拍センサの信号線は、Arduinoのアナログ入力ポートであるA0ポートに接続します。

有機ELディスプレイ

有機ELディスプレイは、秋月電子通商で購入しました。この有機ELディスプレイは画素数が128x64であり、I2Cで制御します。画素数が少ないので波形の細部を描くことはできませんが、波形の概観を見るには十分でしょう。制御チップのSSD1306は広く使われているICのため、ネット上にはライブラリなどの情報も豊富です。ここではAdafruitのSSD1306ライブラリを使わせて頂きました。

プログラム

心拍センサのサンプルコードや、有機ELライブラリのサンプルコードを参考にして書いたプログラムです。BPM_INT画面分の波形を表示したのち、心拍数BPMを2秒間表示し、再び波形表示に戻ります。

/**************************************************************************
 PulseMonitor - Monitoring Heartbeat Pulse 
 -Live visualization on SSD1306 based I2C OLED display.
 -Blink an LED on each Heartbeat.
 -Show BPM on OLED.
 **************************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include <PulseSensorPlayground.h>

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels
#define OLED_RESET -1     // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // I2C address
#define BPM_INT 4         // Screen interval showing BPM
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
PulseSensorPlayground pulseSensor;  // Creates an instance of the PulseSensorPlayground object called "pulseSensor"

int PulseSensorPurplePin = 0; // Pulse Sensor PURPLE WIRE connected to ANALOG PIN 0
int LED = LED_BUILTIN;        // The on-board Arduion LED
int Signal;                   // holds the incoming raw data. Signal value can range from 0-1024
int Mcount = 0;               // counts measurements
int Scount = 0;               // counts screen refreshes
int Threshold = 580;          // Determine which Signal to "count as a beat", and which to ingore.

void setup() {
  Serial.begin(115200);       // Set's up Serial Communication at certain speed.

  // Configure the PulseSensor object, by assigning our variables to it. 
  pulseSensor.analogInput(PulseSensorPurplePin);   
  pulseSensor.blinkOnPulse(LED);       //auto-matically blink Arduino's LED with heartbeat.
  pulseSensor.setThreshold(Threshold);   

  // Double-check the "pulseSensor" object was created and "began" seeing a signal. 
   if (!pulseSensor.begin()) {
    Serial.println(F("pulseSensor allocation failed")); 
    for(;;); // Don't proceed, loop forever
  }

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 sec
  display.clearDisplay();

}

void loop() {
  // Pulse Sensor
  Signal = analogRead(PulseSensorPurplePin);  // Read the PulseSensor's value.

  // draw a point on the OLED
  display.drawPixel(Mcount, (int)(SCREEN_HEIGHT-SCREEN_HEIGHT*Signal/1024), SSD1306_WHITE);
  display.display();

  // check whether reached to the screen edge 
  if (Mcount++ >= SCREEN_WIDTH) {
    display.clearDisplay();
    Mcount = 0;
    if (Scount++ >= BPM_INT) { // if the screen was refreshed BPM_INT times
      Scount = 0;
      int myBPM = pulseSensor.getBeatsPerMinute();  

      display.setTextSize(2);                 // draw 2X-scale text
      display.setTextColor(SSD1306_WHITE);  
      display.setCursor(0,SCREEN_HEIGHT/2);   // set cursor position
      display.print(F("BPM=")); 
      display.println(myBPM);
      display.display();
      delay(2000);
      display.clearDisplay();
    }
  }
}