Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Flowcode programming

Status
Not open for further replies.

kokos

Member
I am currently building a Heart rate monitor based on an optical sensor attached on the Index finger and i am using PIC16F84A microcontroller for counting the beats per minute and drive 3 7-segnebt Displays. I ve designed the first part of the circuit for amplification and filtering but i am having some problems for programming the PIC. I am using Flowcode for programming the PIC but there are not a lot of tutorials or helpful articles about how to use Flowcode. Actually what i need to do is to program the PIc to count the time between two peaks(digital pulses in its input RB0) and do that for about 10 seconds and after to give an average result (Heart Rate) in beats per minute (Heart Rate=60/Time). If somone can help me and knows how to use Flowcode please reply to me and i will supply you with the Schematic Diagram and ask more specific questions. Actually at the moment i am having problems with the interrupt which is running all the time and the program doesnt return back to the main. I hope somebody can help me.

Thanks
 
Can't help with flowcode but if the interrupt is running continuously then it is probably because you aren't clearing INTF in the interrupt.

Mike.
 
Can't help with flowcode but if the interrupt is running continuously then it is probably because you aren't clearing INTF in the interrupt.

Mike.

Mike thanks for your reply
For this device i should program the PIC to count the time between two heart pulses. the pulse signal is applied to RB0 input of the PIC and i need to program it to interrupt whenever the signal goes high and count how many 2ms intervals there are between two heart beat pulses. Then this number is divided into 60,000 to give the heart rate in beat per minute. do you know if first i need to set the interrupt RB0/INT to interrupt when the signal goes high and then to set the TMR0 counter overflow? i confused a bit here.

Thanks
kokos
 
Try increasing a register every time Timer0 overflows, then when your RB0 pin goes high you can read the register count (to give you the last time between heart beats) and then reset the register to 0 in order to read the next time between beats.
 
Try increasing a register every time Timer0 overflows, then when your RB0 pin goes high you can read the register count (to give you the last time between heart beats) and then reset the register to 0 in order to read the next time between beats.

Hi Gobbledok
Thanks for your reply

I am using Flowcode to write the program for the PIC16F84A. i set a push to make switch for RB0 which everytime i press it its like a possitive peak enters the RB0 input and when i release it goes back to zero. each time i press it the program is interrupted by RB0/INT (rising edge) where i set it to do (Peak=Peak+1). in the same interrupt (RB0/INT) i set another interrupt for RB0 timer overflow but i dont know how to use it and get the time between two heart pulses. do i need both interrupts (RB0/INT for rising edge and TMR0 overflow)? if you know how to use flowcode i can upload my code and tell me what i am doing wrong.
Thanks
Regards
kokos
 
Hi Gobbledok
Thanks for your reply

I am using Flowcode to write the program for the PIC16F84A. i set a push to make switch for RB0 which everytime i press it its like a possitive peak enters the RB0 input and when i release it goes back to zero. each time i press it the program is interrupted by RB0/INT (rising edge) where i set it to do (Peak=Peak+1). in the same interrupt (RB0/INT) i set another interrupt for RB0 timer overflow but i dont know how to use it and get the time between two heart pulses. do i need both interrupts (RB0/INT for rising edge and TMR0 overflow)? if you know how to use flowcode i can upload my code and tell me what i am doing wrong.
Thanks
Regards
kokos


Hi, no idea about flowcode sorry.

Yep you will need to use both interrupts. Whenever Timer 0 overflows you need to increase a register count. Then when the interrupt (heart beat) occurs on RB0, you have to read the value of the register which you increase with Timer 0.

For example, if the value of the register is 55 and your Timer 0 interrupt occurs every 10 milliseconds, then that means there was 550 milliseconds between the last beats.

The last thing you need to do with the RB0 interrupt is reset the count register back to 0 in order to count the next period.


So basically:

TMR0 Interrupt: Increase a counter (that's all it needs to do)

RB0 Interrupt: Read the counter, store the number for use in the main program, reset the counter.
 
Hi, no idea about flowcode sorry.

Yep you will need to use both interrupts. Whenever Timer 0 overflows you need to increase a register count. Then when the interrupt (heart beat) occurs on RB0, you have to read the value of the register which you increase with Timer 0.

For example, if the value of the register is 55 and your Timer 0 interrupt occurs every 10 milliseconds, then that means there was 550 milliseconds between the last beats.

The last thing you need to do with the RB0 interrupt is reset the count register back to 0 in order to count the next period.


So basically:

TMR0 Interrupt: Increase a counter (that's all it needs to do)

RB0 Interrupt: Read the counter, store the number for use in the main program, reset the counter.

Hi Dobbledok

Thanks for your help again
is my first time that i am trying to write a code but i find it interesting even if is quite difficult for the first time. i will tell you the steps i used for my program and tell me if there is something that you dont agree and i didnt understand correct.
In flowcode each time i am running the code i can see the values of variables and the calculation on the LCD display. so i used one LCD display (2x16) which is connected to PortB (1-6 bits). Pin RB0 is the input and i used a push to make switch in flowcode connected to RB0. so each time i press it is like a peak in RB0 and when i release it it goes to zero.
My main code is as follows.
1)LCD start
2)set initial Time=0,Count=0,Peak=0
3)Call macro (Rising Edge)
4)Enable Interrupt RB0/INT on macro Rising Edge
5)Main Loop while 1
6) call input Loop while Input=0 and i included in that loop only call macro Input_RB0
7)outside the call input Loop Time=Time+1
8)END
Input_RB0 macro contains
1)Begin
2)RB0->Input
3)END
Rising Edge interrupt contains
1)Begin
2)Peak=Peak+1
3)Call macro counter
4)Enable interrupt TMR0 overflow on macro counter
5)END
interrupt Counter contains
1)Begin
2)count=count+1
3)If count=5 then call component macro EEPROM(write value of count) then call component macro EEPROM (READ), then BPM=12*count, then sent BPM to LCD, then RESET count=0,time=0, then dissable TMR0 interrupt, END
thats all i ve done and i know that i have a lot of mistakes. i hope you can understand as i wrote them here and be able to help me..i really appreciate your help.
when i run this code, each time i press the switch the count and peak are increasing by one and when count =5 the bpm appeare on the LCD and then the values of count and peak are set to zero again.
i know that i confused the count, peak and time variables and thats the why i cant get proper results during simulation..i am trying to find a way and fix them but again something goes wrong..

thanks for your help
 
You want to increase your count register by the timer, not by RB0 interrupt. As it is now, each register increases with RB0 and you are counting 5 pulses and then resetting the timer and count to 0. Nowhere there are you actually timing the length of time if takes for 5 interrupts on RB0.

Therefore every time you get 5 pulses, you are multiplying the number of pulses (always 5) by 12, which will always give you 60 BPM.


So you need to increase Count every time Timer 0 overflows. Increase Peak every time you detect a heart beat. Then when Count reaches 5 (or whatever), you need to look at the Peak register to see how many heart beats occured during that period.
 
You want to increase your count register by the timer, not by RB0 interrupt. As it is now, each register increases with RB0 and you are counting 5 pulses and then resetting the timer and count to 0. Nowhere there are you actually timing the length of time if takes for 5 interrupts on RB0.

Therefore every time you get 5 pulses, you are multiplying the number of pulses (always 5) by 12, which will always give you 60 BPM.


So you need to increase Count every time Timer 0 overflows. Increase Peak every time you detect a heart beat. Then when Count reaches 5 (or whatever), you need to look at the Peak register to see how many heart beats occured during that period.

ok thanks for your help Gobbledok
I will make the corrections that you told me and i will send you back as soon as i will finish it. when i will get it right i will also compile the code to c and upload it here so everyone can see it
Regards
kokos
 
You want to increase your count register by the timer, not by RB0 interrupt. As it is now, each register increases with RB0 and you are counting 5 pulses and then resetting the timer and count to 0. Nowhere there are you actually timing the length of time if takes for 5 interrupts on RB0.

Therefore every time you get 5 pulses, you are multiplying the number of pulses (always 5) by 12, which will always give you 60 BPM.


So you need to increase Count every time Timer 0 overflows. Increase Peak every time you detect a heart beat. Then when Count reaches 5 (or whatever), you need to look at the Peak register to see how many heart beats occured during that period.

Hi Gobbledok
I made the corrections that you told me but still i m having some problems..(i dont know if i am doing something wrong again)
Please see attached a picture of the code that i wrote in Flowcode.
When i run the program the register 'count' (TMR0 overflow) is increasing untill reach 150 interrupts which is at 10seconds.(i am using 4Mz crystal and i choosed in the program a prescale value:1:256 which is 15Hz interrupt frequency in 1 second).each time i press RB0 (switch) is like input goes high and RBO/INT (Rising_Edge) is enabled and Heart_Beat is increasing by one each time i press the RB0 switch.so when the program runs in the TMR0 overflow the count is increasing untill goes count<150 and i am pressing the RB0 switch where i see the heart beats increasing by one each time during this 150 interrupts. after the 150 interrupts of TMR0 overflow do i need to calculate the BPM=(Heart_Beats*60)/10seconds which is BPM=6*Heart_Beats and display them in the LCD? do you think is accurate measurment? as you told me i shall Reset the register 'count' inside the RB0/INT (Rising_Edge) and i did it but each time i press RB0 switch when the program runs the count is reset to 0 before reach the 150 interrupts.what i am doing wrong?
Thanks
kokos
 

Attachments

  • HRM_Code..jpg
    HRM_Code..jpg
    333.3 KB · Views: 1,348
You don't need to reset the Count register now in the Rising_edge macro. That was before when we were going to measure the period between heart beats. Now, because we are measuring the number of beats over a 10 second period, the Count register only gets reset when it reaches 150.

In the InputRB0 macro, where you call the Rising_Edge macro, replace it with [Heart_Beat = Heart_Beat + 1] and take [Heart_Beat = Heart_Beat + 1] out of the Rising_Edge macro.

Then, change the name of the Rising_Edge macro (to something like Timer_Done), and call it once your timer count reaches 150. Then you are working out the BPM after the counter has reached 150 (the only way to do it this way). The only problem with this (may not even be a problem) is that you will only get a reading every ten seconds and the initial reading will take ten seconds to show properly.

I imagine it will be pretty accurate, the only way to make it more accurate would be to increase the time over which you measure the BPM.
 
Last edited:
You don't need to reset the Count register now in the Rising_edge macro. That was before when we were going to measure the period between heart beats. Now, because we are measuring the number of beats over a 10 second period, the Count register only gets reset when it reaches 150.

In the InputRB0 macro, where you call the Rising_Edge macro, replace it with [Heart_Beat = Heart_Beat + 1] and take [Heart_Beat = Heart_Beat + 1] out of the Rising_Edge macro.

Then, change the name of the Rising_Edge macro (to something like Timer_Done), and call it once your timer count reaches 150. Then you are working out the BPM after the counter has reached 150 (the only way to do it this way). The only problem with this (may not even be a problem) is that you will only get a reading every ten seconds and the initial reading will take ten seconds to show properly.

I imagine it will be pretty accurate, the only way to make it more accurate would be to increase the time over which you measure the BPM.

I made the corrections you told me and its working fine i think.thanks for your help. when the program runs, each time i m pressing RB0 switch the value of BPM appears on the LCD before count=150 and each time i am pressing it the value of BPM updates on the LCD but its not the correct one. after the count=150 it updates again with the correct value. do you know why is that?and how to stop doing it before count=150?

Please see attached the new code with the corrections you told me

and something else. the external crystal i am using for the PIC16F84A is 4MHz, inside the flowcode i can choose which prescaler rate to use.i ve chosen 1:256 which it says interrupt frequency 15Hz. (please see attached)is that correct that i say 150 interrupts occur every 10seconds? and you think is the correct way to calculate the BPM=6*Heart_Rate?or i shall do it by measuring the time between two peaks and then divide into 60?


Regards
kokos
 

Attachments

  • HEARTRATE_CODE..jpg
    HEARTRATE_CODE..jpg
    352.5 KB · Views: 1,063
  • HEARTRATE_CODE_Pre&#11.jpg
    HEARTRATE_CODE_Pre&#11.jpg
    381.6 KB · Views: 883
Looking at the code I have no idea why the heartbeat is updated each time RB0 goes high. As it is, it should only be updated every time the counter reaches 150 (if I'm reading it right).


I don't think it will change anything but I would also change the Timer macro to the picture below.

For the interrupt: Yep that's right. Because the interrupt occurs at 15.2588Hz, I would change your counter to 152 or 153 for more accuracy, though it won't make much difference.

The way you are counting heart beats is probably better and more accurate, however slower. If you can handle waiting 10 seconds for a reading I'd leave it as it is.
 

Attachments

  • Flowcode..jpg
    Flowcode..jpg
    24.1 KB · Views: 2,163
Looking at the code I have no idea why the heartbeat is updated each time RB0 goes high. As it is, it should only be updated every time the counter reaches 150 (if I'm reading it right).


I don't think it will change anything but I would also change the Timer macro to the picture below.

For the interrupt: Yep that's right. Because the interrupt occurs at 15.2588Hz, I would change your counter to 152 or 153 for more accuracy, though it won't make much difference.

The way you are counting heart beats is probably better and more accurate, however slower. If you can handle waiting 10 seconds for a reading I'd leave it as it is.

Thanks i really appreciate your help.
Regards
kokos
 
I've been meaning to have a play with flowcode for a while and so thought this would be a good time. I implemented your code without the LCD stuff but with a few changes. I've looked at the C code produced and it appears to be correct. The main change I made was to use a second variable (DoneCount) which the interrupt sets to count after 150 timer interrupts. This new variable (DoneCount) is then used in the main loop to update the display.

You can't really see from the diagram but when count=150 I do the following,
DoneCount=Heart_Beat
Heart_Beat=0
count=0

Edit, forgot to mention why I did it this way. It is because calling the display routines from the interrupt takes a long time and pulses could be missed during this time.

Mike.
 

Attachments

  • FlowCode..png
    FlowCode..png
    83.4 KB · Views: 7,364
Last edited:
I've been meaning to have a play with flowcode for a while and so thought this would be a good time. I implemented your code without the LCD stuff but with a few changes. I've looked at the C code produced and it appears to be correct. The main change I made was to use a second variable (DoneCount) which the interrupt sets to count after 150 timer interrupts. This new variable (DoneCount) is then used in the main loop to update the display.

You can't really see from the diagram but when count=150 I do the following,
DoneCount=Heart_Beat
Heart_Beat=0
count=0

Edit, forgot to mention why I did it this way. It is because calling the display routines from the interrupt takes a long time and pulses could be missed during this time.

Mike.

Hello Mike
Do you think is ok to leave my code as it is now? i also asked Dobbledok for this and he said that the code looks correct as i also believe but do you know why each time i m pressing RB0 switch the Heart Rate appears on the LCD before even count=150 and continue to update for each heart beat detected untill when count=150 and then it updates the correct value for 10 seconds.

Regards
kokos
 
It is because your main code is calling the two interrupt macros. If you remove these two calls I think it will work correctly.

Mike.
 

Attachments

  • FlowCode..png
    FlowCode..png
    131.9 KB · Views: 1,585
It is because your main code is calling the two interrupt macros. If you remove these two calls I think it will work correctly.

Mike.

thanks Mike for your quick reply because i must finilise it and have it ready in two hours and i m working long time on that code as is the first time in my life dealing with programming.

if i remove the calls for input RB0 and for TMR0 (INT_COUNTER) from the main loop where i shal place them for call these two macros? sorry about this question but i am really new in programmin.
and something else as it is now (except the point you mentioned that i need to find the solution) is it ok to transfer it into the PIC? shall i do any other corrections? and something last, in my circuit i connected a snap switch as a reset button to MCLR (pin4) of the PIC16F84A and to +5volts. do i need to include and this into the code?
thanks
Regards
kokos
 
There is something strange going on with flowcode. I ran the code I implemented and set a breakpoint in the timer interrupt and it never triggered. The C code is correct but in the flowcode simulation it never executes the timer0 interrupt.

Mike.
 
There is something strange going on with flowcode. I ran the code I implemented and set a breakpoint in the timer interrupt and it never triggered. The C code is correct but in the flowcode simulation it never executes the timer0 interrupt.

Mike.

As i have it now, what is actually doing when i press the run in flowcode, it starts right away increasing the count by 1 (without pressing RB0 switch) and each time i press the RB0 switch i can actually see that the variable Heart_Beat it is also increasing by 1 and when count reaches 150 it is accurately display the value of BPM=6*Heart_Beat. ofcourse with the exception that during the whole simulation the BPM is appeared on the LCD. as you told me is due to that i call both macros in the main loop but i cant find a solution for this since i dont know where i shall move these calls.
thanks
kokos
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top