random blinking without delay and blinking with delay in 1

Hi all,
I am new here and read through the basic tutorials. I have however a project which I hoped was easy, but turns out to be more difficult that I expected and I am hoping someone can help me point into the right direction of figuring this out.

I have this project of a firetruck which has 2 random blinking lights on top. Something I found out to be usefull was the
const unsigned long led12interval = 400UL ;
const unsigned long led11interval = 450UL ;

and
void loop()

{ if ( (millis () - led12timer) >= led12interval ) {
if (led12State == LOW)
led12State = HIGH ;
else
led12State = LOW ;
digitalWrite (led12, led12State ) ;
led12timer = millis () ;
}

if ( (millis () - led11timer) >= led11interval ) {
if (led11State == LOW)
led11State = HIGH ;
else
led11State = LOW ;
digitalWrite (led11, led11State ) ;
led11timer = millis () ;
}

The other thing I am trying to do is have a blinker in the front that flashes up 3 times and than delays about 1 second.
digitalWrite(led3, HIGH);
delay(50);
digitalWrite(led3, LOW);
delay(50);
digitalWrite(led3, HIGH);
delay(50);
digitalWrite(led3, LOW);
delay(50);
digitalWrite(led3, HIGH);
delay(50);
digitalWrite(led3, LOW);
delay(1000);

I basically took these examples of what I found on the forum, but I can't get them combined. The random flashlights need to keep on going as the blinker should only flash 3 times and wait.. I somehow get the delay to impact my flashlights as well.

Can anyone help me?

Thanks
Roel

The led3 code is the problem.
delay() does not work very well if you want to do more than one thing at a time.
use blink without delay for led3.

The "BLINK" program that is usually a beginners first sketch is written linearly:

Turn on LED;
Wait 1 second;
Turn off LED;
Wait 1 second;
Loop around and do it again.

Notice that it takes 2 whole seconds for loop to go around once. and if you try to do anything else things will get messed up.

This is not a good programming technique because during the time it is waiting(delay) the arduino could be doing literally millions of other things.
It's better to take a reactionary approach like in the " Blink without delay" sketch:

Loop;
Is it time yet (no);
Do other stuff;
Loop;
Is it time yet (no);
Do other stuff;
Loop;
Is it time yet (yes);
switch the LED;
Do other stuff;

With this sketch loop will go around THOUSANDS of times per second. Lots of time to do other stuff

It is allowed to change the interval runtime for random blinking:

const int ledPin = LED_BUILTIN;

unsigned long previousMillis;
unsigned long interval = 200UL;   // not a constant, it will be changed

void setup() 
{
  pinMode( ledPin, OUTPUT);
}

void loop() 
{
  unsigned long currentMillis = millis();

  if( currentMillis - previousMillis >= interval) 
  {
    previousMillis = currentMillis;
    interval = random( 100, 500);   // set the new interval

    // toggle
    digitalWrite( ledPin, digitalRead( ledPin) == HIGH ? LOW : HIGH);
  }
}

There are many ways to blink three times and then wait some time using millis(). The most silly one is to have a counter and do certain things at specific counter values:

const int ledPin = LED_BUILTIN;

unsigned long previousMillis;
const unsigned long interval = 50;
int counter = 0;

void setup() 
{
  pinMode( ledPin, OUTPUT);
}

void loop() 
{
  unsigned long currentMillis = millis();

  if( currentMillis - previousMillis >= interval) 
  {
    previousMillis = currentMillis;

    // Select what to do with certain values of counter.
    switch( counter)
    {
      case 0:
      case 2:
      case 4:
        digitalWrite( ledPin, HIGH);
        break;
      case 1:
      case 3:
      case 5:
        digitalWrite( ledPin, LOW);
        break;
    }

    counter++;
    if( counter >= 25)
    {
      counter = 0;
    }
  }
}

Thanks for your help! I finally managed to get to a setup I like :slight_smile:

I now have:
2 leds which blink at a different pace
1 led which blinks randomly
1 led which flashes 3 times and waits for a bit and flashes 3 times again

/* Multiple independent delay - 3 different blinking patterns


  Written by several forum members. In public domain.  Oct 2011.

  
*/

// Which pins are connected to which LED
const byte led12 = 13;
const byte led11 = 12 ;
const int led3 = 4 ;
const byte led9 = 10 ;

// Time periods of blinks in milliseconds (1000 milliseconds to a second).
// Time variable and constants are always unsigned long
const unsigned long led12interval = 300UL ;
const unsigned long led11interval = 350UL ;
unsigned long previousMillis;
unsigned long previousMillisrandom;
unsigned long intervalblinkrandom = 200UL;   // not a constant, it will be changed
unsigned long currentMillis = millis();

unsigned long currentMillisblinkrandom = millis();
unsigned long currentMillisblink = millis();

// Variable holding the timer value so far. One for each "Timer"
unsigned long led12timer = 0 ;
unsigned long led11timer = 0 ;
unsigned long led3timer = 0 ;
unsigned long led9timer = 0 ;

unsigned long waitUntil = 0;


// Variable to know what the current LED state is
int led12State = LOW ;
int led11State = LOW ;
int led3State = LOW ;
int led9State = LOW ;

const unsigned long intervalblink = 50;
int counter = 0;

void setup() {
  pinMode (led12, OUTPUT) ;
  pinMode (led11, OUTPUT) ;
  pinMode (led3, OUTPUT) ;
  pinMode (led9, OUTPUT) ;
  led12timer = millis () ;
  led11timer = millis () ;
  led3timer = millis () ;
  waitUntil += intervalblinkrandom;
}

void loop()


{

  // Handling the blink of one LED.
  // First, check if it is time to change state
  if ( (millis () - led12timer) >= led12interval ) {
    // It is time to change state. Calculate next state.
    if (led12State == LOW)
      led12State = HIGH ;
    else
      led12State = LOW ;
    // Write new state
    digitalWrite (led12, led12State ) ;
    // Reset timer
    led12timer = millis () ;
  }

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - led11timer) >= led11interval ) {
    if (led11State == LOW)
      led11State = HIGH ;
    else
      led11State = LOW ;
    digitalWrite (led11, led11State ) ;
    led11timer = millis ()  ;
  }

  unsigned long currentMillisrandom = millis();
  if ( currentMillisrandom - previousMillisrandom >= intervalblinkrandom)
  {
    previousMillisrandom = currentMillisrandom;
    intervalblinkrandom = random( 25, 300);   // set the new interval

    // toggle
    digitalWrite( led9, digitalRead( led9) == HIGH ? LOW : HIGH);
  }


  unsigned long currentMillisblink = millis();
  if ( currentMillisblink - previousMillis >= intervalblink)
  {
    previousMillis = currentMillisblink;

    // Select what to do with certain values of counter.
    switch ( counter)
    {
      case 0:
      case 2:
      case 4:
        digitalWrite( led3, HIGH);
        break;
      case 1:
      case 3:
      case 5:
        digitalWrite( led3, LOW);
        break;
    }

    counter++;
    if ( counter >= 25)
    {
      counter = 0;
    }
  }
}

Thanks for your quick help!

OK, you got it working, which is good. Now improve it

unsigned long currentMillis = millis();

unsigned long currentMillisblinkrandom = millis();
unsigned long currentMillisblink = millis();

Why have 3 variables holding the current time ?
copy the value of millis() into currentMillis at the start of loop() and use it wherever you need to do calculations based on the current value of millis()

unsigned long waitUntil = 0;
  waitUntil += intervalblinkrandom;

What is this doing ?

    if (led12State == LOW)
      led12State = HIGH ;
    else
      led12State = LOW ;
    // Write new state
    digitalWrite (led12, led12State ) ;

can be replaced with

digitalWrite(led12, !digitalRead(led12));
    led12timer = millis () ;
    led11timer = millis ()  ;

Don't call millis() again, just set them to the value of currentMillis saved at the start of loop() (see above)

    switch ( counter)
    {
      case 0:
      case 2:
      case 4:
        digitalWrite( led3, HIGH);
        break;
      case 1:
      case 3:
      case 5:
        digitalWrite( led3, LOW);
        break;
    }

Looks like a clumsy way of alternating between led3 being HIGH or LOW

@RoelDriessen Well done 8)
I agree with UKHeliBob, you should improve it to make the code look better.
Don't do that for us, but for yourself. When you want to change something later, it is a lot easier with good written code.

@UKHeliBob Can you scroll back and try my example with the blinking and the switch-case ? RoelDriessen wanted three short blinks and then a longer delay. I called it "The most silly one", you called it "a clumsy way". Ha ha ha, I will stop laughing when you show a sketch that is just as short and clear, but better :smiley:

As you said

here are many ways to blink three times and then wait some time using millis().

Here is another one that gives complete control over the intervals

const long periods[] = {100, 100, 100, 100, 100, 100, 1000, 0};
byte index;
unsigned long startTime;
unsigned long currentTime;
const byte ledPin = 13;

void setup()
{
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop()
{
  currentTime = millis();
  if (currentTime - startTime >= periods[index])
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    index = ++index % 8;
    startTime = currentTime;
  }
}
1 Like

@UKHeliBob Thanks! I like it. Using a table for a sequence is the most common way to do this. I should have known that. Since there is complete control over the intervals it is indeed better.

"Better" is a very subjective term.

The first objective should be to get things working. Then is the time to make it "better" but frankly, if it works, does it matter as long as there are no bugs lurking, perhaps to catch you out in 49 and a bit days time.

Haha! Thanks!
Yeah, this code was somehow pilling up with various ways to get this working and never cleaned up old stuff.

Inwill review the code and get it cleaned and improved!

Still enjoying it to see it actually work

Hi there again! Weekend time, so picked up the arduino work again. Thanks again for your feedback and codes. I went through my code and did some cleanup and changed some namings to be inlign and also for me to understand which led is doing what.
It still works how I want it to work, so I am happy :slight_smile:

/* Multiple independent blinking LED
 This scetch was build with help of many forum members and contains 3 ways of blinking leds, for example used for Firetrucks in Netherlands, Germany etc
 Led 1+2 are representing normal beacon who have an different interval so prevent a standard left right.
 Led 3+4 are representing blinkers that simultaneously flash 3 times short and wait, this can be used for blinkers in the grill
 Led 4+5 are representing blinkers that flash at a random speed and interval
*/

// Which pins are connected to which LED
const byte led1zw = 2;
const byte led2zw = 3 ;
const byte led3k = 4 ;
const byte led4k = 5;
const byte led5kr = 6 ;
const byte led6kr = 7;

// Time periods of blinks in milliseconds (1000 milliseconds to a second).
// Time variable and constants are always unsigned long
const unsigned long led1zwinterval = 300UL ;
const unsigned long led2zwinterval = 275UL ;
unsigned long previousMillis;
unsigned long previousMillisrandom;
unsigned long previousMillisrandom1;
unsigned long intervalblinkrandom = 200UL;   // not a constant, it will be changed
unsigned long intervalblinkrandom1 = 200UL;   // not a constant, it will be changed
unsigned long currentMillis = millis();
const long periods[] = {50, 50, 50, 50, 50, 50, 1000, 0};
byte index;

// Variable holding the timer value so far. One for each "Timer"
unsigned long led1zwtimer = 0 ;
unsigned long led2zwtimer = 0 ;
unsigned long led3ktimer = 0 ;
unsigned long led4_5ktimer = 0 ;
unsigned long led6krtimer = 0 ;

// Variable to know what the current LED state is
int led1zwState = LOW ;
int led2zwState = LOW ;
int led3kState = LOW ;
int led4kState = LOW ;
int led5krState = LOW ;
int led6krState = LOW ;

void setup() {
 pinMode (led1zw, OUTPUT) ;
 pinMode (led2zw, OUTPUT) ;
 pinMode (led3k, OUTPUT) ;
 pinMode (led4k, OUTPUT) ;
 pinMode (led5kr, OUTPUT) ;
 pinMode (led6kr, OUTPUT) ;
 led1zwtimer = millis () ;
 led2zwtimer = millis () ;
 led3ktimer = millis () ;
 led4_5ktimer = millis () ;
 led6krtimer = millis () ;
}

void loop()
{
 unsigned long currentMillis = millis();
 if ( (millis () - led1zwtimer) >= led1zwinterval ) {
   digitalWrite(led1zw, !digitalRead(led1zw));
   led1zwtimer = millis () ;
 }
 if ( (millis () - led2zwtimer) >= led2zwinterval ) {
   digitalWrite(led2zw, !digitalRead(led2zw));
   led2zwtimer = millis ()  ;
 }
 if (millis() - led4_5ktimer >= periods[index])
 {
   digitalWrite(led3k, !digitalRead(led3k));
   digitalWrite(led4k, !digitalRead(led4k));
   index = ++index % 8;
   led4_5ktimer = millis();
 }
 if ( currentMillis - previousMillisrandom >= intervalblinkrandom)
 {
   previousMillisrandom = currentMillis;
   intervalblinkrandom = random( 25, 300);
   digitalWrite( led5kr, digitalRead( led5kr) == HIGH ? LOW : HIGH);
 }
 if ( currentMillis - previousMillisrandom1 >= intervalblinkrandom1)
 {
   previousMillisrandom1 = currentMillis;
   intervalblinkrandom1 = random( 50, 275);
   digitalWrite( led6kr, digitalRead( led6kr) == HIGH ? LOW : HIGH);
 }
}

It's nice when something works.
Now, can it be improved and/or tidied up even more ?

Having copied the value of millis() into the currentMillis variable at the start of loop() why not use it throughout the program when you need the value of millis() rather than reading it again ?

  led1zwtimer = millis () ;
  led2zwtimer = millis () ;
  led3ktimer = millis () ;
  led4_5ktimer = millis () ;
  led6krtimer = millis () ;

Numbered variables almost always means that arrays could be used to shorten code.

   digitalWrite( led6kr, digitalRead( led6kr) == HIGH ? LOW : HIGH);
digitalWrite(led6kr, !digitalRead(led6kr));

would be easier to read and understand

@RoelDriessen, here UKHeliBob and me have different opinions.

With the Arduino, false = 0, LOW = 0, INPUT = 0 and true = 1, HIGH = 1 and OUTPUT = 1.

I like to keep them seperated.
The boolean "not" operator is the "!", but I use that for 'bool' variables only.
A "not" with a "HIGH" or "LOW" has no meaning for me.

You can decide for yourself what suits you best.

A "not" with a "HIGH" or "LOW" has no meaning for me.

To me it is blindingly obvious that "not HIGH" is LOW and "not LOW" is HIGH, but each to his own.

What I don't like seeing is expressions such as

if (digitalRead(aPin) == 0)

A digital pin is either HIGH or LOW, never 0

if (digitalRead(aPin) == false)

would be even worse, but I can't remember seeing it used, thank goodness.

In order to flip a pin's state, use "digitalWrite(pin, digitalRead(pin) ^ 1)". Using "!" (not operator) is confusing since it is no boolean.

Using "!" (not operator) is confusing since it is no boolean.

Is the use of the ! operator limited to booleans ? Answer, no.

As I said previously

To me it is blindingly obvious that "not HIGH" is LOW and "not LOW" is HIGH

How is that confusing ?

UKHeliBob:
Is the use of the ! operator limited to booleans ? Answer, no.

Never said that. The "exclusive or" operator (XOR / ^) is the best and fastest sollution, so that will remain as my recommendation.

The "exclusive or" operator (XOR / ^) is the best and fastest sollution,

"Best" ? Give me strength. How obscure do you want to make the code ?

The most readable and understandable solution is

byte pinState = digitalRead(pinNum);
if (pinState == HIGH)
{
  pinState = LOW;
}
else
{
  pinState = HIGH;
}
digitalWrite(pinNum, pinState);

Of course, this verbose code will be dismissed by experienced programmers who delight in tricks to avoid typing. We should not forget that the compiler will optimise the code so we could end up with the same compiled code for several different source code solutions. The source code is meant to be read and understood by humans whilst the compiled code is meant to be read and understand by the computer.

Fastest solution ?
Use port manipulation for an extra level of obscurity or, of course, write the whole thing in assembler for extra points

I am pretty shure, that your last example will result in something like:

mov reg, val
cmp reg, 1
je @addr1
portx 1
ret
@addr1:
portx 0
ret

Whereas a exclusive or will produce something like:

mov reg, val
xor reg, 1
portx reg
ret

So, that why the xor is not just lazy trickery :slight_smile:

Port manipulation would of course be even faster. But I will not recommend this unless the code is targeted at one, specific chip :slight_smile:

EDIT: Pseudo-assembly alert! Added "ret" for completion :slight_smile:

that why the xor is not just lazy trickery

The first requirement of any program is that it works and does what is required of it, preferably in a way that can be understood, maintained and fixed at some future date. If the requirement requires that the program operates in a given timeframe then by all means do what is necessary to achieve it.

You know what XOR does but others might not. A comment in the code as to what is being done would be appropriate I suggest. I try to make my code readable by one means or another.

Of course, all of this is dependant on the skill and experience of anyone reading the code. Here we tend to be dealing with questions from newcomers to the Arduino who are often new to coding of any kind, so any help that can be given is appreciated. What is blindingly obvious to you may look like a foreign language to someone else.