Flashing LED 3 times without delay.

I am trying to make a tow truck lightbar for my RC car.
I have found a very good guide to get multiple lights to blink seperate from eachother, but my question is how do I get it to blink 3 times and then pause?

I am following this guide

I have no trouble with adding extra lights and changing the speed of the flashing. I just need to make it pause between every 3 blink.

Look at the blink without delay example, add a counter for the number of blinks - and don’t blink when the counter reaches 3

Shameless plug, I just released Fiber lib to easily implement this kind of tasks :slight_smile:

This is heavy artillery for a very simple question...

Not really, this is stupidly simple task with fibers:

struct ffunc_blinky
{
  int i;
  FFUNC()
  {
    FFUNC_BEGIN
    for(i=0; i<3; ++i)
    {
      led_on();
      FFUNC_CALL(ffunc_sleep, (0.5f)); // half second on
      led_off();
      FFUNC_CALL(ffunc_sleep, (0.5f)); // half second off
    }
    FFUNC_CALL(ffunc_sleep, (2.0f)); // pause 2 sec after 3 blinks
    FFUNC_END
  }
};

Something like this can work too.

You can tune each LEDs on, off and pause time. If their on/off time sums and pause times are the same they’ll blink in unison. You can also give each its own times so they look more like strobes on emergency vehicles.

#define NUM_LEDS        3
const byte pinLED1 = 14;
const byte pinLED2 = 15;
const byte pinLED3 = 16;

#define LED_ON          LOW
#define LED_OFF         HIGH

#define ST_LED_ON       0
#define ST_LED_OFF      1
#define ST_LED_PAUSE    2
typedef struct
{
    const byte          pin;
    const byte          numBlinks;
    const unsigned long onTime;
    const unsigned long offTime;
    const unsigned long pauseTime;
    unsigned long       ledtimer;
    byte                blnkcount;
    byte                state;
    
}structBlinkingLED;

structBlinkingLED grBlinks[NUM_LEDS] =
{
    {
        .pin = pinLED1,
        .numBlinks = 3,
        .onTime = 75,
        .offTime = 150,
        .pauseTime = 1000,
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_ON
    },
    {
        .pin = pinLED2,
        .numBlinks = 3,
        .onTime = 50,
        .offTime = 175,
        .pauseTime = 2000,      
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_ON      
    },
    {
        .pin = pinLED3,
        .numBlinks = 3,
        .onTime = 100,
        .offTime = 125,
        .pauseTime = 1750,      
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_ON      
    }
};


void setup()
{
    for( int i=0; i<NUM_LEDS; i++ )
    {
        digitalWrite( grBlinks[i].pin, LED_ON );
        pinMode( grBlinks[i].pin, OUTPUT );
        
    }//for
    
}//setup


void loop()
{
    LEDStateMachine();
        
}//loop

void LEDStateMachine( void )
{
    unsigned long
        timeNow;
    static byte
        index = 0;
        
    if( index == 0 )
        timeNow = millis();
    switch( grBlinks[index].state )
    {
        case    ST_LED_ON:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].onTime )
            {
                digitalWrite( grBlinks[index].pin, LED_OFF );
                grBlinks[index].ledtimer = timeNow;
                grBlinks[index].state = ST_LED_OFF;
                
            }//if
            
        break;

        case    ST_LED_OFF:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].offTime )
            {
                grBlinks[index].ledtimer = timeNow;
                grBlinks[index].blnkcount++;
                if( grBlinks[index].blnkcount == grBlinks[index].numBlinks )
                    grBlinks[index].state = ST_LED_PAUSE;
                else
                {
                    digitalWrite( grBlinks[index].pin, LED_ON );
                    grBlinks[index].state = ST_LED_ON;
                                
                }//else
                
            }//if
            
        break;

        case    ST_LED_PAUSE:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].pauseTime )
            {
                grBlinks[index].ledtimer = timeNow;
                grBlinks[index].blnkcount = 0;
                digitalWrite( grBlinks[index].pin, LED_ON );
                grBlinks[index].state = ST_LED_ON;
                
            }//if
            
        break;
        
    }//switch

    index++;
    if( index == NUM_LEDS )
        index = 0;
        
}//LEDStateMachine

Owww i had just wrote one too :confused:

Well he can choose, mine is maybe smaller and more encapsulated, 100% no delays.

const byte ledPin_3 = 3;           // the number of the LED pin
const byte numberOfFlashes = 3;    // the number of flashes
bool startPulse = false;    // ensures leds dont blink while pulse is active

void setup() {
  Serial.begin(115200);
  pinMode(ledPin_3, OUTPUT);
}

void loop() {
  ledSequence(ledPin_3);
}

void ledSequence(byte ledPin) {
  const long interval = 1000; // time between flashes in ms.
  static bool ledState = false;
  static byte sequencePosition = 0;
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  if ((currentMillis - previousMillis >= interval) && !startPulse) {
    if (sequencePosition < numberOfFlashes * 2) { // blink
      Serial.print("ledState = "); Serial.println(ledState);
      digitalWrite(ledPin, ledState);
      ledState = !ledState;
      sequencePosition++;
    }
    else if (sequencePosition == numberOfFlashes * 2) { // pulse
      Serial.println("Starting pulse");
      startPulse = true;
      sequencePosition = 0;
      ledState = false;
    }
    previousMillis = currentMillis;
  }
  pulse(ledPin);
}

void pulse(byte ledPin) {
  static bool incrementUp = true;
  static byte increment = 0;
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  const long interval = 2; // 2 = 2 * 255 * 2 = 1020ms pulse time.
  if ((currentMillis - previousMillis >= interval) && startPulse) {
    if (incrementUp && increment < 255) {
      increment++;
    }
    else if (increment == 255) {
      incrementUp = false;
    }
    if (!incrementUp && increment > 0) {
      increment--;
    }
    else if (increment == 0) {
      incrementUp = true;
      startPulse = false;
    }
    Serial.print("Pulse PWM = "); Serial.println(increment);
    analogWrite(ledPin, increment);
    previousMillis = currentMillis;
  }
}

JarkkoL:
Not really, this is stupidly simple task with fibers

You forget the high learning curve for your fiber construct for newbie having a challenge blinking a led…

It's easier for a newbie to get blinking led working with the fiber lib than building a custom state machine for the purpose. We have seen in this thread already how anything but extremely trivial case gets horribly convoluted.

But does the noob understand how such code works? A SM might be long but it’s very clear. The same can’t be said of advanced C++ like:

#define FFUNC() size_t __m_ffunc_active_line; bool tick(ffunc_callstack &__ffunc_cs_, size_t __ffunc_stack_pos_, float &__ffunc_dtime_)
#define FFUNC_IMPL(ffunc__) bool ffunc__::tick(ffunc_callstack &__ffunc_cs_, size_t __ffunc_stack_pos_, float &__ffunc_dtime_)
#define FFUNC_BEGIN switch(__m_ffunc_active_line) {case 0:
#define FFUNC_END break;} return false;
#define FFUNC_CALL(ffunc__, ffunc_args__)\
  case __LINE__:\
  {\
    if(__ffunc_cs_.stack_size()==__ffunc_stack_pos_)\
    {\
      __m_ffunc_active_line=__LINE__;\
      new(__ffunc_cs_.push<ffunc__ >())ffunc__ ffunc_args__;\
    }\
    if(__ffunc_cs_.tick<ffunc__ >(__ffunc_stack_pos_, __ffunc_dtime_))\
.
.
.

Noob doesn't need to know implementation details of the library, just like they don't need to know implementation details of digitalWrite(); Most people don't feel the need to understand the internal workings of a combustion engine in order to drive a car.

JarkkoL:
Noob doesn't need to know implementation details of the library, just like they don't need to know implementation details of DigitalWrite();

IMO they should be encouraged to understand what's going on under the hood.

As a hardware engineer I saw an example just recently with software guys brought up on OSs and drivers hiding the hardware layer behind gobs of abstraction. A recent design spec asked that they read and write 8-bit registers in a CPLD and they were lost; it seems like they didn't really know what registers were and because there was no Linux driver they didn't know what to do.

To each his own. Nice lib BTW.

Thanks guys.
I have not yet tried any of your super fine sugesstions, but I defenetly will as soon as I get the time.
A small question.
The first led will start the blink sequence at startup. How can I get the second Led to stay off until the first led is finished blinking.
I am thinking some sort of upstart wait time so it is not connected to the first Led's flashing sequence

And again Thanks for all your help.
It is super interesting to fiddel with these small processors, but when I do not have any background in programming I defenetly need your help.

Cant you just do "Wait(3000)"

Blackfin:
IMO they should be encouraged to understand what's going on under the hood.

... saw an example just recently with software guys ....

Although you didn't elaborate on what a "software guy" is, that presumably means some kind of software professional. Arguably (although not necessarily, since "software guys" (and presumably "software gals" too) come in different flavours at different levels) they should know about registers. Their job may require them to know about such things, agreed. (And if they should but don't, perhaps they were wrongly selected and or wrongly trained.)

But an Arduino hobbyist is more like Jarkkol's car driver than your professional "software guy". The automotive professional equivalent of your "software guy" might be an automotive engineer who might be expected to design a camshaft profile for racing not sitting in the traffic, but who doesn't know what valve timing is.

Back in the day one went to a "camshaft guy" and bought a "warm" or "hot" camshaft, taking the guy's (or gal's) word that it would provide certain functionality under certain conditions, without having to have read Philip H. Smith's "Scientific Design of Exhaust and Intake Systems" or "The Design and Tuning of Competition Engines" like I did when I was still at high school.

A software library is like a camshaft: you slot the right one in, heeding the maker's instructions about other parts of the system needing to be chosen to suit (like decent valve springs) and off you go. If you want to learn about camshaft design, do so. But you can buy a camshaft off the shelf....

Below is fully working version. It first blinks 3x LED in pin 13 followed by 3x LED in pin 14. And keeps looping that sequence.

#include "ffunc.h"

static uint8_t s_led_pins[]={13, 14};
enum {num_leds=sizeof(s_led_pins)/sizeof(*s_led_pins)};
struct ffunc_blinky
{
  int led, i;
  FFUNC()
  {
    FFUNC_BEGIN
    for(led=0; led<num_leds; ++led)
      for(i=0; i<3; ++i)
      {
        digitalWrite(s_led_pins[led], HIGH);
        FFUNC_CALL(ffunc_sleep, (0.5f)); // half second on
        digitalWrite(s_led_pins[led], LOW);
        FFUNC_CALL(ffunc_sleep, (0.5f)); // half second off
      }
    FFUNC_END
  }
};

static ffunc_callstack s_cs;
static unsigned long s_prev_time;

void setup()
{
  for(unsigned i=0; i<num_leds; ++i)
    pinMode(s_led_pins[i], OUTPUT);
  s_prev_time=millis();
}

void loop()
{
  unsigned long cur_time=millis();
  if(!s_cs.tick((cur_time-s_prev_time)/1000.0f))
    FFUNC_START(s_cs, ffunc_blinky, ());
  s_prev_time=cur_time;
}

Nyan_cat_9808:
Cant you just do "Wait(3000)"

You mean "delay(3000)"?

Your fiber library is cool for a software engineer - nice achievement - but I still believe that noobs can grasp more easily what’s going on with a state machine and become self sufficient writing one.

ArduinoRookiedk:
Thanks guys.
I have not yet tried any of your super fine sugesstions, but I defenetly will as soon as I get the time.
A small question.
The first led will start the blink sequence at startup. How can I get the second Led to stay off until the first led is finished blinking.

Slightly modified version of my earlier code, FWIW.

#define NUM_LEDS        3
const byte pinLED1 = 14;
const byte pinLED2 = 15;
const byte pinLED3 = 16;

#define LED_ON          LOW
#define LED_OFF         HIGH

#define ST_LED_ON       0
#define ST_LED_OFF      1
#define ST_LED_PAUSE    2
typedef struct
{
    const byte          pin;
    const byte          numBlinks;
    const unsigned long onTime;
    const unsigned long offTime;
    const unsigned long pauseTime;
    unsigned long       ledtimer;
    byte                blnkcount;
    byte                state;
    
}structBlinkingLED;

structBlinkingLED grBlinks[NUM_LEDS] =
{
    {
        .pin = pinLED1,
        .numBlinks = 3,
        .onTime = 50,
        .offTime = 100,
        .pauseTime = 1000,
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_OFF
    },
    {
        .pin = pinLED2,
        .numBlinks = 3,
        .onTime = 40,
        .offTime = 80,
        .pauseTime = 1500,      
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_OFF      
    },
    {
        .pin = pinLED3,
        .numBlinks = 3,
        .onTime = 100,
        .offTime = 125,
        .pauseTime = 1750,      
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_OFF      
    }
};


void setup()
{
    for( int i=0; i<NUM_LEDS; i++ )
    {
        digitalWrite( grBlinks[i].pin, LED_OFF );
        pinMode( grBlinks[i].pin, OUTPUT );
        
    }//for
    
}//setup


void loop()
{
    LEDStateMachine();
        
}//loop

void LEDStateMachine( void )
{
    unsigned long
        timeNow;
    static byte
        index = 0;
        
    timeNow = millis();
    switch( grBlinks[index].state )
    {
        case    ST_LED_OFF:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].offTime )
            {
                grBlinks[index].ledtimer = timeNow;
                digitalWrite( grBlinks[index].pin, LED_ON );
                grBlinks[index].state = ST_LED_ON;
                
            }//if
            
        break;
        
        case    ST_LED_ON:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].onTime )
            {
                digitalWrite( grBlinks[index].pin, LED_OFF );
                grBlinks[index].ledtimer = timeNow;

                grBlinks[index].blnkcount++;
                if( grBlinks[index].blnkcount == grBlinks[index].numBlinks )
                    grBlinks[index].state = ST_LED_PAUSE;
                else
                    grBlinks[index].state = ST_LED_OFF;
                
            }//if
            
        break;

        case    ST_LED_PAUSE:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].pauseTime )
            {
                grBlinks[index].blnkcount = 0;
                index++;
                if( index == NUM_LEDS )
                    index = 0;
                grBlinks[index].ledtimer = timeNow;
                digitalWrite( grBlinks[index].pin, LED_ON );
                grBlinks[index].state = ST_LED_ON;
                
            }//if
            
        break;
        
    }//switch

        
}//LEDStateMachine

Blackfin:
Slightly modified version of my earlier code, FWIW.

#define NUM_LEDS        3

const byte pinLED1 = 14;
const byte pinLED2 = 15;
const byte pinLED3 = 16;

#define LED_ON          LOW                                              ( shouldent these 2 states be switched?)
#define LED_OFF        HIGH

#define ST_LED_ON      0
#define ST_LED_OFF      1
#define ST_LED_PAUSE    2
typedef struct
{
    const byte          pin;
    const byte          numBlinks;
    const unsigned long onTime;
    const unsigned long offTime;
    const unsigned long pauseTime;
    unsigned long      ledtimer;
    byte                blnkcount;
    byte                state;
   
}structBlinkingLED;

structBlinkingLED grBlinks[NUM_LEDS] =
{
    {
        .pin = pinLED1,
        .numBlinks = 3,
        .onTime = 50,
        .offTime = 100,
        .pauseTime = 1000,
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_OFF
    },
    {
        .pin = pinLED2,
        .numBlinks = 3,
        .onTime = 40,
        .offTime = 80,
        .pauseTime = 1500,     
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_OFF     
    },
    {
        .pin = pinLED3,
        .numBlinks = 3,
        .onTime = 100,
        .offTime = 125,
        .pauseTime = 1750,     
        .ledtimer = 0,
        .blnkcount = 0,
        .state = ST_LED_OFF     
    }
};

void setup()
{
    for( int i=0; i<NUM_LEDS; i++ )
    {
        digitalWrite( grBlinks[i].pin, LED_OFF );
        pinMode( grBlinks[i].pin, OUTPUT );
       
    }//for
   
}//setup

void loop()
{
    LEDStateMachine();
       
}//loop

void LEDStateMachine( void )
{
    unsigned long
        timeNow;
    static byte
        index = 0;
       
    timeNow = millis();
    switch( grBlinks[index].state )
    {
        case    ST_LED_OFF:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].offTime )
            {
                grBlinks[index].ledtimer = timeNow;
                digitalWrite( grBlinks[index].pin, LED_ON );
                grBlinks[index].state = ST_LED_ON;
               
            }//if
           
        break;
       
        case    ST_LED_ON:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].onTime )
            {
                digitalWrite( grBlinks[index].pin, LED_OFF );
                grBlinks[index].ledtimer = timeNow;

grBlinks[index].blnkcount++;
                if( grBlinks[index].blnkcount == grBlinks[index].numBlinks )
                    grBlinks[index].state = ST_LED_PAUSE;
                else
                    grBlinks[index].state = ST_LED_OFF;
               
            }//if
           
        break;

case    ST_LED_PAUSE:
            if( (timeNow - grBlinks[index].ledtimer) >= grBlinks[index].pauseTime )
            {
                grBlinks[index].blnkcount = 0;
                index++;
                if( index == NUM_LEDS )
                    index = 0;
                grBlinks[index].ledtimer = timeNow;
                digitalWrite( grBlinks[index].pin, LED_ON );
                grBlinks[index].state = ST_LED_ON;
               
            }//if
           
        break;
       
    }//switch

}//LEDStateMachine

Super Thanks Blackfin.
Now I can se how it works and change the timers by my self.
I forund a tiny mistake in your code.
I do not know if it was to test my or just a fast finger typing.
The State in define LED ON and LED OFF is i my world switched.
If I change them, I get the respons from the LED as I want.

Very much thanks to every body for your fast and great responses.
I will try to work with all of your codes so I can learn more about how to program this little awesome piece of electronic.