Flashing LED With Interrupt

Hi,

I want to be able to turn on an LED and have it flash while it is "on".

I had it set up in a loop but because it can currently only process one thing at a time, it would sit there flashing forever. there was no way to interrupt it and break it out of the loop.

I have also seen the attachInterrupt() article from arduino but as i understand it, it can only interrupt from a pin changing state (external interrupt). Can I interrupt it programmatically (internal interrupt)?

Or is there a better way to do what I have described?

Thanks

Simon Lehmann

You say you want the LED to flash but at what frequency/duty cycle do you want it to flash? It might be worth checking out the Timer1 (or Timer3) library here.

Riva:
You say you want the LED to flash but at what frequency/duty cycle do you want it to flash? It might be worth checking out the Timer1 (or Timer3) library here.

Yes. I want to blink an LED indefinitely and be able to interrupt it. For example the LED should start blinking at 2hz and when a programmatical state changes, the LED should stop blinking and the program continues.

I will check out your link.

Thanks

If you use the "Blink Without Delay" paradigm to blink your led then you can have it do anything you want outside of the blinking. I regularly include the following code in many projects so I'll have a blinking led to let me know that the board is indeed running even if it's not doing what I want it to:

void heartbeat() {
        static byte heartState = 1;
	static unsigned long previousBeat = millis();
	unsigned long currentMillis = millis();
	if (currentMillis - previousBeat >= 1000) {
		previousBeat = currentMillis;
		heartState ^= 1;
		digitalWrite(heartbeatPin, heartState);
	}
}

That function gets called from loop along with whatever else I'm doing. It would be trivial to use an if statement to decide whether or not to call that function or to stop calling it and stop the led from blinking.

slehmann36:
I have also seen the attachInterrupt() article from Arduino but as i understand it, it can only interrupt from a pin changing state (external interrupt). Can I interrupt it programmatically (internal interrupt)?

Or is there a better way to do what I have described?

You do not understand what interrupts are!

OK, not surprising, a terribly common "newbie" mistake. :grinning: :grinning:

An interrupt cannot be used to "programmatically" interrupt a loop. The very concept of an interrupt is to execute and return to wherever the code was executing at the time the interrupt was triggered, without affecting that code.

It is in fact the case that you can in the interrupt, set a "flag" - a variable which your loop will at some point read and take whatever action is necessary, but that is in most cases, an absurd complication when what you actually want is to "poll" or check within the loop, the device - such as a switch - that you wish to control the alternate action.

Note in general, that you do not - should not - use indefinite loops (such as "while") within your code. The loop() function in the standard sketch is all you need to perform repetitive actions (which is in fact, what the vast majority of programs do). What you do is to include in that loop, switches and counters which control repetitive actions.

As an example, study my multiple flashing code:

// Blink without "delay()" - multiple with on/ off switch

const int led1Pin =  13;    // LED pin number
const int led2Pin =  2;
const int led3Pin =  5;
const int button1 =  10;

char led1State = LOW;        // initialise the LED
char led2State = LOW;
char led3State = LOW;
char bstate1 = 0;
char doflash = LOW;

unsigned long count1 = 0;   // will store last time LED was updated
unsigned long count2 = 0;
unsigned long count3 = 0;
unsigned long bcount1 = 0;  // button debounce timer.  Replicate as necessary.

// ----------------------------- toggle ------------------------------------------
char toggle(char *flip) {   // Yes, it toggles the variable pointed to
  if (*flip == LOW) {
    *flip = HIGH;
  }
  else {
    *flip = LOW; 
  } 
  return *flip;
}

// ----------------------------- timeout -----------------------------------------
// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check 
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

// --------------------------- button read ---------------------------------------
// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, 2 or > if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

// -------------------------------------------------------------------------------
void setup() {
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(button1, INPUT);
  digitalWrite(button1,HIGH);        // internal pullup all versions
}

void loop() {
  // Toggle switch if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) if (toggle(&doflash) == LOW) {    
    // Turn off LEDs only as and when doflash is switched off
    led1State = LOW; 
    led2State = LOW; 
    led3State = LOW; 
    digitalWrite(led1Pin, led1State);
    digitalWrite(led2Pin, led2State);
    digitalWrite(led3Pin, led3State);
  }; 

  // flash if toggle is on
  if (doflash == HIGH) {

    // Act if the latter time (ms) has now passed on this particular counter,
    if (timeout(&count1, 300UL )) {
      toggle(&led1State);
      digitalWrite(led1Pin, led1State);
    } 

    if (timeout(&count2, 200UL )) {
      toggle(&led2State);
      digitalWrite(led2Pin, led2State);
    } 

    if (timeout(&count3, 77UL )) {
      toggle(&led3State);
      digitalWrite(led3Pin, led3State);
    }
  }
}

Thanks for the helpful responses.

I will give your suggestions a go.

For the purpose of making the code generic, is there a way "start" and "stop" an asynchronous loop outside the main loop.
e.g:

void loopedAction() {
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay(1000);
}

Would this not make it much simpler and make would also work for other actions (anything inside a function)?

Thanks

Without getting into such gobbledygook as "an asynchronous loop outside the main loop", if you can actually describe what your code needs to do, detail by detail, I can most likely give you some "boilerplate" code for a start.

Paul__B:
Without getting into such gobbledygook as "an asynchronous loop outside the main loop", if you can actually describe what your code needs to do, detail by detail, I can most likely give you some "boilerplate" code for a start.

Yes sure, sorry.

My project is to set up a simple system that monitors a few machines in a server rack. I want to have a control panel with an LCD screen to interact with the system. If the system detects that a machine is not responding or the ambient air temperature is too high etc, the system should go into an alarm state (send an email/SMS and sound an audible alarm.) There should be functionality to silence the alarm either by acknowledging it via keypad input or by the system detecting the issue has been self resolved.

What I want to knows is, is there an easy way to have the controller start and stop asynchronous code (e.g flashing LEDs, buzzer alarm tones and other timed code)?

If you need any more information, let me know.

Thanks

OK, now we are getting somewhere. You struck the dread "XY problem" whereby your repeated question as such has essentially nothing to do with your need. :grinning:

What you are referring to, is broadly called "multi-tasking" or doing many things at the same time. And in fact, on the Project Guidance index, the first sticky addresses precisely this form of programming, so at the risk of hoeing in to a very detailed matter, that is where you need to go! One hundred and three replies on this thread at this point in time, and my contribution is included (somewhere). :roll_eyes:

This was referred to in earlier replies as "blink without delay" because real world code does not utilise delay() or "while" loops (or extensive and unconstrained "for" loops) - and I gave you what I believe to be elegant code for it.

It looks - and is to some little extent - complex, but this is serious "real world" computer programming, not "flashing a LED". It is in fact, precisely what is required for your application. You need to study the code as you have apparently not done so thus far. Sooner or later you will hit the Eureka moment.