Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: main.cpp
- Revision:
- 2:515e6791dfe2
- Parent:
- 0:a78b08608d76
- Child:
- 3:89dc4a1464e3
--- a/main.cpp Sat Jan 11 12:52:56 2014 +0000 +++ b/main.cpp Fri Jan 24 11:16:30 2020 +0000 @@ -1,102 +1,138 @@ #include "mbed.h" +#include "USBSerial.h" +#include "Adafruit_SSD1306.h" +#include <string> +#include <sstream> +#include <map> -/* ->> Pulse Sensor Amped 1.1 << -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 2 interrupt. 2mS sample rate. -PWM on pins 3 and 11 will not work when using this code, because we are using Timer 2! -The following variables are automatically updated: -Signal : int that holds the analog signal data straight from the sensor. updated every 2mS. -IBI : int that holds the time interval between beats. 2mS resolution. -BPM : int that holds the heart rate value, derived every beat, from averaging previous 10 IBI values. -QS : boolean that is made true whenever Pulse is found and BPM is updated. User must reset. -Pulse : boolean that is true when a heartbeat is sensed then false in time with pin13 LED going out. +AnalogIn pulseIn(A0); +using namespace std; +USBSerial pc; +I2C i2c(PB_9, PB_8); +Adafruit_SSD1306_I2c oled(i2c,PC_13); + + +AnalogIn pulsePin(A0); //This is signal input -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. -If you want to use pin 13 for something else, adjust the interrupt handler -It will also fade an LED on pin fadePin with every beat. Put an LED and series resistor from fadePin to GND. -Check here for detailed code walkthrough: -http://pulsesensor.myshopify.com/pages/pulse-sensor-amped-arduino-v1dot1 +// these variables are because they are used during the interrupt service routine! +int BPM; // used to hold the pulse rate +int Signal; // holds the incoming raw data +int IBI = 600; // holds the time between beats, the Inter-Beat Interval +bool Pulse = false; // true when pulse wave is high, false when it's low +bool QS = false; // becomes true when Arduoino finds a beat. -Code Version 02 by Joel Murphy & Yury Gitman Fall 2012 -This update changes the HRV variable name to IBI, which stands for Inter-Beat Interval, for clarity. -Switched the interrupt to Timer2. 500Hz sample rate, 2mS resolution IBI value. -Fade LED pin moved to pin 5 (use of Timer2 disables PWM on pins 3 & 11). -Tidied up inefficiencies since the last version. -*/ +void heart_rate_test(void); +int rate[10]; // used to hold last ten IBI values +unsigned long sampleCounter = 0; // used to determine pulse timing +unsigned long lastBeatTime = 0; // used to find the inter beat interval +int P =512; // used to find peak in pulse wave +int T = 512; // used to find trough in pulse wave +int thresh = 512; // used to find instant moment of heart beat +int amp = 100; // used to hold amplitude of pulse waveform +bool firstBeat = true; // used to seed rate array so we startup with reasonable BPM +bool secondBeat = true; // used to seed rate array so we startup with reasonable BPM -/* -// VARIABLES -int pulsePin = 0; // Pulse Sensor purple wire connected to analog pin 0 -int blinkPin = 13; // pin to blink led at each beat -int fadePin = 5; // pin to do fancy classy fading blink at each beat -int fadeRate = 0; // used to fade LED on with PWM on fadePin -*/ +Ticker time_up; +// Escreve o texto passado como parâmetro no display +void OLED_writeString(string str, int x, int y) { +oled.clearDisplay(); +oled.setTextCursor(x, y); +oled.fillRect(x, y, 128, 8, 0); + } + -AnalogIn pulsePin(p15); //This is signal input -SPI blinkPin(p11,p12,p13); -PwmOut fadePin(p26); -int fadeRate = 0; +void heart_rate_test() +{ + Signal = pulsePin.read()*1024; // read the Pulse Sensor + sampleCounter += 2; // keep track of the time in mS with this variable + int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid nois // find the peak and trough of the pulse wave + if(Signal < thresh && N > (IBI/5)*3) { // avoid dichrotic noise by waiting 3/5 of last IBI + if (Signal < T) { // T is the trough + T = Signal; // keep track of lowest point in pulse wave + } + } + + if(Signal > thresh && Signal > P) { // thresh condition helps avoid noise + P = Signal; // P is the peak + } // keep track of highest point in pulse wave + + // NOW IT'S TIME TO LOOK FOR THE HEART BEAT + // signal surges up in value every time there is a pulse + if (N > 250) { // avoid high frequency noise + if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ) { + Pulse = true; // set the Pulse flag when we think there is a pulse + //digitalWrite(blinkPin,HIGH); // turn on pin 13 LED + IBI = 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, if firstBeat == TRUE + firstBeat = false; // clear firstBeat flag + return; // IBI value is unreliable so discard it + } + if(secondBeat) { // if this is the second beat, if secondBeat == TRUE + 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] = IBI; + } + } + + // keep a running total of the last 10 IBI values + long runningTotal = 0; // clear the runningTotal variable + + for(int i=0; i<=8; i++) { // shift data in the rate array + rate[i] = rate[i+1]; // and drop the oldest IBI value + runningTotal += rate[i]; // add up the 9 oldest IBI values + } + + rate[9] = IBI; // add the latest IBI to the rate array + runningTotal += rate[9]; // add the latest IBI to runningTotal + runningTotal /= 10; // average the last 10 IBI values + BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM! + QS = true; + string BPM_s= static_cast<ostringstream*>( &(ostringstream() << BPM) )->str(); + OLED_writeString(BPM_s, 1, 1); + // QS FLAG IS NOT CLEARED INSIDE THIS ISR + } + } + + if (Signal < thresh && Pulse == true) { // when the values are going down, the beat is over + Pulse = false; // reset the Pulse flag so we can do it again + amp = P - T; // get amplitude of the pulse wave + thresh = amp/2 + T; // set thresh at 50% of the amplitude + P = thresh; // reset these for next time + T = thresh; + } + + if (N > 2500) { // if 2.5 seconds go by without a beat + thresh = 512; // set thresh default + P = 512; // set P default + T = 512; // set T default + lastBeatTime = sampleCounter; // bring the lastBeatTime up to date + firstBeat = true; // set these to avoid noise + secondBeat = true; // when we get the heartbeat back + } -// these variables are volatile because they are used during the interrupt service routine! -volatile int BPM; // used to hold the pulse rate -volatile int Signal; // holds the incoming raw data -volatile int IBI = 600; // holds the time between beats, the Inter-Beat Interval -//volatile boolean Pulse = false; // true when pulse wave is high, false when it's low -//volatile boolean QS = false; // becomes true when Arduoino finds a beat. -volatile bool Pulse = false; // true when pulse wave is high, false when it's low -volatile bool QS = false; // becomes true when Arduoino finds a beat. -/* -void setup(){ - pinMode(blinkPin,OUTPUT); // pin that will blink to your heartbeat! - pinMode(fadePin,OUTPUT); // pin that will fade to your heartbeat! - Serial.begin(115200); // we agree to talk fast! - interruptSetup(); // sets up to read Pulse Sensor signal every 2mS - // UN-COMMENT THE NEXT LINE IF YOU ARE POWERING The Pulse Sensor AT LOW VOLTAGE, - // AND APPLY THAT VOLTAGE TO THE A-REF PIN - //analogReference(EXTERNAL); -} -*/ - -void setup(){ - // Serial.begin (115200); // we agree to talk fast! - // interruptSetup(); // sets up to read Pulse Sensor signal every 2mS - Serial deta(p9,p10); // we agree to talk fast! - interruptSetup(); // sets up to read Pulse Sensor signal every 2mS - - // UN-COMMENT THE NEXT LINE IF YOU ARE POWERING The Pulse Sensor 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 heart rate with a 'B' prefix - sendDataToProcessing('Q',IBI); // send time between beats 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(fadePin,fadeRate); // fade LED - } +int main() +{ + time_up.attach(&heart_rate_test, 0.002); + oled.clearDisplay(); + OLED_writeString("hello world", 1, 1); + while(true) + { + if (QS == true) + { + + QS = false; + //pc.printf("%d \n ",BPM); // reset the Quantified Self flag for next time + } + wait_ms(20); + } +} -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 culminating in a carriage return - } \ No newline at end of file + +