Hi all,
I bought 2 of these heart pulse sensors (https://www.sparkfun.com/products/11574). How can I modify the sketch below to include a second sensor? The sketch below connects the sensor to pin A0 and then triggers a solenoid on pin 11 every time it detects a heart beat. I want a second sensor to connect to pin A1 to trigger a different solenoid on pin 5.
I am a very novice programmer, so I tried doubling all the variables and slightly changing their names, but I get confused when it comes to how the heart beat is calculated, especially because the sketch is multiple files. Someone suggested I create a class/library, but I don’t understand that, again also because of how the heartbeat signal is calculated with multiple files in one sketch.
Here is the code. ( Put both these codes in one folder.)
/*
>> Pulse Sensor Amped <<
This code is for Pulse Sensor Amped by Joel Murphy and Yury Gitman
www.pulsesensor.com
>>> Pulse Sensor purple wire goes to Analog Pin 0 <<<
Pulse Sensor sample aquisition and processing happens in the background via Timer 1 interrupt. 1mS sample rate.
PWM on pins 9 and 10 will not work when using this code!
The following variables are automatically updated:
Pulse : boolean that is true when a heartbeat is sensed then false in time with pin13 LED going out.
Signal : int that holds the analog signal data straight from the sensor. updated every 1mS.
HRV : int that holds the time between the last two beats. 1mS resolution.
BPM : int that holds the heart rate value. derived every pulse from averaging previous 10 HRV values.
QS : boolean that is made true whenever Pulse is found and BPM is updated. User must reset.
This code is designed with output serial data to Processing sketch "PulseSensorAmped_Processing-xx"
The Processing sketch is a simple data visualizer.
All the work to find the heartbeat and determine the heartrate happens in the code below.
Pin 13 LED will blink with heartbeat.
It will also fade an LED on pin 11 with every beat. Put an LED and series resistor from pin 11 to GND
See the README for more information and known issues.
Code Version 0.1 by Joel Murphy & Yury Gitman Summer 2012
*/
// VARIABLES
int pulsePin = 0; // pulse sensor purple wire connected to analog pin 0
int fadeRate = 0; // used to fade LED on PWM pin 11
// these are volatile because they are used during the interrupt!
volatile int BPM; // used to hold the pulse rate
volatile int Signal; // holds the incoming raw data
volatile int HRV; // holds the time between beats
volatile boolean Pulse = false; // true when pulse wave is high, false when it's low
volatile boolean QS = false; // becomes true when pulse rate is determined. every 20 pulses
void setup(){
pinMode(13,OUTPUT); // pin 13 will blink to your heartbeat!
pinMode(11,OUTPUT); // pin 11 will fade to your heartbeat!
Serial.begin(115200); // we agree to talk fast!
interruptSetup(); // sets up to read Pulse Sensor signal every 1mS
// UN-COMMENT THE NEXT LINE IF YOU ARE POWERING THE PulseSensor AT LOW VOLTAGE,
// AND APPLY THAT VOLTAGE TO THE A-REF PIN
//analogReference(EXTERNAL);
}
void loop(){
sendDataToProcessing('S', Signal); // send Processing the raw Pulse Sensor data
if (QS == true){ // Quantified Self flag is true when arduino finds a heartbeat
fadeRate = 255; // Set 'fadeRate' Variable to 255 to fade LED with pulse
sendDataToProcessing('B',BPM); // send the time between beats with a 'B' prefix
sendDataToProcessing('Q',HRV); // send heart rate with a 'Q' prefix
QS = false; // reset the Quantified Self flag for next time
}
ledFadeToBeat();
delay(20); // take a break
}
void ledFadeToBeat(){
fadeRate -= 15; // set LED fade value
fadeRate = constrain(fadeRate,0,255); // keep LED fade value from going into negative numbers!
analogWrite(11,fadeRate*1.2); // TRIGGERS SOLENOID
}
void sendDataToProcessing(char symbol, int data ){
Serial.print(symbol); // symbol prefix tells Processing what type of data is coming
Serial.println(data); // the data to send
}
Interrupt part:
volatile int rate[10]; // used to get running average of HRV values
volatile unsigned long lastBeatTime = 0; // used to find the time between beats
volatile int sampleCounter; // used to determine pulse timing
volatile int runningTotal; // used to keep track of pulses
volatile boolean firstBeat = true; // used to seed rate array so we startup with reasonable BPM
volatile boolean secondBeat = true; // used to seed rate array so we startup with reasonable BPM
void interruptSetup(){
// Initializes Timer1 to throw an interrupt every 1mS.
TCCR1A = 0x00; // DISABLE OUTPUTS AND PWM ON DIGITAL PINS 9 & 10
TCCR1B = 0x11; // GO INTO 'PHASE AND FREQUENCY CORRECT' MODE, NO PRESCALER
TCCR1C = 0x00; // DON'T FORCE COMPARE
TIMSK1 = 0x01; // ENABLE OVERFLOW INTERRUPT (TOIE1)
ICR1 = 8000; // TRIGGER TIMER INTERRUPT EVERY 1mS
sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED
}
// THIS IS THE TIMER 1 INTERRUPT SERVICE ROUTINE.
ISR(TIMER1_OVF_vect){ // triggered every time Timer 1 overflows
// Timer 1 makes sure that we take a reading every milisecond
Signal = analogRead(pulsePin); // read the Pulse Sensor
sampleCounter++; // keep track of the time with this variable (ISR triggered every 1mS
// NOW IT'S TIME TO LOOK FOR THE HEART BEAT
int H = sampleCounter-lastBeatTime; // monitor the time since the last beat to avoid noise
if ( (Signal > 520) && (Pulse == false) && (H > 500) ){
// signal surges up in value every time there is a pulse
Pulse = true; // set the Pulse flag when we think there is a pulse
digitalWrite(13,HIGH); // turn on pin 13 LED
HRV = sampleCounter - lastBeatTime; // measure time between beats in mS
lastBeatTime = sampleCounter; // keep track of time for next pulse
if(firstBeat){ // if it's the first time we found a beat
firstBeat = false; // clear firstBeat flag
return; // HRV value is unreliable so discard it
}
if(secondBeat){ // if this is the second beat
secondBeat = false; // clear secondBeat flag
for(int i=0; i<=9; i++){ // seed the running total to get a realisitic BPM at startup
rate[i] = HRV;
}
}
// keep a running total of the last 10 HRV values
for(int i=0; i<=8; i++){
rate[i] = rate[i+1]; // shift data in the rate array and drop the oldest HRV value
}
rate[9] = HRV; // add the latest HRV to the rate array
runningTotal = 0; // clear the runningTotal variable
for(int i=0; i<=9; i++){
runningTotal += rate[i]; // add up the last 10 HRV values
}
runningTotal /= 10; // average the last 10 HRV values
BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM!
QS = true; // set Quantified Self flag when beat is found and BPM gets updated.
// QS FLAG IS NOT CLEARED INSIDE THIS ISR
}
if (Signal < 500 && Pulse == true){ // when the values are going down, it's the time between beats
digitalWrite(13,LOW); // turn off pin 13 LED
Pulse = false; // reset the Pulse flag so we can do it again!
}
}// end isr