How can I make LED's blink at random?

Hi Everyone,

I am new to arduino and to programming in general. I want to connect a series of Leds (8) to my arduino board and make them all blink at random. Here is my very first piece of code XD. I was wondering wether I was going the right way (sorry it's probably very basic).

void setup() {
pinMode(1, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);

pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);

}

void loop() {
digitalWrite(1, HIGH);
delay(3000);
digitalWrite(1, LOW);
delay(3000);
digitalWrite(2, HIGH);
delay(4000);
digitalWrite(2, LOW);
delay(4000);
digitalWrite(3, HIGH);
delay(3500);
digitalWrite(3, LOW);
delay(3500);
digitalWrite(4, HIGH);
delay(1200);
digitalWrite(4, LOW);
delay(1200);

digitalWrite(5, HIGH);
delay(2000);
digitalWrite(5, LOW);
delay(2000);
digitalWrite(6, HIGH);
delay(2000);
digitalWrite(6, LOW);
delay(2000);
digitalWrite(7, HIGH);
delay(1000);
digitalWrite(7, LOW);
delay(1000);
digitalWrite(8, HIGH);
delay(3000);
digitalWrite(8, LOW);
delay(3000);
}

... and make them all blink at random

Do they truly have to blink at random or do they just have to appear to blink at random such as 'twinkling' holiday decorations.

Also - I don't think you want to use delay(). Look for 'Blink without delay' whose more correct name should really be 'Blink without delay()'.

Don

So you have 8 LEDs.

Use Blink without delay and an array with random() for the on/off times.
We'll use 3 arrays.
1 will have 8 values for the on/off time amounts
1 will have the 8 I/O pins being used
1 will have the state of the I/O pin

int ledArrayTime[8]; // 8 element array of 16 bit numbers, load it up in setup
byte ledArray[8];  // array for the I/O pins
byte ledArray[] = {2,3,4,5,6,7,8,9};   // use 2-9 vs 1-8, keep 0/1 free for downloading sketches
// thus  ledArray[0] = I/O pin 2, up to ledArray[7] = pin 9
byte ledState[8]; // array to hold the state of the I/O pins
ledState[] = {0,1,0,1,0,1,0,1};  // load the the states with 0,1 to start (or all 0,s, or all 1's)
byte x;  // will use this as the array index pointer

void setup (){
// declare the outputs using the array
for (x=0; x<8; x=x+1){ // walk x from 0 to 7
pinMode (ledArray[x], OUTPUT);
digitalWrite (ledArray[x], ledArrayState[x]); // write the outputs hi/lo
}
// and load up the array with variable times
 for (x= 0; x<8; x=x+1;){  loop from 0 to 7 to load the array
 // find a random number from 1200 to 4000
 randNumber = random(1200, 4000);  //[edit - original post had 400 here, a typo]
// load the array 
ledArrayTime[x] = randNumber;
}
} // end setup

void loop(){

//now turn the lights on/off based the times in the array
// here's the blink without delay part
unsigned long startTime = millis(); // capture the current time
for (x=0; x<8; x=x+1;){
if ( (millis() - startTime) > ledArrayTime[x] ){
ledState[x] = 1-ledState[x];  // this should toggle the bit.
// if the value at ledState[5] for example was 1, then the new value will be 1-1 = 0,  and if 0, then 1-0 = 1
digitalWrite (ledArray[x], ledState[x]);  // turn the led on or off
} // end if time passed
} // end 0-7 loop
} // end void loop

Now, if all that works, can add additional code to change the delay times every once in a while

Thx for the help!!!!

You didn't answer my question. You may be making this a lot more complicated than it has to be.

Don

Yes, may be over complicated, but I enjoyed writing it up as a mental exercise in using arrays to control the state of 8 outputs.

Now that I tried compiling it, I found a few name mismatches, some extra ;s in the for (x ...) statements,
undeclared randNumber variable, and a couple of missing //s.
Not too bad!

int ledArrayTime[8]; // 8 element array of 16 bit numbers, load it up in setup
byte ledArray[8] = {2,3,4,5,6,7,8,9};   // use 2-9 vs 1-8, keep 0/1 free for downloading sketches
// thus  ledArray[0] = I/O pin 2, up to ledArray[7] = pin 9
byte ledArrayState[8] = {0,1,0,1,0,1,0,1};  // load the the states with 0,1 to start (or all 0,s, or all 1's)
byte x;  // will use this as the array index pointer
int randNumber;

void setup (){
  // declare the outputs using the array
  for (x=0; x<8; x=x+1){ // walk x from 0 to 7
    pinMode (ledArray[x], OUTPUT);
    digitalWrite (ledArray[x], ledArrayState[x]); // write the outputs hi/lo
  }
  // and load up the array with variable times
  for (x= 0; x<8; x=x+1){  //loop from 0 to 7 to load the array
      // find a random number from 1200 to 4000
    randNumber = random(1200, 4000);  //[edit - original post had 400 here, a typo]
    // load the array 
    ledArrayTime[x] = randNumber;
  }
} // end setup

void loop(){

  //now turn the lights on/off based the times in the array
  // here's the blink without delay part
  unsigned long startTime = millis(); // capture the current time
  for (x=0; x<8; x=x+1){
    if ( (millis() - startTime) > ledArrayTime[x] ){
      ledArrayState[x] = 1-ledArrayState[x];  // this should toggle the bit.
      // if the value at ledState[5] for example was 1, then the new value will be 1-1 = 0,  and if 0, then 1-0 = 1
      digitalWrite (ledArray[x], ledArrayState[x]);  // turn the led on or off
    } // end if time passed
  } // end 0-7 loop
} // end void loop

Morgan1, let me know how it works out please.

I just finished a tutorial page that might help you sort out using arrays to address pins.
http://www.thebox.myzen.co.uk/Tutorial/Arrays.html

@ CrossRoads

It workes beatyfull, allthoug i had to make a small change in the delay routine.

Furthermore I changed the random number range, but that is because I tried the Sketch, on my new attiny2313 at 1Mhz

int ledArrayTime[8]; // 8 element array of 16 bit numbers, load it up in setup
byte ledArray[8] = {9,11,12,13,4,5,6,7};   // use 2-9 vs 1-8, keep 0/1 free for downloading sketches
// thus  ledArray[0] = I/O pin 2, up to ledArray[7] = pin 9
byte ledArrayState[8] = {0,1,0,1,0,1,0,1};  // load the the states with 0,1 to start (or all 0,s, or all 1's)
byte x;  // will use this as the array index pointer
int randNumber;


void setup (){
  // declare the outputs using the array
  for (x=0; x<8; x=x+1){ // walk x from 0 to 7
    pinMode (ledArray[x], OUTPUT);
    digitalWrite (ledArray[x], ledArrayState[x]); // write the outputs hi/lo
  }
  // and load up the array with variable times
  for (x= 0; x<8; x=x+1){  //loop from 0 to 7 to load the array
      // find a random number from 1200 to 4000
    randNumber = random(120, 400);  //[edit - original post had 400 here, a typo]
    // load the array 
   ledArrayTime[x] = randNumber;
}
} // end setup

void loop(){

  for (x=0; x<8; x=x+1){
 
   //delay
    unsigned long startTime = millis(); // capture the current time
    while ( (millis()- startTime) < ledArrayTime[x] ){
     } // end while time passed

     ledArrayState[x] = 1-ledArrayState[x];  // this should toggle the bit.
      // if the value at ledState[5] for example was 1, then the new value will be 1-1 = 0,  and if 0, then 1-0 = 1
      digitalWrite (ledArray[x], ledArrayState[x]);  // turn the led on or off

  
  } // end 0-7 loop
} // end void loop
1 Like

This is a great sketch,

How easy would it be for these LEDs to fade on and off instead of blink?

thanks.

Phil

Well, you would need to change things a bit to use the 6 PWM pins on a '328 Arduino, or fake PWM in software.
I'd have to think about that tonight.
For example, if you hit the start time, start a for:next loop that went from 0-255 & analogWrite pin to fade up, and then 255-0 to fade down at the end time.

[code]void setup() { 
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
 
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

}

void loop() {
  digitalWrite(1, HIGH);
  delay(3000);
  digitalWrite(1, LOW);
  delay(3000);
  digitalWrite(2, HIGH);
  delay(4000);
  digitalWrite(2, LOW);
  delay(4000);
  digitalWrite(3, HIGH);
  delay(3500);
  digitalWrite(3, LOW);
  delay(3500);
  digitalWrite(4, HIGH);
  delay(1200);
  digitalWrite(4, LOW);
  delay(1200);

  digitalWrite(5, HIGH);
  delay(2000);
  digitalWrite(5, LOW);
  delay(2000);
  digitalWrite(6, HIGH);
  delay(2000);
  digitalWrite(6, LOW);
  delay(2000);
  digitalWrite(7, HIGH);
  delay(1000);
  digitalWrite(7, LOW);
  delay(1000);
  digitalWrite(8, HIGH);
  delay(3000);
  digitalWrite(8, LOW);
  delay(3000);   
}

Here is some code to make this easier;

void setup() {

  Serial.begin(9600);

      for (int thisPin = 2; thisPin < 7; thisPin++) {
        pinMode(thisPin, OUTPUT);
      }
}

void loop() {

  if (Serial.available() > 0) {
    int inByte = Serial.read();
   
    switch (inByte) {
    case 'q':    
      digitalWrite(2, HIGH);
      delay(1000); 
      break;
    case 'w':    
      digitalWrite(3, HIGH);
       delay(1000);
      break;
    case 'e':    
      digitalWrite(4, HIGH);
       delay(1000);
      break;
    case 'r':    
      digitalWrite(5, HIGH);
       delay(1000);
      break;
    case 't':    
      digitalWrite(6, HIGH);
       delay(1000);
      break;
      case 'a':    
      digitalWrite(2, HIGH);
      delay(500); 
      break;
    case 's':    
      digitalWrite(3, HIGH);
       delay(500);
      break;
    case 'd':    
      digitalWrite(4, HIGH);
       delay(500);
      break;
    case 'f':    
      digitalWrite(5, HIGH);
       delay(500);
      break;
    case 'g':    
      digitalWrite(6, HIGH);
       delay(500);
      break;
       case 'z':    
      digitalWrite(2, HIGH);
      delay(250); 
      break;
    case 'x':    
      digitalWrite(3, HIGH);
       delay(250);
      break;
    case 'c':    
      digitalWrite(4, HIGH);
       delay(250);
      break;
    case 'v':    
      digitalWrite(5, HIGH);
       delay(250);
      break;
    case 'b':    
      digitalWrite(6, HIGH);
       delay(250);
      break;
    default:

      for (int thisPin = 2; thisPin < 7; thisPin++) {
        digitalWrite(thisPin, LOW);
      }
    }
  }
}

I just randomly type letters and it creates random blinking LED's.
The disadvantage is that it only works once before it has to be re-uploaded.
Hope this helps. [/code]

Try this. I found a video of a Lilypad doing PWM on all its pins one time and asked the author how he did it and this is what I got. it does work, and will work on a regular Uno as well, basically any 328P IC. Just specify your first and last pins to fade:

// Fade all IO by Osamu Iwasaki
// November 10, 2010

#include <MsTimer2.h>

#define OUT_MIN 0  // First pin
#define OUT_MAX 19  // Last pin (this includes the analog pins)

byte luminance[20];
byte lumi[20] = {};

void setup()
{
 int i;

 for(i = OUT_MIN; i <= OUT_MAX; i++){
   pinMode(i, OUTPUT);
   digitalWrite(i,LOW);
 }


 for(i = OUT_MIN; i <= OUT_MAX; i++){
   digitalWrite(i,HIGH);
   delay(150);
 }
 for(i = OUT_MIN; i <= OUT_MAX; i++){
   digitalWrite(i,LOW);
   //delay(50);
 }
 delay(1000);

 MsTimer2::set(1, int_pwm);
 MsTimer2::start();
}


void int_pwm() {

 static int f_wait[20];
 static int f_max_time[20];
 static int f_speed[20];
 static int f_ct[20];
 static long f_interval[20];

 static int ch;

 for(ch = OUT_MIN; ch <= OUT_MAX; ch++){
   if(f_wait[ch] == 0){
     f_wait[ch] = f_speed[ch] + 1;

     if( (f_ct[ch] < 255) )
       if(luminance[ch] != 255)
         luminance[ch] ++;

     if(f_ct[ch] == 255){
       if(f_max_time[ch] == 0)
         f_max_time[ch] = 0; // On Max Time
       else
         f_max_time[ch] --;
     }

     if( (f_ct[ch] > 255) && (f_ct[ch] < 511) && (f_max_time[ch] == 0))
       if(luminance[ch] != 0)
         luminance[ch] --;

     if(f_ct[ch] >= 511){
       if(f_interval[ch] == 0){
         f_interval[ch] = 10 * random(100); // fading seed
         f_speed[ch] = random(1); // fading speed
         f_ct[ch] = 0;
       }
       else
         f_interval[ch] --;
     }
     else
       f_ct[ch] ++;
   }
   f_wait[ch] --;
 }
}

void fading(){

 static byte counter = 0;
 static boolean prev_off[20];
 int i;

 for(i = OUT_MIN; i <= OUT_MAX; i++){
   if(lumi[i] == 0){
     if(prev_off[i] == HIGH){
       digitalWrite(i,LOW);
       prev_off[i] = LOW;
     }
   }
   else
     lumi[i] --;
 }

 counter --;

 if(counter == 0){
   for(i = OUT_MIN; i <= OUT_MAX; i++){
     if(luminance[i]){
       digitalWrite(i,HIGH);
       prev_off[i] = HIGH;
     }
     lumi[i] = luminance[i];
   }
 }
}


void loop(){
 fading();
}

By the way, I never bothered trying this on the Tiny family of AVRs, so you're on your own there. :slight_smile:

MSTimer2.h is from where?

Playground? Arduino Playground - MsTimer2