0

I am using a function outside loop(), which is called after an interrupt. Inside this function, I am setting several relays that need to change after a second or two, depending on my setting. I tried the delay, it doesn't work. millis() isn't working as well; I found out it stops counting when I exit the loop function.

My code looks something like this:

const long on_interval = 2000;
unsigned long currentMillis = millis();
bool hv_bool = false;

void hv_switch() {
    if (digitalRead(hv_pin)==HIGH){
        hv_startup();
    }
}

void hv_startup() {
    unsigned long previousMillis = 0;
    digitalWrite(pre_charge, HIGH);
    digitalWrite(main_charge, LOW);
    //Wait interval
    previousMillis = currentMillis;
    while (currentMillis - previousMillis < on_interval) {
        Serial.println(millis());
        //Wait
    }
    digitalWrite(pre_charge, LOW);
    digitalWrite(main_charge, HIGH);
    hv_bool = true;
    loop();
}

void setup(){
    //Set some ports

    //Initiate interrupt 
    attachInterrupt(digitalPinToInterrupt(hv_pin), hv_switch, RISING);
}

void loop() {
    //Low voltage loop after startup, high voltage off
    while (hv_bool == false) {
        Serial.println("Waiting on high voltage");
        digitalWrite(hv_led, LOW);
        digitalWrite(pre_charge, LOW);
        digitalWrite(main_charge, LOW);
    }
}
1
  • millis() works fine in any function, except in interrupt context, where it doesn't increment. Jul 16 '16 at 12:26
2

@EdgarBonet has it - hv_startup() is part of the the interrupt handler. Interrupt handlers should be as short (timewise) as possible, doing only what has to be done with the interrupts off, and leaving longer tasks for the mainline (loop() and its sub-functions) to do.

But a bigger problem is that loop() is called from hv_startup(), also getting used as part of the interrupt handler, and loop() has a while{} loop that depends on hv_bool, which can never get changed, 1) because there is no statement to set it false (besides the initialization); and 2) because loop is now running at interrupt level and no more interrupts (at the same level) can be taken.

So I'd suggest several fixes:

  • Don't call loop from your interrupt handler. When your handler exits, loop() will resume from wherever it was when it got interrupted.

  • Don't delay in your interrupt handlers. If the interrupting hardware needs to be reset, do that and any other processing you have to do while the interrupts are off. But if some longer processing needs doing, set a flag in the interrupt handler (remember to declare it to be 'volatile'!), and exit.

    • In loop(), test the flag. If it is set, clear it and call another function to handle the less urgent processing required by the interrupt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.