Run time error when using rising edge pin interrupt

Hello, I am writing a piece of software as part of an assignment to calculate heart rate. The hardware itself is working nicely and I am able to graph my incoming signal on the LCD display in software with no problem. My problem occurs when I enable a rising edge interrupt to act as a frequency counter(this signal is sanitised via a schmitt trigger). As soon as I do that, that mbed will crash sooner rather than later. There is an error code that is displayed via one of the blue LEDs, but the documentation does not list what these codes mean. I have tried reducing the code in my ISR to the very minimum and it does take a little longer to crash. I am struggling to understand how this ISR can make the mbed crash, if I had a way to interpret the flashing LED then it would be helpful, but as I don’t I am unsure where to begin. I have attached my code below.

Thank you

#include "mbed.h"
#include "C12832.h"

AnalogIn   ECG_read(A2);
C12832 lcd(p5, p7, p6, p8, p11);
InterruptIn ECG(p9);
Timer t;

void heartRise(void);

int bpm = 0;
int oxy = 75;

uint32_t previousTime = 0;
uint32_t currentTime = 0;



int main(void)
{
    ECG.rise(&heartRise);
    while (1)
    {
        bpm = 60000/(currentTime-previousTime);
        int sample = 0;
        int previous_sample = 0;
        float read=0;
        lcd.cls();
        lcd.rect(46, 0, 127, 31, 1);

    
        lcd.locate(1,10);
        lcd.printf("O2:%d",oxy);
        while(true) { 
  
            lcd.locate(1,1);
            lcd.printf("BPM:%d",bpm); 
            for (int j=0; j<80;j++)
            {
                previous_sample=sample;
                read=ECG_read*32;  
                sample=read;  
                lcd.line(j+47, 32-previous_sample, j+48, 32-sample, 1);
                wait(0.02);
            }
            lcd.fillrect(47, 1, 126, 30, 0);
        }
    }
}



void heartRise(void)
{
    previousTime = currentTime;
    currentTime = t.read_ms();
}

Hi there,

I little bit not understand your code.

  • Object Timer was never started, t.start() is missing
  • In the documentation of Timer

the read_ms() and read_us() methods only return 32-bit signed integers

  • First bmp variable calculation
bpm = 60000/(currentTime-previousTime);
//It is same like 
bpm = 60000/(0-0);
  • How program reach the second while loop, then it never left it and also the bpm printed again and again will be never changed. So what is benefit of the first while loop?
  • Interrupt’s callback looks ok but, because you never start the timer, nothing will be measure. Also the variables are not used out of bpm calculation, so the measurement in the callback have no effect.
  • Maybe would be useful declare these global variables as volatile.

I apologize, but can you explain how it works?

BR, Jan

Hi, thanks for your response. The BPM calculation was originally in the ISR, I moved it to the main loop whilst trying to debug, you are right that I should have put it into the second while loop and the divide by zero will be because of that move (it originally calculated inside the isr so would not have been zero). The first while loop was added at the same time, I’m not sure of my thinking as to why I did that. I will make sure I start the timer as the program initialises. The second while loop is just looping round and graphing the analogue input onto the LCD screen, this works fine when I don’t have the interrupt triggered. I think I shouldn’t be trying to code whilst feeling unwell, these are some silly errors.

Thank you.

David, just try to make you code simplest how it can be, ideally without use of the LCD only for reproduce of your issue and then after a verification by your self, edit your code above in first post.

BR, Jan

Thanks for the help, I think the problem was the variable not being set to volatile. I had a google about what the volatile keyword does and it makes sense, I was changing the global variable under interrupt; I feel like I have learned something new and useful. My code is working well for now, I am going to save a snapshot of it so I can roll back should any further changes break it.

#include "mbed.h"
#include "C12832.h"

AnalogIn   ECG_read(A2);
C12832 lcd(p5, p7, p6, p8, p11);
InterruptIn ECG(p9);
Timer t;

void heartRise(void);


volatile int bpm[5] = {0,0,0,0,0};
int oxy = 75;

volatile uint32_t previousTime = 0;
volatile uint32_t currentTime = 1;



int main(void)
{
    t.start();
    ECG.rise(&heartRise);
    while (1)
    {
        
        int sample = 0;
        int previous_sample = 0;
        float read=0;
        lcd.cls();
        lcd.rect(46, 0, 127, 31, 1);

    
        lcd.locate(1,10);
        lcd.printf("O2:%d",oxy);
        while(true)
        { 

            bpm[4]=bpm[3];
            bpm[3]=bpm[2];
            bpm[2]=bpm[1];
            bpm[1]=bpm[0];
            bpm[0] = 60000/(currentTime-previousTime);
            lcd.locate(1,1);
            lcd.printf("BPM:%d   ",(bpm[0]+bpm[1]+bpm[2]+bpm[3]+bpm[4])/5);
            
            for (int j=0; j<80;j++)
            {
                previous_sample=sample;
                read=ECG_read*32;  
                sample=read;  
                lcd.line(j+47, 32-previous_sample, j+48, 32-sample, 1);
                wait(0.02);
            }
            
            lcd.fillrect(47, 1, 126, 30, 0);
        }
    }
}



void heartRise(void)
{
    previousTime = currentTime;
    currentTime = t.read_ms();

}

That’s great news, David.
You are welcome
BR, Jan