3 LED blinking randomly using millis got reversed for some reason

  • Why are you using delay(1000) rather than the TIMERs created by the makeTIMER structure ?

  • If you had left the heartbeat section in the sketch, you would have seen that delay(1000) screws everything up.

  • Why are you not poling the ledChanger switch in the checkSwitches() function ?

void loop() {
  if (digitalRead(ledChanger) == HIGH) {      //Kiểm tra chọn nút đánh ngẫu nhiên
    singlemodecontrol();
  }
  • Why did you remove the top header in your attempt in post #61 ?

  • You do not seem to understand very much of what's happening in the sketch offered you.

  • If you want to become proficient in this area, you must be able to fully understand the techniques offered you here. Anything else, you may as well go fishing.

  • It is not enough to copy and paste code, nor is it reasonable to throw up your hands and revert to old programming habits instead of applying the things presented here.

  • Try these changes; you have one more chance to learn how to do things correctly.

//********************************************^************************************************
//  https://forum.arduino.cc/t/3-led-blinking-randomly-using-millis-got-reversed-for-some-reason/1164916/4
//
//  LarryD
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ====================================================================
//  1.00       20/09/03    Running code
//  1.10       20/09/04    Added the increment and decrement switches
//  1.20       20/09/05    Cleaned up the sketch a bit
//  1.30       20/09/10    Added a random/sequence Mode switch
//

//************************************************
#define LEDon                      HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff                     LOW

#define PUSHED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND
#define RELEASED                   HIGH

#define CLOSED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND 
#define OPEN                       HIGH

#define EXPIRED                    true
#define STILLtiming                false

#define ENABLED                    true
#define DISABLED                   false

#define YES                        true
#define NO                         false

#define RANDOM                     true
#define SEQUENCE                   false

//************************************************
const byte LEDpin1               = 2;       //PIN---[220R]---A[LED]K---GND
const byte LEDpin2               = 3;
const byte LEDpin3               = 4;

const byte incSwitch             = 5;       //+5V---[Internal 50k]---PIN---[switch]---GND
const byte decSwitch             = 6;
const byte modeSwitch            = 7;

const byte heartbeatLED          = 13;

const byte firstLED              = LEDpin1;
const byte lastLED               = LEDpin3;

bool modeFlag                    = SEQUENCE; //start out in sequence mode

byte sequenceCounter             = firstLED; //start out with the first LED
byte randNumber;
byte LEDselected;
byte lastIncSwitch               = RELEASED; //the last state of this switch
byte lastDecSwitch               = RELEASED;
byte lastModeSwitch              = RELEASED;

unsigned long minimumLEDoffTime  = 200ul;


//                          m i l l i s ( )   B a s e d   T I M E R S
//********************************************^************************************************
//
struct makeTIMER
{
#define ENABLED       true
#define DISABLED      false

#define YES           true
#define NO            false

#define EXPIRED       true
#define STILLtiming   false

  unsigned long Time;           //when the TIMER started
  unsigned long Interval;       //delay time in ms which we are looking for
  bool          TimerFlag;      //is the TIMER enabled ? ENABLED/DISABLED
  bool          Restart;        //restart this TIMER ? YES/NO

  //****************************************
  //function to check if the TIMER is enabled and check if the TIMER has expired
  bool checkTIMER()
  {
    //*********************
    //is this TIMER enabled and has this TIMER expired ?
    if (TimerFlag == ENABLED && millis() - Time >= Interval)
    {
      //*********************
      //should this TIMER restart ?
      if (Restart == YES)
      {
        //restart this TIMER
        Time = millis();
      }

      //this TIMER is enabled and has expired
      return EXPIRED;
    }

    //this TIMER is disabled and/or has not expired
    return STILLtiming;

  } //END of   checkTIMER()

  //****************************************
  //function to enable the TIMER
  void enableTIMER()
  {
    TimerFlag = ENABLED;

    //restart this TIMER
    Time = millis();

  } //END of   enableTIMER()

  //****************************************
  //function to disable this TIMER
  void disableTIMER()
  {
    TimerFlag = DISABLED;

  } //END of    disableTIMER()

  //****************************************
  //function to restart this TIMER
  void restartTIMER()
  {
    Time = millis();

  } //END of    restartTIMER()

}; //END of   struct makeTIMER

//********************************************^************************************************
/*example
  // *******************
  makeTIMER toggleLED =
  {
  0, 500ul, ENABLED/DISABLED, YES/NO  //.Time, .Interval, .TimerFlag, .Restart
  };
*/

//*******************
makeTIMER heartbeatTimer =
{
  0, 500ul, ENABLED, YES              //.Time, .Interval, .TimerFlag, .Restart
};

//*******************
makeTIMER checkSwitchesTimer =
{
  0, 50ul, ENABLED, YES               //.Time, .Interval, .TimerFlag, .Restart
};

//*******************
makeTIMER LEDonTimer =
{
  0, 1000ul, DISABLED, NO             //.Time, .Interval, .TimerFlag, .Restart
};

//*******************
makeTIMER LEDoffTimer =
{
  0, minimumLEDoffTime, DISABLED, NO  //.Time, .Interval, .TimerFlag, .Restart
};


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(115200);

  pinMode(heartbeatLED, OUTPUT);

  pinMode(LEDpin1, OUTPUT);
  pinMode(LEDpin2, OUTPUT);
  pinMode(LEDpin3, OUTPUT);

  pinMode(incSwitch, INPUT_PULLUP);
  pinMode(decSwitch, INPUT_PULLUP);
  pinMode(modeSwitch, INPUT_PULLUP);

  randomSeed(analogRead(A0));

} //END of   setup()


//                                        l o o p ( )
//********************************************^************************************************
void loop()
{
  //************************************************              T I M E R  heartbeat
  //is this TIMER enabled, is it time to toggle the heartbeat LED ?
  if (heartbeatTimer.checkTIMER() == EXPIRED)
  {
    //time toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //************************************************              T I M E R  checkSwitches
  //is this TIMER enabled, is it time to scan our switches ?
  if (checkSwitchesTimer.checkTIMER() == EXPIRED)
  {
    //time to check the switches
    checkSwitches();
  }

  //************************************************              T I M E R  LEDon
  //is this TIMER enabled, is it time to turn OFF this LED ?
  if (LEDonTimer.checkTIMER() == EXPIRED)
  {
    //the selected LED goes OFF
    digitalWrite(LEDselected, LEDoff);

    //we are finished using this TIMER
    LEDonTimer.disableTIMER();

    //enable the LEDoff TIMER
    LEDoffTimer.enableTIMER();
  }

  //************************************************              T I M E R  LEDoff
  //is this TIMER enabled, is it time to turn ON the next LED ?
  if (LEDoffTimer.checkTIMER() == EXPIRED)
  {
    //we are finished using this TIMER
    LEDoffTimer.disableTIMER();
  }

  //************************************************              Next  LED
  //has LED timing stopped ?
  if (LEDonTimer.TimerFlag == DISABLED && LEDoffTimer.TimerFlag == DISABLED)
  {
    //are we in random Mode ?
    if (modeFlag == RANDOM)
    {
      //pick a random LED to operate
      randomly();
    }

    //we must be in sequence Mode
    else
    {
      //pick the next LED in the sequence
      sequence();
    }
  }

  //************************************************
  //other non blocking code goes here
  //************************************************

} //END of   loop()


//                               c h e c k S w i t c h e s ( )
//********************************************^************************************************
void checkSwitches()
{
  byte state;

  //************************************************              incSwitch
  state = digitalRead(incSwitch);

  //has there been a change in switch's state ?
  if (lastIncSwitch != state)
  {
    //update to this new state
    lastIncSwitch = state;

    //*************************************
    //if the decSwitch is released, is the increment switch PUSHED ?
    if (lastDecSwitch == RELEASED && state == PUSHED)
    {
      //increase the LED OFF time
      LEDoffTimer.Interval += 100ul;
    }

  } //END of this switch

  //************************************************              decSwitch
  state = digitalRead(decSwitch);

  //has there been a change in switch's state ?
  if (lastDecSwitch != state)
  {
    //update to this new state
    lastDecSwitch = state;

    //*************************************
    //if the incSwitch is released, is the decrement switch PUSHED ?
    if (lastIncSwitch == RELEASED && state == PUSHED)
    {
      //decrease the LED OFF time
      LEDoffTimer.Interval -= 100ul;

      //do not go under minimumLEDoffTime
      if (LEDoffTimer.Interval < minimumLEDoffTime)
      {
        LEDoffTimer.Interval = minimumLEDoffTime;
      }
    }

  } //END of this switch

  //************************************************              modeSwitch
  state = digitalRead(modeSwitch);

  //has there been a change in switch's state ?
  if (lastModeSwitch != state)
  {
    //update to this new state
    lastModeSwitch = state;

    //*************************************
    //is the mode switch PUSHED ?
    if (state == PUSHED)
    {
      //toggle the operating mode
      modeFlag = !modeFlag;
    }

  } //END of this switch

} //END of   checkSwitches()


//                                    s e q u e n c e ( )
//********************************************^************************************************
void sequence()
{
  LEDselected = sequenceCounter;

  //the selected LED goes ON
  digitalWrite(LEDselected, LEDon);

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

  //next LED to operate
  sequenceCounter++;

  //don't go past the last LED
  if (sequenceCounter > lastLED)
  {
    //start at the first LED
    sequenceCounter = firstLED;
  }

} //END of   sequence()

//                                    r a n d o m l y ( )
//********************************************^************************************************
void randomly()
{
  //select a LED connected to pin 2,3 or 4
  LEDselected = random(firstLED, lastLED + 1);

  //the selected LED goes ON
  digitalWrite(LEDselected, LEDon);

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

} //END of   randomly()


//********************************************^************************************************

Sorry for a dumb code, i was trying to put the timer in my old code

The delay was from my old code, i put the delay over there because i want to let you know what i was doing. Of course when i put one delay, it will screw everything up

Thats why i was asking you how to use the timer in the section that i mentioned inside the code.

Of course i will use the

Sorry for that, i do understand all of the code

Does the sketch in post #63 work for you ?

Im at school:D, ill test it as soon as possible, sorry for making you missunderstand me because of the code

This is actually what i was asking for :sweat_smile:
What I need was the mechanism of the single mode, so the reason i put delay in my sketch was actually explaining to you what I meant so uhhh sorry for making you missunderstand :sweat_smile:

it doesnt work:/ im trying to fix it, the modeSwitch somehow doesnt work tho, but i will try to make my own sketch using your sequence(), because thats the only thing i need

when i separate this, it works great so now im trying to do things on my own

hey there, I fixed it in my way and it works like a charm! Tomorrow i will work on the modeSwitch, i think i can handle that.
you can check this sketch out

//********************************************^************************************************
//  https://forum.arduino.cc/t/3-led-blinking-randomly-using-millis-got-reversed-for-some-reason/1164916/4
//
//  LarryD
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ====================================================================
//  1.00       20/09/03    Running code
//
//
//

//************************************************
#define EXPIRED                    true
#define stillTIMING                false

#define LEDon                      HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff                     LOW

#define PUSHED                     HIGH    //+5V---[Internal 50k]---PIN---[switch]---GND
#define RELEASED                   LOW

#define CLOSED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND 
#define OPEN                       HIGH

#define ENABLED                    true
#define DISABLED                   false

#define YES                        true
#define NO                         false

#define SEQUENCE                   false



//************************************************


const byte LEDpin1               = 2;  
const byte LEDpin2               = 3;  
const byte LEDpin3               = 4;  
const byte heartbeatLED          = 13;
const byte incSwitch             = 5;     //+5V---[Internal 50k]---PIN---[switch]---GND
const byte decSwitch             = 6;   
const byte ledChanger            = 7;

const byte firstLED              = LEDpin1;
const byte lastLED               = LEDpin3;


byte sequenceCounter             = firstLED; //start out with the first LED

byte randNumber;
byte LEDselected;

//                          m i l l i s ( )   B a s e d   T I M E R S
//********************************************^************************************************
//TIMER definitions
//Two ways to define a new TIMER
//The first, we will call it a manual method:        example: heartbeat TIMER
//The second, we will call it the structure method:  example: scanSwitches TIMER

//****************************************
//manual method:
//heartbeat TIMER
unsigned long heartbeatTime      = 0;
unsigned long heartbeatInterval  = 500ul;
bool heartbeatTimerFlag          = ENABLED;
bool heartbeatRestart            = YES;
byte lastIncSwitch               = RELEASED;
byte lastDecSwitch               = RELEASED;
byte lastLedSwitch               = RELEASED;

//****************************************
//structure method:
struct makeTIMER
{
//#define ENABLED       true
//#define DISABLED      false

//#define YES           true
//#define NO            false

//#define EXPIRED       true
//#define stillTIMING   false

  unsigned long Time;           //when the TIMER started
  unsigned long Interval;       //delay time in ms which we are looking for
  bool          timerFlag;      //is the TIMER enabled ? ENABLED/DISABLED
  bool          Restart;        //restart this TIMER ? YES/NO

  //****************************************
  //fuction to check if the TIMER is enabled and check if the TIMER has expired
  bool checkTIMER()
  {
    //*********************
    //is this TIMER enabled and has this TIMER expired ?
    if (timerFlag == ENABLED && millis() - Time >= Interval)
    {
      //*********************
      //should this TIMER restart again?
      if (Restart == YES)
      {
        //restart this TIMER
        Time = millis();
      }

      //this TIMER is enabled and has expired
      return EXPIRED;
    }

    //this TIMER is disabled and/or has not expired
    return stillTIMING;
  } //END of   checkTime()

  //****************************************
  //function to enable the TIMER
  void enableTIMER()
  {
    timerFlag = ENABLED;

    //restart this TIMER
    Time = millis();

  } //END of   enableTIMER()

  //****************************************
  //function to disable this TIMER
  void disableTIMER()
  {
    timerFlag = DISABLED;

  } //END of    disableTIMER()

  //****************************************
  //function to restart this TIMER
  void restartTIMER()
  {
    Time = millis();

  } //END of    restartTIMER()

}; //END of   struct makeTIMER


makeTIMER checkSwitchesTimer1 =
{
  0, 50ul, ENABLED, YES      //Time, Interval, timerFlag, Restart
};

makeTIMER checkSwitchesTimer2 =
{
  0, 50ul, ENABLED, YES      //Time, Interval, timerFlag, Restart
};

makeTIMER checkSwitchesTimer3 =
{
  0, 50ul, ENABLED, YES      //Time, Interval, timerFlag, Restart
};

//*******************
makeTIMER LEDonTimer =
{
  0, 1000ul, DISABLED, NO      //Time, Interval, timerFlag, Restart
};
//*******************
makeTIMER LEDoffTimer =
{
  0, 200ul, DISABLED, NO      //Time, Interval, timerFlag, Restart
};
//*******************


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(115200);
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);
  pinMode(LEDpin1, OUTPUT);
  pinMode(LEDpin2, OUTPUT);
  pinMode(LEDpin3, OUTPUT);
  pinMode(incSwitch, INPUT_PULLUP);
  pinMode(decSwitch, INPUT_PULLUP);
  pinMode(ledChanger, INPUT_PULLUP);


  //randomSeed(analogRead(A0));

} //END of   setup()


//                                        l o o p ( )
//********************************************^************************************************
void loop()
{
  //************************************************              T I M E R  heartbeatLED
  //when enabled, is it time to toggle the heartbeat LED ?

  //is this TIMER enabled and is it time to scan our switches ?
  if (checkSwitchesTimer1.checkTIMER() == EXPIRED)
  {
    checkSwitches();
  }

  if (checkSwitchesTimer2.checkTIMER() == EXPIRED)
  {
    checkSwitches();
  }

  if (checkSwitchesTimer3.checkTIMER() == EXPIRED)
  {
    checkSwitches();
  }

  if (heartbeatTimerFlag == ENABLED && millis() - heartbeatTime >= heartbeatInterval)
  {
    //restart this TIMER ?
    if (heartbeatRestart == YES)
    {
      heartbeatTime = millis();
    }

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //************************************************           T I M E R  LEDon

  //is the TIMER enabled and is it time to turn OFF this LED ?

  if (LEDonTimer.checkTIMER() == EXPIRED)
  {
    //LED selected goes OFF
    digitalWrite(LEDselected, LEDoff);

    //disabled this TIMER
    LEDonTimer.timerFlag = DISABLED;

    //enable the OFF TIMER
    LEDoffTimer.timerFlag = ENABLED;

    //restart the OFF TIMER
    LEDoffTimer.Time = millis();    
  }

  //************************************************           T I M E R  LEDoff
  //is the TIMER enabled and is it time to turn ON the next LED ?
  if (LEDoffTimer.checkTIMER() == EXPIRED)
  {
    //disabled this TIMER
    LEDoffTimer.timerFlag = DISABLED;
  }

  //************************************************              Next random LED
  //has LED timing stopped ?
  if (LEDonTimer.timerFlag == DISABLED && LEDoffTimer.timerFlag == DISABLED)
  {
    //randomly();
    sequence();
  }

  //************************************************
  //other non blocking code goes here
  //************************************************

} //END of   loop()


//                                    r a n d o m l y ( )
//********************************************^************************************************

//                               c h e c k S w i t c h e s ( )
//********************************************^************************************************
void checkSwitches()
{
  byte state1;
  byte state2;
  byte state3;

  //*******************************************                       incSwitch
  state1 = digitalRead(incSwitch);
  state2 = digitalRead(decSwitch);
  state3 = digitalRead(ledChanger);

  //has there been a change in "incSwitch" state ?
  if (lastIncSwitch != state1)
  {
    //update to this new state
    lastIncSwitch = state1;

    //*************************************
    //is the increment switch PUSHED ?
    if(state1 == PUSHED)
    {
      //increase the LED OFF time
      if(LEDoffTimer.Interval == 1000ul){
        LEDoffTimer.Interval += 0ul;
        Serial.println(LEDoffTimer.Interval);
      }
      else{
        LEDoffTimer.Interval += 100ul;
        Serial.println(LEDoffTimer.Interval);
      }
    }
  } //END of this switch

  //*******************************************                       decSwitch
  //code for the decrement switch goes here       <---------<<<<<<

  //has there been a change in "decSwitch" state ?
  if (lastDecSwitch != state2)
  {
    //update to this new state
    lastDecSwitch = state2;

    //*************************************
    //is the increment switch PUSHED ?
    if(state2 == PUSHED)
    {
      //increase the LED OFF time
      if(LEDoffTimer.Interval == 200ul){
        LEDoffTimer.Interval += 0ul;
        Serial.println(LEDoffTimer.Interval);
      }
      else{
        LEDoffTimer.Interval -= 100ul;
        Serial.println(LEDoffTimer.Interval);
      }
    }
  } //END of this switch

  //*******************************************                       ledChanger
  //has there been a change in "ledChanger" state ?
  if (lastLedSwitch != state3)
  {
    //update to this new state
    lastLedSwitch = state3;

    //is the switch PUSHED ?
    if(state3 == PUSHED)
    {
      sequenceCounter++;
      //don't go past the last LED 
      if (sequenceCounter > lastLED)
      {
        //start at the first LED
        sequenceCounter = firstLED;
      }
    }
  } //END of this switch

} //END of   checkSwitches()

void randomly()
{
  //select a LED connected to pin 2,3 or 4
  LEDselected = random(2,5);

  //LED goes ON
  digitalWrite(LEDselected, LEDon);

  //enable the LEDon TIMER
  LEDonTimer.timerFlag = ENABLED;

  //restart this TIMER
  LEDonTimer.Time = millis();

} //END of   randomly()

//                                    s e q u e n c e ( )
//********************************************^************************************************
void sequence()
{
  LEDselected = sequenceCounter;

  //the selected LED goes ON
  digitalWrite(LEDselected, LEDon);

  Serial.println(sequenceCounter);

  //enable the LEDon TIMER
  LEDonTimer.timerFlag = ENABLED;

} //END of   sequence()


//********************************************^************************************************

You forgot restart the TIMER !

//                                    s e q u e n c e ( )
//********************************************^************************************************
void sequence()
{
  LEDselected = sequenceCounter;

  //the selected LED goes ON
  digitalWrite(LEDselected, LEDon);

  Serial.println(sequenceCounter);

  //enable the LEDon TIMER
  LEDonTimer.timerFlag = ENABLED;
  
  //restart the TIMER
  LEDonTimer.Time = millis();          // <-----<<<<<  You need to restart the TIMER !

} //END of   sequence()

Why are you using 3 variables ?

  state1 = digitalRead(incSwitch);
  state2 = digitalRead(decSwitch);
  state3 = digitalRead(ledChanger);

You only need 1

  byte state;

  //************************************************              incSwitch
  state = digitalRead(incSwitch);

. . . . . .

  //************************************************              decSwitch
  state = digitalRead(decSwitch);

. . . . . .

  //************************************************              modeSwitch
  state = digitalRead(modeSwitch);

1 Like
  • One thing you should learn from this exercise; when you do not define everything fully the software sketch can be cumbersome.

  • If we were to start over, this sketch should have been written using State Machine techniques. We will leave that topic for next time.

Try this version of the sketch.

  • You should see 5 different LED display modes.
    enum LEDmodes {START, SEQUENCE, SINGLEled, RANDOM, ALL, REVERSEsequence, END }; // <--------<<<<< M O D E S

  • Work your way through the sketch to see how things are being done.
  • If you want to learn, ask questions.

After you test the sketch, add a 4th LED/resistor to pin #8 and make this change:

  • Change:
    const byte LEDarray[] = {2, 3, 4}; //PIN---[220R]---A[LED]K---GND W i t h 3 L E D s
  • To:
    const byte LEDarray[] = {2, 3, 4, 8}; //PIN---[220R]---A[LED]K---GND W i t h 4 L E D s

What happens when you make the above changes ?


//********************************************^************************************************
//  https://forum.arduino.cc/t/3-led-blinking-randomly-using-millis-got-reversed-for-some-reason/1164916/4
//
//  LarryD
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ====================================================================
//  1.00       20/09/03    Running code
//  1.10       20/09/04    Added the increment and decrement switches
//  1.20       20/09/05    Cleaned up the sketch a bit
//  1.30       20/09/10    Added a random/sequence Mode switch
//  1.40       20/09/10    Changed MODE from 2 to more than 3 . . .  display modes
//

//************************************************
#define LEDon                      HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff                     LOW

#define PUSHED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND
#define RELEASED                   HIGH

#define CLOSED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND 
#define OPEN                       HIGH

#define EXPIRED                    true
#define STILLtiming                false

#define ENABLED                    true
#define DISABLED                   false

#define YES                        true
#define NO                         false

#define minimumLEDoffTime          200ul


//                        m i l l i s ( )   B a s e d   T I M E R S
//********************************************^************************************************
//
struct makeTIMER
{
  //#define ENABLED       true
  //#define DISABLED      false
  //
  //#define YES           true
  //#define NO            false
  //
  //#define EXPIRED       true
  //#define STILLtiming   false

  unsigned long Time;           //when the TIMER started
  unsigned long Interval;       //delay time in ms which we are looking for
  bool          TimerFlag;      //is the TIMER enabled ? ENABLED/DISABLED
  bool          Restart;        //restart this TIMER ? YES/NO

  //****************************************
  //function to check if the TIMER is enabled and check if the TIMER has expired
  bool checkTIMER()
  {
    //*********************
    //is this TIMER enabled and has this TIMER expired ?
    if (TimerFlag == ENABLED && millis() - Time >= Interval)
    {
      //*********************
      //should this TIMER restart ?
      if (Restart == YES)
      {
        //restart this TIMER
        Time = millis();
      }

      //this TIMER is enabled and has expired
      return EXPIRED;
    }

    //this TIMER is disabled and/or has not expired
    return STILLtiming;

  } //END of   checkTIMER()

  //****************************************
  //function to enable the TIMER
  void enableTIMER()
  {
    TimerFlag = ENABLED;

    //restart this TIMER
    Time = millis();

  } //END of   enableTIMER()

  //****************************************
  //function to disable this TIMER
  void disableTIMER()
  {
    TimerFlag = DISABLED;

  } //END of    disableTIMER()

  //****************************************
  //function to restart this TIMER
  void restartTIMER()
  {
    Time = millis();

  } //END of    restartTIMER()

}; //END of   struct makeTIMER

//********************************************^************************************************
/*example
  // *******************
  makeTIMER toggleLED =
  {
  0, 500ul, ENABLED/DISABLED, YES/NO  //.Time, .Interval, .TimerFlag, .Restart
  };
*/

//*******************
makeTIMER heartbeatTimer =
{
  0, 500ul, ENABLED, YES              //.Time, .Interval, .TimerFlag, .Restart
};

//*******************
makeTIMER checkSwitchesTimer =
{
  0, 50ul, ENABLED, YES               //.Time, .Interval, .TimerFlag, .Restart
};

//*******************
makeTIMER LEDonTimer =
{
  0, 1000ul, DISABLED, NO             //.Time, .Interval, .TimerFlag, .Restart
};

//*******************
makeTIMER LEDoffTimer =
{
  0, minimumLEDoffTime, DISABLED, NO  //.Time, .Interval, .TimerFlag, .Restart
};


//********************************************^************************************************
//LED display modes
enum LEDmodes {START, SEQUENCE, SINGLEled, RANDOM, ALL, REVERSEsequence, END }; // <------<<<<     M O D E S

//the LED GPIOs used in the display
const byte LEDarray[]            = {2, 3, 4};    //PIN---[220R]---A[LED]K---GND        W i t h   3   L E D s
//const byte LEDarray[]          = {2, 3, 4, 8}; //PIN---[220R]---A[LED]K---GND        W i t h   4   L E D s

const byte incSwitch             = 5;            //+5V---[Internal 50k]---PIN---[switch]---GND
const byte decSwitch             = 6;
const byte modeSwitch            = 7;

const byte heartbeatLED          = 13;

byte randNumber;
byte LEDselected;
byte lastIncSwitch               = RELEASED;     //the last state of this switch
byte lastDecSwitch               = RELEASED;
byte lastModeSwitch              = RELEASED;

int singleLEDcounter             = -1;
int sequenceCounter              = 0;            //start out with the first LED
int modeCounterFlag              = START + 1;    //start out in sequence mode


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(115200);

  pinMode(heartbeatLED, OUTPUT);

  //all LED GPIOs made OUTPUTS
  for (byte x = 0; x < sizeof(LEDarray) / sizeof(LEDarray[0]); x++)
  {
    pinMode(LEDarray[x], OUTPUT);
  }

  pinMode(incSwitch, INPUT_PULLUP);
  pinMode(decSwitch, INPUT_PULLUP);
  pinMode(modeSwitch, INPUT_PULLUP);

  randomSeed(analogRead(A0));

} //END of   setup()


//                                        l o o p ( )
//********************************************^************************************************
void loop()
{
  //************************************************              T I M E R  heartbeat
  //is this TIMER enabled, is it time to toggle the heartbeat LED ?
  if (heartbeatTimer.checkTIMER() == EXPIRED)
  {
    //time toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //************************************************              T I M E R  checkSwitches
  //is this TIMER enabled, is it time to scan our switches ?
  if (checkSwitchesTimer.checkTIMER() == EXPIRED)
  {
    //time to check the switches
    checkSwitches();
  }

  //************************************************              T I M E R  LEDon
  //is this TIMER enabled, is it time to turn OFF this LED ?
  if (LEDonTimer.checkTIMER() == EXPIRED)
  {
    //all LED GPIOs go OFF
    for (byte x = 0; x < sizeof(LEDarray) / sizeof(LEDarray[0]); x++)
    {
      digitalWrite(LEDarray[x], LEDoff);
    }

    //we are finished using this TIMER
    LEDonTimer.disableTIMER();

    //enable the LEDoff TIMER
    LEDoffTimer.enableTIMER();
  }

  //************************************************              T I M E R  LEDoff
  //is this TIMER enabled, is it time to turn ON LED(s) ?
  if (LEDoffTimer.checkTIMER() == EXPIRED)
  {
    //we are finished using this TIMER
    LEDoffTimer.disableTIMER();
  }

  //************************************************              Next  LED
  //has LED timing stopped ?
  if (LEDonTimer.TimerFlag == DISABLED && LEDoffTimer.TimerFlag == DISABLED)
  {
    //what LED display mode are we in ?
    switch (modeCounterFlag)
    {
      //**********************
      case SEQUENCE:
        {
          //pick the next LED in the sequence
          sequence();
        }
        break;

      //**********************
      case SINGLEled:
        {
          //operate just one LED
          single();
        }
        break;

      //**********************
      case RANDOM:
        {
          //pick another random LED to operate
          randomly();
        }
        break;

      //**********************
      case ALL:
        {
          //operate LEDs
          ALLleds();
        }
        break;

      //**********************
      case REVERSEsequence:
        {
          //operate LEDs
          reverse();
        }
        break;

    } //END of   switch/case
  }

  //************************************************
  //other non blocking code goes here
  //************************************************

} //END of   loop()


//                               c h e c k S w i t c h e s ( )
//********************************************^************************************************
void checkSwitches()
{
  byte state;

  //************************************************              incSwitch
  state = digitalRead(incSwitch);

  //has there been a change in switch's state ?
  if (lastIncSwitch != state)
  {
    //update to this new state
    lastIncSwitch = state;

    //*************************************
    //if the decSwitch is released, is the increment switch PUSHED ?
    if (lastDecSwitch == RELEASED && state == PUSHED)
    {
      //increase the LED OFF time
      LEDoffTimer.Interval += 100ul;
    }

  } //END of this switch

  //************************************************              decSwitch
  state = digitalRead(decSwitch);

  //has there been a change in switch's state ?
  if (lastDecSwitch != state)
  {
    //update to this new state
    lastDecSwitch = state;

    //*************************************
    //if the incSwitch is released, is the decrement switch PUSHED ?
    if (lastIncSwitch == RELEASED && state == PUSHED)
    {
      //decrease the LED OFF time
      LEDoffTimer.Interval -= 100ul;

      //do not go under minimumLEDoffTime
      if (LEDoffTimer.Interval < minimumLEDoffTime)
      {
        LEDoffTimer.Interval = minimumLEDoffTime;
      }
    }

  } //END of this switch

  //************************************************              modeSwitch
  state = digitalRead(modeSwitch);

  //has there been a change in switch's state ?
  if (lastModeSwitch != state)
  {
    //update to this new state
    lastModeSwitch = state;

    //*************************************
    //is the mode switch PUSHED ?
    if (state == PUSHED)
    {
      //only increment modeCounter if not in SINGLEled
      if (modeCounterFlag != SINGLEled)
      {
        //next LED display mode
        modeCounterFlag++;
      }

      //are we at the end of the LED display modes
      if (modeCounterFlag == END)
      {
        //back to the beginning of the display modes
        modeCounterFlag = START + 1;
      }

      //set up initial conditions
      switch (modeCounterFlag)
      {
        //**********************
        case SINGLEled:
          {
            //first element in the LEDarray
            singleLEDcounter++;

            //have we done each LED ?
            if (singleLEDcounter > (sizeof(LEDarray) / sizeof(LEDarray[0]) - 1))
            {
              //okay, next display mode
              modeCounterFlag++;

              //re-initialize for next time
              singleLEDcounter = -1;
            }
          }
          break;

        //**********************
        case SEQUENCE:
          {
            //first element in the LEDarray
            sequenceCounter = 0;
          }
          break;

        //**********************
        case REVERSEsequence:
          {
            //last element in the LEDarray
            sequenceCounter = (sizeof(LEDarray) / sizeof(LEDarray[0]) - 1);
          }
          break;

      } //END of   switch/case
    }

  } //END of this switch

} //END of   checkSwitches()


//                                     r e v e r s e ( )
//********************************************^************************************************
void reverse()
{
  //the selected LED goes ON         LEDarray[0], LEDarray[1] or LEDarray[2]
  digitalWrite(LEDarray[sequenceCounter], LEDon);

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

  //next LED to operate
  sequenceCounter--;

  //don't go less than first LED in LEDarray[]
  if (sequenceCounter < 0)
  {
    //start at the last LEDarray element
    sequenceCounter = (sizeof(LEDarray) / sizeof(LEDarray[0]) - 1);
  }

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

} //END of reverse()


//                                      A L L l e d s ( )
//********************************************^************************************************
void ALLleds()
{
  //all LED GPIOs go ON
  for (byte x = 0; x < sizeof(LEDarray) / sizeof(LEDarray[0]); x++)
  {
    digitalWrite(LEDarray[x], LEDon);
  }

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

} //END of   ALLleds()


//                                      s i n g l e ( )
//********************************************^************************************************
void single()
{
  digitalWrite(LEDarray[singleLEDcounter], LEDon);

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

} //END of   single()


//                                    s e q u e n c e ( )
//********************************************^************************************************
void sequence()
{
  //the selected LED goes ON         LEDarray[0], LEDarray[1] or LEDarray[2]
  digitalWrite(LEDarray[sequenceCounter], LEDon);

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

  //next LED to operate
  sequenceCounter++;

  //don't go past the last LED in LEDarray[]
  if (sequenceCounter > (sizeof(LEDarray) / sizeof(LEDarray[0])) - 1)
  {
    //start at the first LED
    sequenceCounter = 0;
  }

} //END of   sequence()


//                                    r a n d o m l y ( )
//********************************************^************************************************
void randomly()
{
  //select a LEDarray[] element i.e. 0, 1, 2
  LEDselected = random(0, (sizeof(LEDarray) / sizeof(LEDarray[0])));

  //the selected LED goes ON
  digitalWrite(LEDarray[LEDselected], LEDon);

  //enable the LEDon TIMER
  LEDonTimer.enableTIMER();

} //END of   randomly()


//********************************************^************************************************
1 Like

ok instead of adding more LED display modes, i need to add 2 more mode which are: punch's force measurement(using g force from a MPU6050) and velocity of a punch(which ill do later)
my project is a punching bag that can be use to practice how fast can you punch by punching marks that has the LED on top of it, there are 10 LEDs, 5 red LEDs represent for the right arm, and 5 green LEDs for the left arm. I can change to modes and there are 4 of them(can be more in the future) which are Random LED mode, Single Mode(which is the sequence mode) Punch's Force measurement and Punch's velocity measurement. Im planning to use ic for the LEDs (74HC595) but my skills are limited so can you help me with that?

I think you are missing the lesson here.

The point is to show you how to change/add code to an existing sketch to make that sketch do something new.

Suggest you look (very closely) at how things are written to learn what was done so you can apply similar techniques.

The help given so far is all about mastering programming techniques, not about doing your project for you.

It is obvious you have a goal to accomplish, the problem we see is you did not fully explain this goal to this group at the very beginning of this thread.

It seems you keep moving these goal posts.


Before proceeding, draw a complete schematic of everything that needs to be in your project’s circuitry.



Have you considered using a NeoPixel strip ?

IMG_2068

You could have as many LEDs as needed, any colour, all on a strip of LEDs.

Only one Arduino pin is needed.

2 Likes

Oh im just describing my project to let you understand what im doing :sweat_smile:

The last sketch offered you probably exposes all the techniques you will ever need for this and future projects.

2 Likes

Wait one second, these strips can be cut into 1 led?

Yes you can cut the Neopixel WS2812B strips between LEDs, 1, 2, 3, 4 etc.


Also, these are available, 100 for about $20.00 on Amazon.