Newbie just tsrating, need help with a sketch

The code above shows how non-blocking timing works

the loop runs through very fast and does check the if-condition

if( currentMillis - previousMillis >= 80)

very often.
if 80 milliseconds have passed by the condition becomes true.

So a timer for let the bulbs blink for 30 seconds works with the same principle.
Make a snapshot of time and check if 30000 milliseconds have passed by.

If the blinking shall only happen after a button has been pressed you use a boolean variable
Just a suggestion for the variable name

boolean doBlink;

an if-condition checks the value

if (doBlink == true) {
  // do the blinking
}
``
the expression doBlink == true evaluates to "true" or "false"

As do Blink is a boolean variable which contains the value "true" or "false"
this could be written shorter as

if (doBlink) {
// do the blinking
}


There has to be an if-condition that checks for the buttonpress

just as pseudo-code (which is code that does **not** compile but explain the functionality) 

if (button_pin == pressed) {
  //make snapshot of Time (for the 30 seconds timer    previous30SecTimer
  set variable doBlink to true
}

if (previous30SecTimer - currentTime > 30000) {
  //set variable doBlink to false
}

and as the Blinking is only done when

if (doBlink) {
// do the blinking
}

the blinking stops
There are some more details to add but this is the basic principle

best regards Stefan
1 Like

Hello
a debounce-ing is essentional not needed, if the function of the control button is interlocked for the time of 30 seconds.

Thank you for taking the time to explain, i relaly appreciate it!

So I know this is wrong for a number of reasons:
It only starts the loop, and the loop continues forever.

const byte LedPins[5] = { 8, 9, 10, 11, 12};

unsigned long previousMillis;
int index = 0;
int updown = +1;      // +1 or -1 for going left and right
int buttonstate = 0;


void setup() 
{
  for( auto a:LedPins) 
    pinMode( a, OUTPUT);
    pinMode(2 ,INPUT_PULLUP);   // activates the internal pull-up resistor 
}

void loop () 
{
     if(buttonstate==LOW)
    {
       unsigned long currentMillis = millis();

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

    digitalWrite( LedPins[index], LOW);       // turn old led off
    index += updown;
    digitalWrite( LedPins[index], HIGH);      // turn new led on

    if( index <=0 || index >= 4)
      updown = -updown;
  }
   }
   else
   {
}
}

OK so there are some details that are important to know

You should let teh Arduino-IDE autoformat the indentions by pressing Ctrl-T.

If opening or closing brackets are missing they are easier to find because of a bracket is missing the indention looks different than it should

const byte LedPins[5] = { 8, 9, 10, 11, 12};

unsigned long previousMillis;
int index = 0;
int updown = +1;      // +1 or -1 for going left and right
int buttonstate = 0;


void setup()
{
  for ( auto a : LedPins)
    pinMode( a, OUTPUT);
    
  pinMode(2 , INPUT_PULLUP);  // activates the internal pull-up resistor
}

void loop ()
{
  if (buttonstate == LOW)
  {
    unsigned long currentMillis = millis();

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

      digitalWrite( LedPins[index], LOW);       // turn old led off
      index += updown;
      digitalWrite( LedPins[index], HIGH);      // turn new led on

      if ( index <= 0 || index >= 4)
        updown = -updown;
    }
  }
  else
  {
  }
}

declaring a variable inside of any brackets makes the variable local isnide these brackets.

  if (buttonstate == LOW)
  {
    unsigned long currentMillis = millis();

in this case outside the brackets the variable currentMillis is unknown
like a only local known singer inspite of a world-star that everybody around the world knows.

a global declaring of a variable is written outside any function and outside any brackets.

If you want to use more than one "timer" in your case you have the 80 milliseconds timer for switching on/of the lamps

and the second timer is the 30-second timer. And this second timer needs his own previousMillis-variable.

That's why I called it previous30SecondMillis .

There has to be a if-condition checking if the button is pressed
and if pressed that does two particular things:

  1. storing a snapshot of millis() in a variable called previous30SecondMillis

the name is program what number did function millis() have when the 30second interval started

  1. setting a global defined boolean variable named "doRunningLight" to true

for the compiler the name is not relevant you could name it "blabla" but this name gives absolutely no hints about the purpose of the variable

The part of the code that does the running-light shall only be exectuted if variable
doRunningLight is true

this means
if (doRunningLight) {
// the lines of code running the light
}

the loop has to have another if-condition that checks for how many seconds have passed by since last buttonpress

if (doRunningLight && currentMillis - previous30SecondMillis > 30000) {
doRunningLight = false
}

as soon as doRunningLight is false the code inside if-condition
if (doRunningLight) is no longer executed

so try to add this to the basic code and analyse the behaviour of your program
It is pretty likely that some details will still be wrong but that's my way of supporting. Giving hints and then practise.

best regards Stefan

Amazing, thanks Stefan! Great explanation! this will keep me going for a while to figure it out, but thats what's it about working it out :slight_smile:
Thank you again!

So I've gone back a step or two to try and learn :slight_smile: , and see if I can turn on an LED after 5 seconds, i thought this woudl work but it's not, where have i gone wrong

int ledPin = 12;        
unsigned long previousMillis;
unsigned long currentMillis = millis();
boolean doBlink;

void setup() 
{
   pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop () 
{
  unsigned long currentMillis = millis();
  if( currentMillis - previousMillis >= 500)  
  { doBlink == true;
  
  }

  if (doBlink) {

    digitalWrite( ledPin, HIGH); 
   
  }
    
  }
doBlink == true;

You are comparing doBlink to true rather than setting it to true

1 Like

Thank you @UKHeliBob !

so..I;ve been playing around, and this is where I;ve got so far;

The idea was to see if I could make it wait 5 seconds, then start the led sequence for 30seconds, then switch off the leds and repeat the cycle, so wait another 5 seconds and start the cycle, Im getting somehwere but i know ive got into a muddle with the timers and need some steering if possible :slight_smile:
Thank you!

const byte LedPins[5] = { 8, 9, 10, 11, 12};
unsigned long previousMillis;
unsigned long currentMillis = millis();
unsigned long previous30secondMillis;
int index = 0;
int updown = +1;      // +1 or -1 for going left and right
boolean doBlink;

void setup() 
{
 for( auto a:LedPins) 
    pinMode( a, OUTPUT);
}

void loop () 
{
  unsigned long currentMillis = millis();
  if( currentMillis - previousMillis >= 5000)  
  { doBlink = true;
  
  }

  if (doBlink) {
   unsigned long currentMillis = millis();

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

    digitalWrite( LedPins[index], LOW);       // turn old led off
    index += updown;
    digitalWrite( LedPins[index], HIGH);      // turn new led on

    if( index <=0 || index >= 4)
      updown = -updown;
  }
  }

  if (doBlink && currentMillis - previous30secondMillis > 30000) { 
doBlink = false;

  }
    
  }

I see some bad habits for just starting out programming.

Don't take short cuts in coding, especially at the start.

Make explicit lines of code, comment your sketch so you can come back to it later and easily understand what's going on.

boolean doBlink             = false;  //used to enable TIMERs

const byte maximum          = 5;

const byte LedPins[maximum] = {8, 9, 10, 11, 12};

byte index;

//+1 or -1 for going left and right
char updown                 = 1;

//timing stuff
unsigned long previousMillis;
unsigned long currentMillis;
unsigned long previous30secondMillis;

//*******************************************************************************
void setup()
{
  for (byte x = 0; x < maximum; x++)
  {
    pinMode(LedPins[x], OUTPUT);

    digitalWrite(LedPins[x], LOW);
  }

} //END of setup()


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

  //******************************                        5   s e c o n d   T I M E R
  //if the 5 second TIMER is enabled, has it expired ?
  if (doBlink == false && currentMillis - previousMillis >= 5000)
  {
    //enable the 80ms and 30 second TIMERs
    doBlink = true;

    //restart the 80ms TIMER
    previousMillis = millis();

    //restart the 30 second TIMER
    previous30secondMillis = millis();
  }

  //******************************                        8 0 m s   T I M E R
  //if the 80ms TIMER is enabled, has it expired ?
  if (doBlink == true && currentMillis - previousMillis >= 80)
  {
    //restart the 80ms TIMER
    previousMillis = currentMillis;

    digitalWrite( LedPins[index], LOW);      // turn old led off

    index += updown;

    digitalWrite(LedPins[index], HIGH);      // turn new led on

    //are we at the limit ?
    if ( index <= 0 || index >= 4)
    {
      updown = -updown;
    }
  }

  //******************************                        3 0   s e c o n d   T I M E R
  //if the 30 second TIMER is enabled, has it expired ?
  if (doBlink == true && currentMillis - previous30secondMillis > 30000)
  {
    //LEDs OFF
    for (byte x = 0; x < maximum; x++)
    {
      digitalWrite(LedPins[x], LOW);
    }

    //enable the 5 second TIMER
    doBlink = false;

    //restart the 5 second TIMER
    previousMillis = millis();
  }

} //END of loop()

I guess this should be a different comment
EDIT: No wait it is right but a bit short

//enable the 5 second TIMER  see if (doBlink == false && ....)
    doBlink = false;

best regards Stefan

1 Like

We are sure you know there is something called negative logic.

For example, a LOW reading from a switch can mean it it closed, but you knew that.

@LarryD Thank you! Yes I'll certainly continue to comment the code, thank you!

Keep up with your reading !

Have fun.

1 Like

@LarryD one thing i cant find amount and maybe throwing me is currentMillis and previousMillis;

I've read Millis is the time elpased since the programe run, but is current and previousMillis just the variable name given? coudl they be called anything?

this line:

 if (doBlink == false && currentMillis - previousMillis >= 5000)

I understand it's checking if 5 seconds has past and the doBlink is false but what has been assigned to previousMillis ?

I've read Millis is the time elpased since the programe run,
millis( ) returns the time since power up or reset.

but is current and previousMillis just the variable name given?
Yes they are variables
coudl they be called anything?
Yes

currentMillis could be called AcopyOfMillis
previousMillis could be called commonMillisValue

At power up, previousMillis is initialized to 0 by the compiler if it is not given an explicit value.
Also note millis( ) returns 0 at power up.

if (doBlink == false && currentMillis - previousMillis >= 5000)
So at power up we would have:
if(doBlink == false && 0 - 0 >= 5000)
Obviously this would not be so.


If you scoot down to the 30 second timer you see:


    //enable the 5 second TIMER
    doBlink = false;

    //restart the 5 second TIMER
    previousMillis = millis();

What is being done is the 5 second TIMER is enabled once again and we make previousMillis the same value that millis( ) returns

Making previousMillis = millis( ) basically resets the 5 second TIMER

I see - alot of people seem to use current and previous so I wondered if it was a pre determined variable name