ISR delayMicroseconds in Boron LTE

Hi,

I have a hardware watchdog timer which would send wake pulse (~20ms) and boron sends a DONE pulse (20ms) as response. I am using ISR to do that. It seems to be working so far. But randomly we are seeing issue with cloud disconnects and or charge fault LED blinking. Is there any other better way to do this. I am doing serial read in the loop() function, so cannot implement it there as well.

void STAT_CHANGE_FALLING()
{
  digitalWrite(donePin, HIGH);
  delayMicroseconds(20000);
  digitalWrite(donePin, LOW); 
}

void setup_the_donePin()
{
    pinMode(donePin, OUTPUT); 
    digitalWrite(donePin, HIGH); 

   pinMode(wakeupPin, INPUT_PULLDOWN);
   delayMicroseconds(20000);
   digitalWrite(donePin, LOW); 
      
   attachInterrupt(wakeupPin, STAT_CHANGE_FALLING, FALLING) ; 
}

Thanks

Use of delay() in an ISR is usually bad. 20ms doesn’t seem like a lot but best practice would be to set a flag in the ISR and then process back in loop(). I’m not sure if it matters but you could also switch to delay(20); instead of delayMicroseconds();.

I cannot process that in the loop because I am doing serial read data. I don’t want to miss any data from serial port. I found this in boron documentation.

Since delay() requires interrupts to work, it will not work if called inside an ISR. Using delayMicroseconds() will work as normal.

Good point. Didn’t know that about delay(). Buti meant that for loop() anyways.

@testboron, the delay will stall the DeviceOS. Delays in ISRs are just plain bad, especially 20ms. Instead, you can set a flag and use a software timer running at 1ms intervals to sample the flag and drop the DONE pin to LOW. In fact, you could use the software timer to sample the DONE pin directly if you don’t mind a 1ms (+/-) on responding.

2 Likes

Hi,

I changed my code like below. But still doesn’t work.

void changeDonePinLow()
{
    digitalWrite(donePin, LOW);
}
 Timer timer(20, changeDonePinLow, true);

void STAT_CHANGE_FALLING()
{
    digitalWrite(donePin, HIGH);
    timer.startFromISR(); 
}

void setup_the_donePin()
{
    pinMode(donePin, OUTPUT); 
    pinMode(wakeupPin, INPUT_PULLDOWN);

    attachInterrupt(wakeupPin, STAT_CHANGE_FALLING, FALLING) ; 
}

@testboron, when you say “doesn’t work”, what exactly is not working. You could also pulse the D7 LED pin like you do donePin to see if you can see it. Or, if you have an oscilloscope, see what wakeupPin and donePin are doing. What hardware watchdog chip are you using?

Does this mean that you are potentially locked in tight loop for extended periods while you are reading your serial data?
What data rate are you expecting on your serial port that you can't spare a few clock cycles for minimal tasks like this?

I will be getting serial data every 30 sec ideally. But that can be configured to be 1 sec also.

    // Read data from serial
    while(Serial1.available() ) {
        if (readBufOffset < INPUT_BUF_SIZE) {
            char c = Serial1.read();
            if (c != '\n') {
                // Add character to buffer
                readBuf[readBufOffset++] = c;
                lastCharTime = millis();
            }
            else {
                // End of line character found, process line
                processBuffer(readBuf);
                readBuf[readBufOffset] = 0;
                readBufOffset = 0;
            }
        }
        else {
            log("readBuf overflow, emptying buffer");
            readBufOffset = 0;
        }     
    }