Hello everyone, I am working on a school project which uses Arduino UNO and pulse sensor SEN-11574 from pulsesensor.com to measure the heart rate. I want to ask if anyone knows how to increase the measurement speed of the pulse sensor. Now it will take about 10 seconds to measure the heart rate. I think it is too slow. I want to reduce it to less than 5 seconds. Does anybody have any pieces of advice? Should I modify the code or hardware? Thank you very much in advance. Following is the code that I am using right now.
#define USE_ARDUINO_INTERRUPTS true // Set-up low-level interrupts for most acurate BPM math.
#include <PulseSensorPlayground.h> // Includes the PulseSensorPlayground Library.
// Variables
const int PulseWire = 0; // PulseSensor PURPLE WIRE connected to ANALOG PIN 0
int Threshold = 550; // Determine which Signal to "count as a beat" and which to ignore.
// Use the "Gettting Started Project" to fine-tune Threshold Value beyond default setting.
// Otherwise leave the default "550" value.
PulseSensorPlayground pulseSensor; // Creates an instance of the PulseSensorPlayground object called "pulseSensor"
void setup() {
Serial.begin(9600); // For Serial Monitor
// initialize digital pin2 as an output.
pinMode(2, OUTPUT);
// Configure the PulseSensor object, by assigning our variables to it.
pulseSensor.analogInput(PulseWire);
pulseSensor.setThreshold(Threshold);
// Double-check the "pulseSensor" object was created and "began" seeing a signal.
if (pulseSensor.begin()) {
Serial.println("We created a pulseSensor Object !"); //This prints one time at Arduino power-up, or on Arduino reset.
}
}
void loop() {
int myBPM = pulseSensor.getBeatsPerMinute(); // Calls function on our pulseSensor object that returns BPM as an "int".
// "myBPM" hold this BPM value now.
if (pulseSensor.sawStartOfBeat()) { // Constantly test to see if "a beat happened".
Serial.println("♥ A HeartBeat Happened ! "); // If test is "true", print a message "a heartbeat happened".
Serial.print("BPM: "); // Print phrase "BPM: "
Serial.println(myBPM); // Print the value inside of myBPM.
if(myBPM >= 80){ // If the signal is above "550", then "turn-on" Arduino's on-Board LED.
digitalWrite(2, LOW);
delay(50);
digitalWrite(2, HIGH);
delay(50);
} else if (myBPM >= 70 && myBPM < 80){
digitalWrite(2, LOW);
delay(100);
digitalWrite(2, HIGH);
delay(100);
}
else if (myBPM >= 60 && myBPM < 70){
digitalWrite(2, LOW);
delay(500);
digitalWrite(2, HIGH);
delay(500);
}
else {
digitalWrite(2, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(2, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
}
else {
digitalWrite(2,LOW); // Else, the sigal must be below "550", so "turn-off" this LED.
}
delay(20); // considered best practice in a simple sketch.
}
@DragonPig, do not cross-post. Other thread removed.
so sorry about that! I didn't know
To make it give a number faster (but less accurate as you had less beats) you will have to make changes to the PulseSensorPlayground library.
Wow! Thank you so much!! But can I modify the PulseSensorPlayground library?
Thank you, I had taken a look at the code but I am not sure which line of code should I modify and I couldn't find any guide online. Should modify this line? THANK YOU VERY MUCH if you can help me!
static const unsigned long MICROS_PER_READ = (2 * 1000L); // usecs per sample
This is the code for pulsesensorplayground library
#ifndef PULSE_SENSOR_PLAYGROUND_H
#define PULSE_SENSOR_PLAYGROUND_H
#define PULSE_SENSOR_TIMING_ANALYSIS false
#define PULSE_SENSOR_MEMORY_USAGE false
//#define PULSE_SENSOR_MEMORY_USAGE true
#include <Arduino.h>
#include "utility/PulseSensor.h"
#include "utility/PulseSensorSerialOutput.h"
#include "utility/PulseSensorTimingStatistics.h"
class PulseSensorPlayground {
public:
/*
The number of microseconds per sample of data from the PulseSensor.
1 millisecond is 1,000 microseconds.
Refer to this value as PulseSensorPlayground::MICROS_PER_READ
*/
static const unsigned long MICROS_PER_READ = (2 * 1000L); // usecs per sample.
//---------- PulseSensor Manager functions
PulseSensorPlayground(int numberOfSensors = 1);
/*
Start reading and processing data from the PulseSensors.
Your Sketch should make all necessary PulseSensor configuration calls
before calling begin().
If the Sketch defined USE_ARDUINO_INTERRUPTS as true, this function
sets up and turns on interrupts for the PulseSensor.
If instead the Sketch defined USE_ARDUINO_INTERRUPTS as false,
it initializes what's necessary for the Sketch to process
PulsSensor signals. See sawNewSample(), below.
Returns true if successful, false if unsuccessful.
Returns false if PulseSensorPlayground doesn't yet support
interrupts on this Arduino platform and the user's Sketch
did a #define USE_ARDUINO_INTERRUPTS true.
If begin() returns false, you can either use a different
type of Arduino platform, or you can change your Sketch's
definition of USE_ARDUINO_INTERRUPTS to false:
#define USE_ARDUINO_INTERRUPTS false
*/
boolean begin();
/*
Returns true if a new sample has been read from each PulseSensor.
You'll likely want to add this call to your Sketch's loop()
only if you either 1) want to do something with each sample of the
PulseSensor signals, or 2) your Sketch doesn't use interrupts
to read from the PulseSensors.
NOTE: If your Sketch defined USE_ARDUINO_INTERRUPTS as false,
you must call pulse.sawNewSample() frequently (at least
once every 2 milliseconds) to assure that PulseSensor signals
are read accurately.
A typical loop() that doesn't use interrupts will contain:
if (pulse.sawNewSample()) {
int latest = pulse.getLatestSample();
...do whatever you want with the sample read from the PulseSensor.
}
*/
boolean sawNewSample();
//---------- Per-PulseSensor functions
void analogInput(int inputPin, int sensorIndex = 0);
void blinkOnPulse(int blinkPin, int sensorIndex = 0);
void fadeOnPulse(int fadePin, int sensorIndex = 0);
void onSampleTime();
/*
Returns the most recently read analog value from the given PulseSensor
(range: 0..1023).
sensorIndex = optional, index (0..numberOfSensors - 1)
of the PulseSensor of interest.
*/
int getLatestSample(int sensorIndex = 0);
/*
Returns the latest beats-per-minute measure for the given PulseSensor.
The internal beats-per-minute measure is updated per-PulseSensor,
when a beat is detected from that PulseSensor.
sensorIndex = optional, index (0..numberOfSensors - 1)
of the PulseSensor of interest.
*/
int getBeatsPerMinute(int sensorIndex = 0);
/*
Returns the latest IBI (inter-beat interval, in milliseconds) measure
for the given PulseSensor.
The internal IBI measure is updated per-PulseSensor,
when a beat is detected from that PulseSensor.
sensorIndex = optional, index (0..numberOfSensors - 1)
of the PulseSensor of interest.
*/
int getInterBeatIntervalMs(int sensorIndex = 0);
/*
Returns true if a new heartbeat (pulse) has been detected
from the given PulseSensor since the last call to sawStartOfBeat()
on this PulseSensor.
Typical use in loop():
if (pulse.sawStartOfBeat()) {
...do what you want to do per-heartbeat.
}
sensorIndex = optional, index (0..numberOfSensors - 1)
of the PulseSensor of interest.
*/
boolean sawStartOfBeat(int sensorIndex = 0);
/*
Returns true if the given PulseSensor signal is currently
inside a heartbeat. That is, returns true if the signal is above
the automatically-set threshold of a beat, false otherwise.
Typical use in loop():
if (pulse.isInsideBeat()) {
...do what you want while in the beat.
} else {
...do what you want while between beats.
}
sensorIndex = optional, index (0..numberOfSensors - 1)
of the PulseSensor of interest.
*/
boolean isInsideBeat(int sensorIndex = 0);
//---------- Serial Output functions
void setSerial(Stream &output);
void setOutputType(byte outputType);
void setThreshold(int threshold, int sensorIndex = 0);
void outputSample();
void outputToSerial(char symbol, int data);
int getPulseAmplitude(int sensorIndex = 0);
/*
Returns the sample number when the last beat was found. 2mS resolution.
*/
unsigned long getLastBeatTime(int sensorIndex = 0);
/*
Output the current per-beat information for each PulseSensor,
in the previously-set outputType.
If your Sketch wants to plot beat information, it should call this
function every time a beat is detected.
Typical use:
if (pulse.sawStartOfBeat()) {
pulse.outputBeat();
}
*/
void outputBeat(int sensorIndex = 0);
// (internal to the library) "this" pointer for the ISR.
static PulseSensorPlayground *OurThis;
private:
void setupInterrupt();
#if PULSE_SENSOR_MEMORY_USAGE
void printMemoryUsage();
#endif // PULSE_SENSOR_MEMORY_USAGE
static boolean UsingInterrupts;
byte SensorCount; // number of PulseSensors in Sensors[].
PulseSensor *Sensors; // use Sensors[idx] to access a sensor.
volatile unsigned long NextSampleMicros; // Desired time to sample next.
volatile boolean SawNewSample; // "A sample has arrived from the ISR"
PulseSensorSerialOutput SerialOutput; // Serial Output manager.
#if PULSE_SENSOR_TIMING_ANALYSIS // Don't use ram and flash we don't need.
PulseSensorTimingStatistics *pTiming;
#endif // PULSE_SENSOR_TIMING_ANALYSIS
};
#include "utility/Interrupts.h"
#endif // PULSE_SENSOR_PLAYGROUND_H
You'll just have to analyse the code and find out how it works, and how it sets the sample rate. A line that mentions a timing of 2000 us doesn't sound like the part where it takes 10 seconds between readings.