Go Down

Topic: Newbie- Blink Multiple LED's at random speeds w/ millis() (Read 3568 times) previous topic - next topic



I am about a week in to learning to work with the Arduino platform and programming in general.   I am trying to accomplish what I think may be a fairly straight forward task. I have searched this forum and others, and not yet solved my problem.

I would like to eventually blink 3 LEDs at random speeds, independent from each other.   I can accomplish blinking 1 LED at random using randomSeed() and delay() with no problem.   I am trying to wrap my head around multitasking using millis() and am doing ok, but I'm trying to figure out how to combine millis() with a random function and am not having any luck. 

Perhaps for this example, let's just say I wanted to blink 1 led at random without using delay().   I grabbed this from the Arduino reference and modified to the best of my ability.   The code below blinks the LED always at about a 1 second interval.  Hoping someone can offer some guidance.


Code: [Select]

// Blink 1 LED at a random interval (1 second to 5 seconds) without using delay()
//Curcuit:  LED connected to pin 10 with 330 ohm resistor to ground.

int ledPin =  10; 
int ledState = LOW;         
long previousMillis = 0;
long randInterval = 0;

void setup() {

  pinMode(ledPin, OUTPUT);   
  randomSeed (analogRead (0));

void loop()
  randInterval = random (1000, 5000);

  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > randInterval) {

    previousMillis = currentMillis;   

    if (ledState == LOW)
      ledState = HIGH;
      ledState = LOW;

    digitalWrite(ledPin, ledState);


Say 1100 milliseconds have passed, and loop() runs 10 times per millisecond. After a few iterations of loop(), randInterval is going to be less than 1100, and the led will blink and the time will be reset so another 1 second needs to pass.

The solution is to only update randInterval inside of the if statement.


Thanks very much for the fast help.  That solved my problem.  In all honestly, I'm having some difficulty in really following along with millis() (and C in general) and I think it's partly due to an overall lack of experience and i'm also finding that my brain may just not be wired for this kind of stuff.  Working on it though.

I was able to extrapolate your answer out to randomly blink 5 LEDs. However, I'm not sure if the code I came up with is overkill (i.e. defining all the new variables for each LED if statement).  Posting just to to see if anyone has input.

Thanks again.  Great community here.

Code: [Select]
// Blink 1 LED at a random interval (1 second to 5 seconds) without using delay()
//Curcuit:  LEDs connected to pin 10, 12, 13, 1  & 2, all with 330 ohm resistors to ground.

int led1Pin =  10; 
int led2Pin = 12;
int led3Pin = 13;
int led4Pin = 1;
int led5Pin = 2;
int led1State = LOW;
int led2State = LOW;
int led3State = LOW;
int led4State = LOW;
int led5State = LOW;
long previousMillis1 = 0;
long previousMillis2 = 0;
long previousMillis3 = 0;
long previousMillis4 = 0;
long previousMillis5 = 0;
long randInterval1 = 0;
long randInterval2 = 0;
long randInterval3 = 0;
long randInterval4 = 0;
long randInterval5 = 0;

void setup() {

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  pinMode(led5Pin, OUTPUT);
  randomSeed (analogRead (0));

void loop()

  unsigned long currentMillis = millis();

  //LED 1/////////////////////////
  if(currentMillis - previousMillis1 > randInterval1) {
    randInterval1 = random (1000, 5000);
    previousMillis1 = currentMillis;   

    if (led1State == LOW)
      led1State = HIGH;
      led1State = LOW;

    digitalWrite(led1Pin, led1State);
  //LED 2/////////////////////////
    if(currentMillis - previousMillis2 > randInterval2) {
    randInterval2 = random (1000, 5000);
    previousMillis2 = currentMillis;   

    if (led2State == LOW)
      led2State = HIGH;
      led2State = LOW;

    digitalWrite(led2Pin, led2State);
  //LED 3/////////////////////////
      if(currentMillis - previousMillis3 > randInterval3) {
    randInterval3 = random (1000, 5000);
    previousMillis3 = currentMillis;   

    if (led3State == LOW)
      led3State = HIGH;
      led3State = LOW;

    digitalWrite(led3Pin, led3State);

  //LED 4/////////////////////////
        if(currentMillis - previousMillis4 > randInterval4) {
    randInterval4 = random (1000, 5000);
    previousMillis4 = currentMillis;   

    if (led4State == LOW)
      led4State = HIGH;
      led4State = LOW;

    digitalWrite(led4Pin, led4State);
  //LED 5/////////////////////////
         if(currentMillis - previousMillis5 > randInterval5) {
    randInterval5 = random (1000, 5000);
    previousMillis5 = currentMillis;   

    if (led5State == LOW)
      led5State = HIGH;
      led5State = LOW;

    digitalWrite(led5Pin, led5State);


Arrays are the next thing for you to learn about. Repeating the same code over and over is silly, when a for loop will do the same thing in a lot less space.
The art of getting good answers lies in asking good questions.



struct ledData {
   int pin;
   int state;
   unsigned long previousMillis;
   long randInterval;

ledData leds[5];

   if ( now - theLed.previousMillis > theLed.randInterval){
      theLed.randInterval = random(1000,5000);
      theLed.previousMillis = now;
      theLed.state = ! theLed.state;   // toggle
      digitalWrite(theLed.pin, theLed.state);

This is "object oriented", in C

Have fun!

Go Up