Maths routine problem???

Discussion in 'Programmer's Corner' started by asm_lan, Jul 30, 2007.

  1. asm_lan

    Thread Starter New Member

    Jul 30, 2007
    9
    0
    Hi all,
    I'm currently doing a project on measuring heart rate using a sensor.
    I have tried programming to display the beats per min(BPM) on a LCD but to no avail. I'm using Silabs C8051F226 development kit. The LCD only displays 2 values either "77 BPM" or "154 BPM". I'm using a timer and an external interrupt. In the external ISR, when the 1st pulse comes in, i'll start the timer and stop the timer at the 2nd pulse. And in the timer ISR, i count the number of overflows. I suspect that my overflows counter always count from 1-2 only... Thats why in my maths routine, it gave me the 2 values.

    My code are as follows:
    Code ( (Unknown Language)):
    1.  
    2. ;***************************************
    3. ;-----------INTERRUPT CONFIGURATIONS-----------
    4. ;***************************************       
    5. SETB EA      ; Enable Global Interrupts
    6. SETB ET0     ; Enable Timer 0 Interrupt
    7. SETB EX0     ; Enable External Interrupt 0
    8. SETB PX0     ; External Interrupt 0 High Priority
    9.  
    10. ;***************************************
    11. ;------------TIMER 0 CONFIGURATIONS------------
    12. ;***************************************
    13. TIMER_0 EQU 65535
    14. SETB IT0                                         ; External Interrupt 0 detect falling-edge
    15. MOV TMOD,#01H                           ; Set Timer 0 to Mode 1    
    16. MOV A,CKCON                               ; Move CKCON to Accumualtor
    17. CLR ACC.3                                     ; Set system clock to divided by 12
    18. MOV 70H,#00H                               ; Move 0 to 70H
    19. MOV R7,#02H          ; Move 4 to R7
    20. MOV 62H,#01H             ; Move 1 to 62H
    21. MOV TH0,#HIGH TIMER_0       ; Set High Byte of Timer 0
    22. MOV TL0,#LOW TIMER_0        ; Set Low Byte of Timer 0
    23.  
    24. ;**********************
    25. ;-Wait Until 4th Pulse-
    26. ;**********************
    27. WAIT:   CJNE R7,#00H,WAIT  ; Compare and jump to subroutine "WAIT" if R7 != 0
    28. CLR TR0         ; Stop Timer 0
    29.  
    30. ;******
    31. ;-Math-
    32. ;******
    33. MATH:   MOV A,#9AH      ; Move 154 to A
    34.     MOV B,70H
    35.     DIV AB
    36.     MOV R6,A
    37.  
    38. ;**********************
    39. ;-External Interrupt 0-
    40. ;**********************
    41. EX_INT0:    DJNZ 62H,COUNT  ; Decrement 62H and jump if != 0
    42.     SETB TR0    ; Start Timer 0
    43.  
    44. COUNT:  DEC R7      ; Decrement R7
    45.     RETI        ; Return from Interrupt
    46.  
    47. ;***********************
    48. ;-Timer 0 Overflow Flag-
    49. ;***********************
    50. T0_INT: INC 70H         ; Overflow Counter
    51.              MOV TH0,#HIGH TIMER_0  ; Reloads Timer 0 with High Byte
    52.     MOV TL0,#LOW TIMER_0    ; Reloads Timer 0 with Low Byte
    53.     RETI            ; Return from Interrupt
    54.  
    Any advice?
     
  2. beenthere

    Retired Moderator

    Apr 20, 2004
    15,815
    282
    Accumulate the beats in a register. Use the timer to mark an interval - say 15 seconds. When it times out, multiply the register count by 4 for BPM. Don't forget to clear the count before the next interval.
     
  3. asm_lan

    Thread Starter New Member

    Jul 30, 2007
    9
    0
    Meaning i start the timer to run for 15 secs and count the number of pulses for 15 secs and multiply by 4 to get the result?

    EDIT: I have tried the method, but it is not accurate. Like when i input 1.2Hz, it gave me a value of 80BPM. The higher the frequency, the more it is not accurate...
     
  4. beenthere

    Retired Moderator

    Apr 20, 2004
    15,815
    282
    How certain are you that the input is clean? It might be helpful to know what interface circuitry is inputting the heart rate.
     
  5. asm_lan

    Thread Starter New Member

    Jul 30, 2007
    9
    0
    I test the program using a fuction generator... Since its from the function gen, shouldn't it be clean enough for the 8051 to detect? :confused:

    I have another question:

    Does the 8051 have a range for detecting pulses?
    For example: below/above certain frequencies or below/above certain amplitudes, it cannot detect?:confused::D
     
  6. beenthere

    Retired Moderator

    Apr 20, 2004
    15,815
    282
    It can't count pulses that come faster than the counting register can increment. I believe it is necessary to use external circuitry to introduce the signals to the 8051 - an interface circuit. What are you using to do this function?
     
  7. asm_lan

    Thread Starter New Member

    Jul 30, 2007
    9
    0
    I'm using a timer and an external interrupt pin to do this function... I start the timer for 10 secs. Whenever, there is a falling edge on the external interrupt pin, the counter will increase...
     
  8. beenthere

    Retired Moderator

    Apr 20, 2004
    15,815
    282
    If the levels of the pulse satisfy the electrical requirement of the 8051's input, then the interrupt should get generated.

    By the way, your code shows that you initialize R7 with 02h. The interrupt routine has you decrementing the value in R7. How is this going to count the number of inputs? Shouldn't you set the register to 0 and then increment it with each interrupt?
     
  9. asm_lan

    Thread Starter New Member

    Jul 30, 2007
    9
    0
    I see.... Thanks... :D

    EDIT: I have tried the code below to start the timer for 5 secs and count the number of pulses than multiplying by 12 to get the result. But it is not accurate. I have to multiply it by 11 to make it more accurate... It still have a error of -8 to 8 BPM...

    This is the code that i used:

    Code ( (Unknown Language)):
    1.  
    2. ;**********
    3. ;-Definitions-
    4. ;**********
    5. COUNTER EQU 70H
    6. START_TIMER EQU 60H
    7.  
    8. ;***************************************
    9. ;-----------INTERRUPT CONFIGURATIONS-----------
    10. ;***************************************
    11. SETB EA      ; Enable Global Interrupts
    12. SETB ET0     ; Enable Timer 0 Interrupt
    13. SETB EX0     ; Enable External Interrupt 0
    14. SETB PX0     ; External Interrupt 0 High Priority
    15.  
    16. ;**********************************************
    17. ;-------------TIMER 0 CONFIGURATIONS-----------
    18. ;**********************************************
    19. SETB IT0        ; External Interrupt 0 detect falling-edge
    20. MOV TMOD,#01H   ; Set Timer 0 to Mode 1
    21. MOV A,CKCON ; Move CKCON to Accumualtor
    22. CLR ACC.3            ; Set system clock to divided by 12
    23. MOV START_TIMER,#01
    24.  
    25. ;********************
    26. ;-Initialize Timer 0-
    27. ;********************                  
    28. INIT:   MOV COUNTER,#00H    ; Initialize counter to count pulses to zero.
    29.     MOV TH0,#3CH        ; Initialize Timer 0 to run for 50ms
    30.     MOV TL0,#0B0H                      
    31.  
    32. ;****************
    33. ;-Wait for pulse-
    34. ;****************
    35. WAIT:   JNB EX0,WAIT        ; Wait for pulses to generate interrupt
    36.     ACALL DELAY2        ; Make Timer 0 loop for 100 times to get 5 secs
    37.  
    38. ;**********************
    39. ;-External Interrupt 0-
    40. ;**********************
    41. EX_INT0:    DJNZ START_TIMER,COUNT  ; Start Timer 0 only once
    42.     SETB TR0        ; Start Timer 0
    43.  
    44. COUNT:  INC COUNTER     ; Count number of pulses               
    45.              RETI
    46.  
    47. ;***********************
    48. ;-Timer 0 Overflow Flag-
    49. ;***********************
    50. T0_INT: NOP         ; Do nothing
    51.     RETI
    52. ;**************
    53. ;-Delay for 5 secs-
    54. ;**************
    55. DELAY2:   MOV R0,#100D     
    56. D7: CLR TF0        
    57.     MOV TH0,#3CH            ; Loop Timer 0 using 12 MHz
    58.     MOV TL0,#0B0H           ; crystal to run for 5 secs
    59. D8: JNB TF0,D8 
    60.     DJNZ R0,D7
    61.     CLR TR0                    
    62.     RET
    63.  
     
  10. beenthere

    Retired Moderator

    Apr 20, 2004
    15,815
    282
    At this point, about all I can suggest is to insestigate why the count varies so much. If you can set your function generator to accurately run at an accurate frequency and the accumulated count does not agree, then something must be wrong. If the value in the counter is not always the same, then the timing loop must be incorrect.

    If you do 10 runs with the function generator and the 10 values in the counter are not accurate, then you will need to tinker with your code. This can be frustrating, but the accumulated count should be repeatable.
     
  11. asm_lan

    Thread Starter New Member

    Jul 30, 2007
    9
    0
    I see... Thanks:D:D
     
Loading...