Am I doing to much in attachInterrupt function?

Hi guys,

Am I doing to much in the interrupt function? The below code works fine and I am getting the result I wanted. The reason that I am using interrupt for the button is because inside the loop() I have functions that is taking up time and causing skip reads when the button pressed by the user. To get by the skip reads issue, interrupt look like a solution. But the document said, interrupt need to be short as possible. So I created this topic to see what issue I would be facing if I do something like the below code inside a interrupt if any.

  pinMode(BFAN, INPUT);
  attachInterrupt(BFAN, butFanFunc, FALLING);

void butFanFunc ()
{
  if ((millis() - lastDebounceTime) > 150) //if current time minus the last trigger time is greater than
    {                                                  //the delay (debounce) time, button is completley closed.
      lastDebounceTime = millis();

      if(digitalRead(BFAN) == LOW && currentModeMenuPick != 34){
        RGB.control(false);         // turn on status led
        analogWrite(LCDDIM, 255);   // turn on tftscreen
        if (pushBFanCount == 1){
          pushBFanCount=0;
          tstCount++;
        }
        else{
          pushBFanCount=1;
          tstCount++;
        }

        // print auto or on to screen
        tft.setFont(ARIAL_18);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.setCursor(20,206);
        tft.print(BFanChoice[pushBFanCount]);
        tft.print("     ");

        Serial.printlnf ("pushBFanCount %d  tcount %d",pushBFanCount,tstCount);
        Serial.println("________________________");

        fanTimer.start();  // start fan timer
        sensTime = millis(); // store sense time
        Serial.printlnf ("sensTime %d",sensTime);
      }
  }

}

@sheng, yes you are doing too much in the ISR. Writing to Serial in an ISR is a no-no since it is a single shared resource and the ISR could fire in the middle of another Serial action. Same applies with writing to the tft since it uses the single SPI resource.

So the real issue is this. I would suggest you need to look at your blocking code in loop() first. The ISR can certainly do most of what you have but not the tft and Serial stuff. That should be done in loop(). Note also that fanTimer.start() needs to be fanTimer.startFromISR()!

I typically run non-blocking timers in loop() for refreshing different parts of my display at different intervals depending of their "speed". The trick is to create non-blocking code. If you share your code, we might be able to help.

1 Like

@peekay123, Thank you for the quick reply. The Serial.print are for my sanity check, but the tft I do need to keep in sync with the user pushes.

Look like I will have to change my draw screen more like yours since right now I am drawing the screen all in one function and I notice this contribute to skip reads for the button. Will definite post the code if I can't figure it out. Thanks for the help.

@sheng, in my case, I found that redrawing the entire screen took too long and instead, I only draw specific areas at different intervals of 1 sec, 750ms and 250ms. This keeps loop() running nicely in between.

@peekay123, I also found that redrawing the entire screen took to long. Finally, I was able to get it working on my screen with intervals of 1 sec and 500ms, thanks to your information.

Is there a limit on global variable that could be define in the firmware? It seem like if I added to much global variable, one of my other global variable is acting up. It always stay zero no matter how I change it.

You might also be able to do something like this to help in these situations.

pinMode(BFAN, INPUT);
attachInterrupt(BFAN, butFanFunc, FALLING);

boolean pressed= false;

void butFanFunc ()
{
pressed= true;
}

loop()
{
if(pressed)
{
pressed= false;

    // Do what you need to
}

}