Add LED Flash Count using Millis

Hi There - i have a Ardunio UNO board using Adafruit Library and have been creating a set of flashing lights to replicate the Navigation lights for our local Harbour. i have managed to progress from simple delay - with obvious issues to using Millis and now for the first 3 lights i would like to add a group flash then a long delay (each light varies e.g KaiparaEnteranceLight flashes Green 3 times and then is off for a period of 8 seconds, the Kaipara2ndMark flashes Green 4 times and then is off for a period of 4 seconds and i would like to just concentrate on the KaiparaEnterance Light
First Question = Is there a way to "count" how many times a pixel has turned on or off
Second Question = Am i going about this the right way or is there a better way
Thirdly - It's been a great learning experience to get to this point - i have learned a lot but now my brain is fried but I'm a long way down the rabbit hole

Code Below, I have commented out the additional lights but read the rules about posting complete code

// Issue with Pixel7 and TeKawau Marker - leftout at this point, also need to do groups flash for Marker 1,2,3
#include <Adafruit_NeoPixel.h>

//define NeoPixel Pin and Number of LEDs
#define PIN 7
#define NUM_LEDS 10

// On and Off Times (as int, max=32secs)
const unsigned int Pixel0onTime = 500;
const unsigned int Pixel0offTime = 2000;
const unsigned int Pixel1onTime = 1000;
const unsigned int Pixel1offTime = 500;
const unsigned int Pixel3onTime = 500;
const unsigned int Pixel3offTime = 2000;
const unsigned int Pixel5onTime = 1000;
const unsigned int Pixel5offTime = 10000;
const unsigned int Pixel6onTime = 1000;
const unsigned int Pixel6offTime = 10000;
const unsigned int Pixel7onTime = 5000;
const unsigned int Pixel7offTime = 5000;
const unsigned int Pixel8onTime = 1000;
const unsigned int Pixel8offTime = 7500;
const unsigned int Pixel9onTime = 1000;
const unsigned int Pixel9offTime = 5000;

// each "event" (Pixel) gets their own tracking variable - maybe change Pixel# to Kaipara# or #KH1
unsigned long previousMillisPixel0 = 0;
unsigned long previousMillisPixel1 = 0;
unsigned long previousMillisPixel2 = 0;
unsigned long previousMillisPixel3 = 0;
unsigned long previousMillisPixel4 = 0;
unsigned long previousMillisPixel5 = 0;
unsigned long previousMillisPixel6 = 0;
unsigned long previousMillisPixel7 = 0;
unsigned long previousMillisPixel8 = 0;
unsigned long previousMillisPixel9 = 0;

// different intervals for each LED
int intervalPixel0 = Pixel0onTime;
int intervalPixel1 = Pixel1onTime;
int intervalPixel2 = Pixel0onTime;
int intervalPixel3 = Pixel0onTime;
int intervalPixel4 = Pixel0onTime;
int intervalPixel5 = Pixel0onTime;
int intervalPixel6 = Pixel0onTime;
int intervalPixel7 = Pixel0onTime;
int intervalPixel8 = Pixel0onTime;
int intervalPixel9 = Pixel0onTime;

// Interval is how long we wait
int intervalP0ot = Pixel0onTime;
int intervalP0off = Pixel0offTime;

// Used to track if LED should be on or off
boolean Pixel0state = false;
boolean Pixel1state = false;
boolean Pixel2state = false;
boolean Pixel3state = false;
boolean Pixel4state = false;
boolean Pixel5state = false;
boolean Pixel6state = false;
boolean Pixel7state = false;
boolean Pixel8state = false;
boolean Pixel9state = false;

//Define Colour "Constant?"
uint32_t RedColor;// current Color in case we need it
uint32_t GreenColor;// current Color in case we need it
uint32_t WhiteColor;// current Color in case we need it
uint32_t BlackColor;// current Color in case we need it

//create a NeoPixel strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_RGB + NEO_KHZ400);

void setup() { // start the strip
  //Set the Colours defined earlier
  RedColor = strip.Color(255, 0, 0); //sets colour to Red
  GreenColor = strip.Color(0, 255, 0); //sets colour to Green
  WhiteColor = strip.Color(255, 255, 255); //sets colour to White
  BlackColor = strip.Color(0, 0, 0); //sets colour to off
  strip.begin();
  strip.show();
}

void loop() {
  // Grab snapshot of current time, this keeps all timing consistent real time
  unsigned long currentMillis = millis();

  //update each light
  kaiparaEnteranceLight();
  kaipara2ndMark();
  //kaiparaHaranui();
  //kaipara3rdMark();
  //kaiparaShellybeach();
  //kaiparaConcreteMarkRed();
  //kaiparaConcreteMarkWhite();
  //kaiparaTekawauMark();
  //kaiparaSouthHead();
  //kaiparaPoutuPoint();
}

/*  4137 KAIPARA ENTRANCE LIGHT - CURRENTLY FLASHING GREEN - Q(3)G 8s 3 2 White wooden pile beacon
  Set Pixel0 to state of pixel0state each timethrough loop()
  If pixel0State hasn't changed, neither will the pin */
void kaiparaEnteranceLight() {
  unsigned long currentMillis = millis();
  digitalWrite(0, Pixel0state);
  // Grab snapshot of current time, this keeps all timing consistent real time

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel0) >= intervalPixel0) {
    // Change wait interval, based on current LED state
    if (Pixel0state) {
      // LED is currently on, set time to stay off
      intervalPixel0 = Pixel0offTime;
      strip.setPixelColor(0, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel0 = Pixel0onTime;
      strip.setPixelColor(0, GreenColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!? Fuck year
    Pixel0state = !(Pixel0state);

    // Save the current time to compare "later"
    previousMillisPixel0 = currentMillis;
  }
}
/* 4137 KAIPARA 2nd MARK (Triangle) Fl G 4s 4 2 Grey metal pile beacon
  Set Pixel1 to state of pixel0state each timethrough loop()*/
void kaipara2ndMark() {
  unsigned long currentMillis = millis();
  digitalWrite(1, Pixel1state);
  // Grab snapshot of current time, this keeps all timing consistent real time
  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel1) >= intervalPixel1) {
    // Change wait interval, based on current LED state
    if (Pixel1state) {
      // LED is currently on, set time to stay off
      intervalPixel1 = Pixel1offTime;
      strip.setPixelColor(1, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel1 = Pixel1onTime;
      strip.setPixelColor(1, GreenColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!?
    Pixel1state = !(Pixel1state);

    // Save the current time to compare "later"
    previousMillisPixel1 = currentMillis;
  }
}
//4XXX KAIPARA Haranui Light (on land) White Solid
void kaiparaHaranui() {
  strip.setPixelColor(2, WhiteColor);
  strip.show();
}

//4135 KAIPARA 3rd MARK Fl G 6s 2 2 Green
// Set Pixel3 to state of pixel3state each timethrough loop()
void kaipara3rdMark() {
  unsigned long currentMillis = millis();
  digitalWrite(3, Pixel3state);

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel3) >= intervalPixel3) {
    // Change wait interval, based on current LED state
    if (Pixel3state) {
      // LED is currently on, set time to stay off
      intervalPixel3 = Pixel3offTime;
      strip.setPixelColor(3, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel3 = Pixel3onTime;
      strip.setPixelColor(3, GreenColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!?
    Pixel3state = !(Pixel3state);

    // Save the current time to compare "later"
    previousMillisPixel3 = currentMillis;
  }
}
//4XXX KAIPARA SHELLY BEACH Light (on land) White Solid
void kaiparaShellybeach() {
  strip.setPixelColor(4, WhiteColor);
  strip.show();
}

//4134 KAIPARA CONCRETE MARKER (RED) Fl WR 10s 6 W4 R2 2fl 0.5, ec 9.5 (Pixel#5)
// Set Pixel5 to state of pixel5state each timethrough loop()
void kaiparaConcreteMarkRed() {
  unsigned long currentMillis = millis();
  digitalWrite(5, Pixel5state);

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel5) >= intervalPixel5) {
    // Change wait interval, based on current LED state
    if (Pixel5state) {
      // LED is currently on, set time to stay off
      intervalPixel5 = Pixel5offTime;
      strip.setPixelColor(5, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel5 = Pixel5onTime;
      strip.setPixelColor(5, RedColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!?
    Pixel5state = !(Pixel5state);

    // Save the current time to compare "later"
    previousMillisPixel5 = currentMillis;
  }
}
//4134 KAIPARA CONCRETE MARKER (WHITE) Fl WR 10s 6 W4 R2 2fl 0.5, ec 9.5 (Pixel#6)
// Set Pixel6 to state of pixel5state each timethrough loop()
void kaiparaConcreteMarkWhite() {
  unsigned long currentMillis = millis();
  digitalWrite(6, Pixel6state);

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel6) >= intervalPixel6) {
    // Change wait interval, based on current LED state
    if (Pixel6state) {
      // LED is currently on, set time to stay off
      intervalPixel6 = Pixel6offTime;
      strip.setPixelColor(6, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel6 = Pixel6onTime;
      strip.setPixelColor(6, WhiteColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!?
    Pixel6state = !(Pixel6state);

    // Save the current time to compare "later"
    previousMillisPixel6 = currentMillis;
  }
}

//413 KAIPARA TeKawau Mark
// Set Pixel7 to state of pixel7state each timethrough loop()
void kaiparaTekawauMark() {
  unsigned long currentMillis = millis();
  digitalWrite(7, Pixel7state);

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel7) >= intervalPixel7) {
    // Change wait interval, based on current LED state
    if (Pixel7state) {
      // LED is currently on, set time to stay off
      intervalPixel7 = Pixel7offTime;
      strip.setPixelColor(7, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel7 = Pixel7onTime;
      strip.setPixelColor(7, WhiteColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!?
    Pixel7state = !(Pixel7state);

    // Save the current time to compare "later"
    previousMillisPixel7 = currentMillis;
  }
}
//4137 KAIPARA SOUTH HEAD WHITE
// Set Pixel8 to state of pixel8state each timethrough loop()
void kaiparaSouthHead() {
  unsigned long currentMillis = millis();
  digitalWrite(8, Pixel8state);

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel8) >= intervalPixel8) {
    // Change wait interval, based on current LED state
    if (Pixel8state) {
      // LED is currently on, set time to stay off
      intervalPixel8 = Pixel8offTime;
      strip.setPixelColor(8, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel8 = Pixel8onTime;
      strip.setPixelColor(8, WhiteColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!?
    Pixel8state = !(Pixel8state);

    // Save the current time to compare "later"
    previousMillisPixel8 = currentMillis;
  }
}
//4137 KAIPARA POUTU POINT Fl W 5s 6 6 White tower 4fl 0.3, ec 4.7
// Set Pixel9 to state of pixel8state each timethrough loop()
void kaiparaPoutuPoint() {
  unsigned long currentMillis = millis();
  digitalWrite(9, Pixel9state);

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisPixel9) >= intervalPixel9) {
    // Change wait interval, based on current LED state
    if (Pixel9state) {
      // LED is currently on, set time to stay off
      intervalPixel9 = Pixel9offTime;
      strip.setPixelColor(9, BlackColor);
      strip.show();
    } else {
      // LED is currently off, set time to stay on
      intervalPixel9 = Pixel9onTime;
      strip.setPixelColor(9, WhiteColor);
      strip.show();
    }
    // Toggle the LED's state, Fancy, eh!?
    Pixel9state = !(Pixel9state);

    // Save the current time to compare "later"
    previousMillisPixel9 = currentMillis;
  }
}

Hello
This is a good way to start using OOP.
Each light is an object that can formulated with the times for on/off light sequenze inside an array. To have multiple lights this array shall be arranged to a two dimenesional array. The first dimension contains the name of the light and the second contains the on/off sequence. All in all the sketch needs a data struct per light containing the information about the used led pin, colour and I guess a counter. One timer takes care about all information.
Have a nice day and enjoy coding in C++.

Thanks for the information - i will make a start at learning OOP and transfer the coding over. Its been over 20 years since i programmed a Motorola 68HC11 and that was in Pascal and this is my first time using Ardunio - fortunately there's lots of good tutorials and code that almost suits that i have been able to learn from

Yes. Use a variable. Add one to the variable each time the led is flashed. Simple as that.

There is a better way, and you don't necessarily need to go down the OOP route just yet, unless you want to. Whenever you see yourself making lots of variables with the same name but 1, 2, 3 at the end of the name, you should be using an array. Arrays let you remove lots of duplicated code by using a loop such as a for-loop to process each element of the array in turn.

Not sure how to answer that question. It sounds more like like a cry for help than an actual question.

Hello
Arrays are members of the OOP club.
The sketch can be made class-less by using some practical OOP instruction eg struct or range-based for loop.
Thus will result in a compact and maintainable code.
Have a nice day and enjoy coding in C++.

Thanks PaulRB and sorry the "Thirdly" was more a statement showing that i have enjoyed getting back into this side of programming but time just disappears and I have to force myself to Stop!

Ive started looking into OOP and have made a basic sketch to flash 3 x Pixels - does this look like i'm on the right track?
Note! I deleted my last post as i spotted an obvious error that needed fixing

#include <Adafruit_NeoPixel.h>

//define NeoPixel Pin and Number of LEDs
#define PIN 7
#define NUM_LEDS 10

//Define Colour "Constant?"
uint32_t RedColor;// current Color in case we need it
uint32_t GreenColor;// current Color in case we need it
uint32_t WhiteColor;// current Color in case we need it
uint32_t BlackColor;// current Color in case we need it

//create a NeoPixel strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_RGB + NEO_KHZ400);

class Flasher
{
    // Class Member Variables
    // These are initialized at startup
    int ledPin;      // the number of the LED pin
    long OnTime;     // milliseconds of on-time
    long OffTime;    // milliseconds of off-time

    // These maintain the current state
    int ledState;                 // ledState used to set the LED
    unsigned long previousMillis;   // will store last time LED was updated

    // Constructor - creates a Flasher
    // and initializes the member variables and state
  public:
    Flasher(int pin, long on, long off)
    {
      ledPin = pin;
      pinMode(ledPin, OUTPUT);

      OnTime = on;
      OffTime = off;

      ledState = LOW;
      previousMillis = 0;
    }

    void Update()
    {
      // check to see if it's time to change the state of the LED
      unsigned long currentMillis = millis();

      if ((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
      {
        ledState = LOW;  // Turn it off
        previousMillis = currentMillis;  // Remember the time
        strip.setPixelColor(ledPin, ledState);
        strip.show();
      }
      else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
      {
        ledState = HIGH;  // turn it on
        previousMillis = currentMillis;   // Remember the time
        strip.setPixelColor(ledPin, ledState);
        strip.show();
      }
    }
};


Flasher led1(0, 500, 400);
Flasher led2(1, 500, 400);
Flasher led3(3, 500, 400);

void setup() { // start the strip
  //Set the Colours defined earlier
  RedColor = strip.Color(255, 0, 0); //sets colour to Red
  GreenColor = strip.Color(0, 255, 0); //sets colour to Green
  WhiteColor = strip.Color(255, 255, 255); //sets colour to White
  BlackColor = strip.Color(0, 0, 0); //sets colour to off
  strip.begin();
  strip.show();
}

void loop()
{
  led1.Update();
  led2.Update();
  led3.Update();
}

And a updated code with the rest of the lights,
it's amazing how much shorter and cleaner the code is and if I have this right in my head the "Class" Flasher simply uses the arguments provided to perform the action on the Pixel# and the Void Loop keeps it updating - thanks for the suggestion's and I'll add more comments to my sketch to firmly get a grasp of the coding
Just the grouping for the first 2 pixels left

#include <Adafruit_NeoPixel.h>

//define NeoPixel Pin and Number of LEDs
#define PIN 7
#define NUM_LEDS 10

//Define Colour "Constant?"
uint32_t RedColor;// current Color in case we need it
uint32_t GreenColor;// current Color in case we need it
uint32_t WhiteColor;// current Color in case we need it
uint32_t BlackColor;// current Color in case we need it

//create a NeoPixel strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_RGB + NEO_KHZ400);

class Flasher
{
    // Class Member Variables
    // These are initialized at startup
    int ledPin;      // the number of the LED pin
    long OnTime;     // milliseconds of on-time
    long OffTime;    // milliseconds of off-time

    int red;
    int blue;
    int green;

    // These maintain the current state
    int ledState;                 // ledState used to set the LED
    unsigned long previousMillis;   // will store last time LED was updated

    // Constructor - creates a Flasher
    // and initializes the member variables and state
    // parameter .... pRed pBlue pGreen
  public:
    Flasher(int pin, long on, long off, int pRed, int pBlue, int pGreen)
    {
      ledPin = pin;
      pinMode(ledPin, OUTPUT);

      OnTime = on;
      OffTime = off;

      ledState = LOW;
      previousMillis = 0;

      red = pRed;
      blue = pBlue;
      green = pGreen;

    }

    void Update()
    {
      // check to see if it's time to change the state of the LED
      unsigned long currentMillis = millis();

      if ((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
      {
        ledState = LOW;  // Turn it off
        previousMillis = currentMillis;  // Remember the time
        strip.setPixelColor(ledPin, ledState);
        strip.show();
      }
      else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
      {
        ledState = HIGH;  // turn it on
        previousMillis = currentMillis;   // Remember the time
        //strip.setPixelColor(ledPin, HIGH);
        strip.setPixelColor(ledPin, red, green, blue);
        strip.show();
      }
    }
};


Flasher led1(0, 500, 2000, 0, 0, 255); //Arguments passed to contructor
Flasher led2(1, 1000, 4000, 0, 0, 255);
Flasher led3(2, 1000, 0, 255, 255, 255);
Flasher led4(3, 200, 400, 0, 0, 255);
Flasher led5(4, 300, 0, 255, 255, 255);
Flasher led6(5, 1000, 10000, 255, 0, 0);
Flasher led7(6, 1000, 10000, 255, 255, 255);
Flasher led8(7, 5000, 5000, 0, 0, 255);
Flasher led9(8, 1000, 7500, 255, 255, 255);
Flasher led10(9, 1000, 5000, 255, 255, 255);

void setup() { // start the strip
  //Set the Colours defined earlier
  RedColor = strip.Color(255, 0, 0); //sets colour to Red
  GreenColor = strip.Color(0, 255, 0); //sets colour to Green
  WhiteColor = strip.Color(255, 255, 255); //sets colour to White
  BlackColor = strip.Color(0, 0, 0); //sets colour to off
  strip.begin();
  strip.show();
}

void loop()
{
  led1.Update();
  led2.Update();
  led3.Update();
  led4.Update();
  led5.Update();
  led6.Update();
  led7.Update();
  led8.Update();
  led9.Update();
  led10.Update();

}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.