項目采用MAX30102血氧及心率監視模塊、Arduino UNO板、OLED顯示器和蜂鳴器,搭建了一個簡單的心率(BPM)測量儀。
?
這里,BPM為每分鐘的心跳數,正常人的數字為65-75之間,體育運動員的數字要低些;血氧飽和度(SaO2)對于正常然來說大概為95%。
項目物料
本項目所需材料包括:
Max30102(×1):這是項目的功能器件,是一款用于可穿戴設備的高靈敏脈沖式血樣及心率傳感器,具有不同版本,但是只要型號正確即可。?
Arduino UNO(×1)
OLED 128x32(×1):低功耗顯示器。?
Buzzer (×1):蜂鳴器
面包板(×1):方便組件安裝和連接的線路板。
連接線
?
本項目所用代碼來自Sparkfun_MAX3010x示例庫,OLED和Buzzer代碼根據 "HeartRate" 示例改進而來,這需要用戶將手指放在傳感器上。
注意,如果將手指放在傳感器上,就要保持安靜,直到蜂鳴器的“嗶嗶”聲與你的心率節拍同步,或者與OLED動畫同步,這時可讀出正確的BPM心率讀數。
?
本項目采用4次BPM讀數的平均值,因此比較準確。
讓OLED顯示bmp圖像
OLED顯示的是小的“心形”柵格圖(bmp),一旦傳感器檢測到一次心跳,就立即切換為大點的“心形”柵格圖并保持一會兒,這樣屏幕就像心跳一樣,一閃一閃的,并伴有蜂鳴器的“嗶嗶”聲。
?
選擇希望看到的圖走向的格式,如 .png\ .bmp\ .dib等。切記,本項目屏幕尺寸為128x32px,圖像尺寸要小一些,為32x32px和24x21px。
?
下載LCD助手并打開。
?
可看到如下"數字"
?
這就是所謂的代碼:
display.drawBitmap(5, 5, logo2_bmp, 24, 21, WHITE);
其含義為:
display.drawBitmap(Starting x pos, Starting y pos, Bitmap name, Width, Height, Color);
這段代碼描述了兩件事——“當檢測到手指時做什么”,以及“撿到心跳時做什么”。
以下是更新后的代碼:
MAX_BPM_OLED_Buzzer.inoArduino
Modified from the SparkFun MAX3010x library
/* This code works with MAX30102 + 128x32 OLED i2c + Buzzer and Arduino UNO
* It's displays the Average BPM on the screen, with an animation and a buzzer sound
* everytime a heart pulse is detected
* It's a modified version of the HeartRate library example
* Refer to www.surtrtech.com for more details or SurtrTech YouTube channel
*/
#include ? ? ? ?//OLED libraries
#include
#include
#include "MAX30105.h" ? ? ? ? ? //MAX3010x library
#include "heartRate.h" ? ? ? ? ?//Heart rate calculating algorithm
MAX30105 particleSensor;
const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred
float beatsPerMinute;
int beatAvg;
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET ? ?-1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //Declaring the display name (display)
static const unsigned char PROGMEM logo2_bmp[] =
{ 0x03, 0xC0, 0xF0, 0x06, 0x71, 0x8C, 0x0C, 0x1B, 0x06, 0x18, 0x0E, 0x02, 0x10, 0x0C, 0x03, 0x10, ? ? ? ? ? ? ?//Logo2 and Logo3 are two bmp pictures that display on the OLED if called
0x04, 0x01, 0x10, 0x04, 0x01, 0x10, 0x40, 0x01, 0x10, 0x40, 0x01, 0x10, 0xC0, 0x03, 0x08, 0x88,
0x02, 0x08, 0xB8, 0x04, 0xFF, 0x37, 0x08, 0x01, 0x30, 0x18, 0x01, 0x90, 0x30, 0x00, 0xC0, 0x60,
0x00, 0x60, 0xC0, 0x00, 0x31, 0x80, 0x00, 0x1B, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x04, 0x00, ?};
static const unsigned char PROGMEM logo3_bmp[] =
{ 0x01, 0xF0, 0x0F, 0x80, 0x06, 0x1C, 0x38, 0x60, 0x18, 0x06, 0x60, 0x18, 0x10, 0x01, 0x80, 0x08,
0x20, 0x01, 0x80, 0x04, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0xC0, 0x00, 0x08, 0x03,
0x80, 0x00, 0x08, 0x01, 0x80, 0x00, 0x18, 0x01, 0x80, 0x00, 0x1C, 0x01, 0x80, 0x00, 0x14, 0x00,
0x80, 0x00, 0x14, 0x00, 0x80, 0x00, 0x14, 0x00, 0x40, 0x10, 0x12, 0x00, 0x40, 0x10, 0x12, 0x00,
0x7E, 0x1F, 0x23, 0xFE, 0x03, 0x31, 0xA0, 0x04, 0x01, 0xA0, 0xA0, 0x0C, 0x00, 0xA0, 0xA0, 0x08,
0x00, 0x60, 0xE0, 0x10, 0x00, 0x20, 0x60, 0x20, 0x06, 0x00, 0x40, 0x60, 0x03, 0x00, 0x40, 0xC0,
0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x30, 0x0C, 0x00,
0x00, 0x08, 0x10, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00 ?};
void setup() { ?
?display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Start the OLED display
?display.display();
?delay(3000);
?// Initialize sensor
?particleSensor.begin(Wire, I2C_SPEED_FAST); //Use default I2C port, 400kHz speed
?particleSensor.setup(); //Configure sensor with default settings
?particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
}
void loop() {
long irValue = particleSensor.getIR(); ? ?//Reading the IR value it will permit us to know if there's a finger on the sensor or not
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //Also detecting a heartbeat
if(irValue > 7000){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //If a finger is detected
? ?display.clearDisplay(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //Clear the display
? ?display.drawBitmap(5, 5, logo2_bmp, 24, 21, WHITE); ? ? ? //Draw the first bmp picture (little heart)
? ?display.setTextSize(2); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //Near it display the average BPM you can display the BPM if you want
? ?display.setTextColor(WHITE);?
? ?display.setCursor(50,0); ? ? ? ? ? ? ? ?
? ?display.println("BPM"); ? ? ? ? ? ??
? ?display.setCursor(50,18); ? ? ? ? ? ? ? ?
? ?display.println(beatAvg);?
? ?display.display();
? ?
?if (checkForBeat(irValue) == true) ? ? ? ? ? ? ? ? ? ? ? ?//If a heart beat is detected
?{
? ?display.clearDisplay(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//Clear the display
? ?display.drawBitmap(0, 0, logo3_bmp, 32, 32, WHITE); ? ?//Draw the second picture (bigger heart)
? ?display.setTextSize(2); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//And still displays the average BPM
? ?display.setTextColor(WHITE); ? ? ? ? ? ??
? ?display.setCursor(50,0); ? ? ? ? ? ? ? ?
? ?display.println("BPM"); ? ? ? ? ? ??
? ?display.setCursor(50,18); ? ? ? ? ? ? ? ?
? ?display.println(beatAvg);?
? ?display.display();
? ?tone(3,1000); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//And tone the buzzer for a 100ms you can reduce it it will be better
? ?delay(100);
? ?noTone(3); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//Deactivate the buzzer to have the effect of a "bip"
? ?//We sensed a beat!
? ?long delta = millis() - lastBeat; ? ? ? ? ? ? ? ? ? //Measure duration between two beats
? ?lastBeat = millis();
? ?beatsPerMinute = 60 / (delta / 1000.0); ? ? ? ? ? //Calculating the BPM
? ?if (beatsPerMinute < 255 && beatsPerMinute > 20) ? ? ? ? ? ? ? //To calculate the average we strore some values (4) then do some math to calculate the average
? ?{
? ? ?rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
? ? ?rateSpot %= RATE_SIZE; //Wrap variable
? ? ?//Take average of readings
? ? ?beatAvg = 0;
? ? ?for (byte x = 0 ; x < RATE_SIZE ; x++)
? ? ? ?beatAvg += rates[x];
? ? ?beatAvg /= RATE_SIZE;
? ?}
?}
}
?if (irValue < 7000){ ? ? ? //If no finger is detected it inform the user and put the average BPM to 0 or it will be stored for the next measure
? ? beatAvg=0;
? ? display.clearDisplay();
? ? display.setTextSize(1); ? ? ? ? ? ? ? ? ? ?
? ? display.setTextColor(WHITE); ? ? ? ? ? ??
? ? display.setCursor(30,5); ? ? ? ? ? ? ? ?
? ? display.println("Please Place ");?
? ? display.setCursor(30,15);
? ? display.println("your finger "); ?
? ? display.display();
? ? noTone(3);
? ? }
}
審核編輯:湯梓紅
評論
查看更多