Timing Issues With millis() and interrupts

Hello all.

I am stuck with some weird timing issues. I am trying to blink an LED, when triggered with an interrupt. I am trying to do this with the millis() function, and not the delay() function, outside of the ISR. The issue is, my LED blinks very fast (greater than once a second). I can increase the delay period in my millis() function, but the program stops. Interesting to note, is that if I do use the delay() function, the timing is still way too fast. Thoughts?Preformatted text

int period = 1000;
unsigned long time_now = 0;
int LED = LED_BUILTIN;
int startPin = 2;
volatile byte ledState = LOW;




void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(startPin), blinker, CHANGE);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
}

void blinker() {
  blinking();
}

void blinking() {
  int loopControl = 0;
  while (loopControl != 1) {
    time_now = millis();
    if (time_now > period) {
      ledState != ledState;
      digitalWrite(LED_BUILTIN, ledState);
      Serial.println("Blinking");
    }
  }
}

You failed.

millis() does not work with interrupts disabled, Serial.print should not be used.

blinking does never return.

There are quite a few issues with your code.

This creates an endless loop as loopControl is always 0.

You're basically calling this from inside the interrupt... so everything in blinking is running inside the interrupt. The interrupt should be as quick as possible, and avoid anything that uses interrupts. It is better to just set a variable (volatile) and evaluate that in the rest of your code.

Once your program has been running for 1 second this will always be true, hence the rapid flashing.

unsigned long timepast = millis();

void blinking() {  
int loopControl = 0;
  while (loopControl != 1) {
    //time_now = millis();
    if ( (millis()-timepast) >= period) {
      ledState != ledState;
      digitalWrite(LED_BUILTIN, ledState);
      Serial.println("Blinking");
timepast=millis();
    }
  }
}

perhaps.

Serial.print was for other things, not described in my post.

Thanks for the help! I made my ISR much simpler, and your post got me there!

I see what I did. I changed my ISR, and spliced in your code. I am good to go now. All the best, and thank you!

Regardless, Serial.print() should never be used in an interrupt. Nor should any other serial I/O.

And the very first question is - why did the OP think an interrupt was in any way whatsoever appropriate for this purpose? :astonished: