/*
Voltaat learn (http://learn.voltaat.com)
Link for full tutorial:
Tutorial: Building a device to read and graph heart rate using Arduino and MAX30102!
The purpose of this sketch is to build a device to read and chart the heart rate using
an Arduino board and a heart rate sensor to capture vital signs. We will use a screen
to display the results visually and also display the results through a graph on the computer.
Connections from the Arduino to the breadboard:
• Arduino GND pin → Breadboard ground line
• Arduino 5V pin → Breadboard 5V line
Connection from the LCD:
• VCC pin → breadboard 5v line
• GND pin→ breadboard GND line
• SDA pin→ Arduino analog pin A4
• SCL pin → Arduino analog pin A5
Connections from the Heartbeat Sensor:
• VCC pin → breadboard 5v line
• GND pin→ breadboard GND line
• SDA pin→ Arduino analog pin A4
• SCL pin → Arduino analog pin A5
Connections from the buzzer:
• The positive terminal of the speaker → Pin 2 on the Arduino board
• The negative terminal of the speaker → Negative terminals on the breadboard
*/
#include "MAX30105.h"
#include "heartRate.h"
#include "LiquidCrystal_I2C.h"
// Initialize MAX30105 pulse sensor
MAX30105 particleSensor;
// Initialize LCD display with I2C address 0x27, 16 columns, and 2 rows
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Define heart shape character for LCD
byte heartChar[8] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};
const byte RATE_SIZE = 7; // Number of readings to calculate the average BPM
byte rates[RATE_SIZE]; // Array to store heart rate values
byte rateSpot = 0; // Index for storing heart rate readings
long lastBeat = 0; // Timestamp of the last detected heartbeat
float beatsPerMinute; // Instant BPM value
int beatAvg; // Average BPM value
unsigned long previousMillis = 0;
const long interval = 1000; // LCD update interval (1 second)
int buzzer = 3; // Buzzer pin
void setup() {
Serial.begin(9600); // Initialize serial communication
pinMode(buzzer, OUTPUT); // Set buzzer pin as output
lcd.begin(16, 2); // Initialize LCD
lcd.backlight(); // Turn on LCD backlight
lcd.createChar(0, heartChar); // Register the custom heart character
lcd.print("Initializing...");
// Check if the MAX30105 sensor is detected
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
lcd.clear();
lcd.print("Sensor Error!");
while (1); // Halt execution if sensor is not found
}
particleSensor.setup(); // Configure the sensor
particleSensor.setPulseAmplitudeRed(0x0A); // Set LED pulse amplitude for red light
}
void loop() {
long irValue = particleSensor.getIR(); // Read IR sensor value
// Check if a heartbeat is detected
if (checkForBeat(irValue)) {
long delta = millis() - lastBeat; // Calculate time between beats
lastBeat = millis(); // Update last beat timestamp
beatsPerMinute = 60 / (delta / 1000.0); // Convert time difference to BPM
// Validate BPM range to filter out noise
if (beatsPerMinute > 20 && beatsPerMinute < 255) {
rates[rateSpot++] = (byte)beatsPerMinute; // Store BPM in the array
rateSpot %= RATE_SIZE; // Loop back index when it reaches max size
// Calculate the average BPM
beatAvg = 0;
for (byte x = 0; x < RATE_SIZE; x++) beatAvg += rates[x];
beatAvg /= RATE_SIZE;
}
}
// Update the LCD every second
if (millis() - previousMillis >= interval) {
previousMillis = millis();
lcd.clear();
// Display BPM on the first row
lcd.setCursor(0, 0);
lcd.print("BPM: ");
lcd.print(beatAvg);
Serial.println(beatAvg); // Print BPM to serial monitor
// Show heart symbol if a recent beat is detected
if (millis() - lastBeat < 1000) {
lcd.setCursor(13,0);
lcd.write(0); // Display heart symbol
}
// Display BPM status on the second row
lcd.setCursor(1,1);
if (beatAvg < 60) {
lcd.print("LOW BPM");
}
else if (beatAvg > 100){
lcd.print("High BPM");
digitalWrite(buzzer, HIGH); // Activate buzzer for high BPM
}
else {
lcd.print("Normal BPM");
digitalWrite(buzzer, LOW); // Turn off buzzer
}
// Show heart symbol again if a recent beat is detected
if (millis() - lastBeat < 1000) {
lcd.setCursor(13,0);
lcd.write(0); // Display heart symbol
}
// If IR value is too low, prompt user to place a finger
if (irValue < 50000) {
lcd.clear();
lcd.print("Place finger?");
}
}
}