Hey guys, i'm new to the forum and quite a begginer with Arduino. So i'm trying to do a project where you could send the GPS coordinate along side with the BPM through WIFI. I already made the wifi working together with the GPS but somehow i cannot make sense of putting the pulse sensor into the equation.
I tried to run the pulse sensor alone and it works just fine with the example code. The problem is when i try to match it all together. It just doesn't work. The xBee (wifi module) and even the GPS (adafruit) can't get signal. This is probably just a rookie mistake and i'm kind of guessing it has something to do with the fact that pulse sensor requests a reading every 2ms.
I'm asking for some guidance so i don't know if i should post the code because i think the problem is in the way that i'm doing things. If you need any code feel free to ask.
Thanks guys!
diogonunes92:
This -> PulseSensor
You paid too much. http://www.ebay.com/itm/Heart-Rate-Pulse-Sensor-Pulsesensor-Sensor-Module-For-Arduino-new-/281742083536?hash=item41992305d0:g:Q8cAAOSwLVZVmhx9
We have no idea how to solve your problem because we can't see it. Please post your code using code tags. The code tags make the code look
like this
when posting source code files. It makes it easier to read, and can be copied with a single mouse click. Also, if you don't do it, some of the character sequences in the code can be misinterpreted by the forum code as italics or funny emoticons.
Unless the sketch is too large, it's better if you post your code, rather than attach it. When it's attached, we have to download it, create a folder then open your code in our IDE. Or perhaps open it in WordPad, which isn't very good for looking at code. And afterwards, the folder remains unless we navigate to the "Temp" folder and manually remove it. It's much easier to just view the code in your post.
Many questions can be answered by reading the documentation which is provided with the IDE, available under the help tab, or online here.
There are many other things that programmers do to make their code understandable. Please do them, as a courtesy to the members who volunteer their time to help you here. One is to use a standard indentation to clearly show the code blocks. Never put more than one statement per line. Place any brackets by themselves on a separate line. Before posting the code, use Ctrl-T in the IDE to reformat the code in a standard format, which makes it easier for us to read. Another is to give things descriptive names. You can name numerical constants, pin numbers, variables and many other things in this way.
Interrupt Function:
volatile int rate[10]; // array to hold last ten IBI values
volatile unsigned long sampleCounter = 0; // used to determine pulse timing
volatile unsigned long lastBeatTime = 0; // used to find IBI
volatile int P =512; // used to find peak in pulse wave, seeded
volatile int T = 512; // used to find trough in pulse wave, seeded
volatile int thresh = 525; // used to find instant moment of heart beat, seeded
volatile int amp = 100; // used to hold amplitude of pulse waveform, seeded
volatile boolean firstBeat = true; // used to seed rate array so we startup with reasonable BPM
volatile boolean secondBeat = false; // used to seed rate array so we startup with reasonable BPM
void interruptSetup(){
// Initializes Timer2 to throw an interrupt every 2mS.
TCCR2A = 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE
TCCR2B = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER
OCR2A = 0X7C; // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE
TIMSK2 = 0x02; // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A
sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED
}
// THIS IS THE TIMER 2 INTERRUPT SERVICE ROUTINE.
// Timer 2 makes sure that we take a reading every 2 miliseconds
ISR(TIMER2_COMPA_vect){ // triggered when Timer2 counts to 124
cli(); // disable interrupts while we do this
Signal = analogRead(pulsePin); // 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 noise
// 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
bpm = BPM; //ALTERADO!
Serial.println("1");
// 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(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;
}
}
if(firstBeat){ // if it's the first time we found a beat, if firstBeat == TRUE
firstBeat = false; // clear firstBeat flag
secondBeat = true; // set the second beat flag
sei(); // enable interrupts again
return; // IBI value is unreliable so discard it
}
// keep a running total of the last 10 IBI values
word 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; // set Quantified Self flag
// QS FLAG IS NOT CLEARED INSIDE THIS ISR
}
}
if (Signal < thresh && Pulse == true){ // when the values are going down, the beat is over
// digitalWrite(blinkPin,LOW); // turn off pin 13 LED
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;
//BPM = 0; // cASO NAO HAJA PULSO
//Serial.println("0");
//bpm = 0;
}
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 = false; // when we get the heartbeat back
}
sei(); // enable interrupts when youre done!
}// end isr
AllSerialHandling:
// Sends Data to Pulse Sensor Processing App, Native Mac App, or Third-party Serial Readers.
void sendDataToSerial(char symbol, int data ){
Serial.print(symbol);
Serial.println(data);
}
Main Code:
Attached
Well, I see a serial print inside the ISR. That's not allowed.
Not in the code you posted. Anything else you didn't tell us?
Sorry, you're talking about the "Serial.println("1");". You're right. But why it's not allowed to put Serial prints inside ISR?
Because an ISR disables interrupts, and Serial depends on interrupts to work. When it fails, it can crash the program.
So i changed my code and now it passes the Interrupt setup method but after exiting setup it just doesn't do anything else. It gets stuck on loop.
See attachment. I only changed the main code (and also removed the Serial printlns)
wifi_withPulse.ino (6.87 KB)