Arduino Looping states in Void Loop help needed for a novice.

Thread Starter

James90s

Joined Mar 3, 2021
31
Hello everyone.

I am still very new to programming an Arduino. I have this code that changes states, but it does not repeat. It works once and I then need to go through all the counts again to repeat. How can I keep each state repeating without having to go through the count again.

Any help would be appreciated.
Mod: use Code Tags.E

Code below.

C-like:
int button = 4;

  int pin2 = 2;

   int pin7 = 7;

    int oldstate = LOW;

     int count = HIGH;


void setup() {

  pinMode(button, INPUT);

   pinMode(pin2, OUTPUT);

    pinMode(pin7, OUTPUT);

    }



void loop() {


  int buttonstate = digitalRead(button);

   if (buttonstate == oldstate && buttonstate == HIGH){      

    if (count == 1){

     digitalWrite(pin2,HIGH);

        delay(400);

         digitalWrite(pin2,LOW);

          delay(400);

           digitalWrite(pin2,HIGH);

            delay(400);

             digitalWrite(pin2,LOW);

              delay(400);

              }

   

     if (count == 2){

      digitalWrite(pin7,HIGH);

        delay(400);

         digitalWrite(pin7,LOW);

          delay(400);

           digitalWrite(pin7,HIGH);

            delay(400);

             digitalWrite(pin7,LOW);

              delay(400);

              }


   

      if (count < 2);


      else

       count = 0;

        count++;

         delay(50);

         }

       

      oldstate = buttonstate;

      }
 
Last edited by a moderator:

ericgibbs

Joined Jan 29, 2010
16,747
hi James.
Built the project,.
#1
Press p/b, LED1 flashes twice,
press p/b again LED2 flashes twice.
back to #1
What do want to happen.??
E
 

Thread Starter

James90s

Joined Mar 3, 2021
31
hi James.
Built the project,.
#1
Press p/b, LED1 flashes twice,
press p/b again LED2 flashes twice.
back to #1
What do want to happen.??
E
Hello.
I want to build a light, but I would like it to have many modes like Christmas tree lights. So if I have 10 led's, I would like to click the button once and it moves to a list of coding on the first increment then the lights flash on and off, and repeat the same way until I press the button again and move to another the second state where it will flash in a different until I then press the button again and it moves back to its original state. Just like a set of Christmas tree lights with a controller.
 

ericgibbs

Joined Jan 29, 2010
16,747
hi James.
Look at this option, you can add more patterns and call them in an order to suit the project.
E

C-like:
int button = 4;
  int pin2 = 2;
   int pin7 = 7;
    int oldstate = LOW;
     int count = HIGH;

void setup() {
  pinMode(button, INPUT);
   pinMode(pin2, OUTPUT);
    pinMode(pin7, OUTPUT);
    }

void loop() {
  int buttonstate = digitalRead(button);
//   if (buttonstate == oldstate && buttonstate == HIGH){     
    if (count == 1){
      pattern1();}
      
    if (count == 2){
      pattern2();} 
    
    if (count == 3){
     pattern3();}
    
     if (count == 4){
     pattern3();
     pattern2();
     pattern1();}
    
      if (count < 4);
      else
      count = 0;
      count++;
      delay(50);
      }
 //     oldstate = buttonstate;
      

void pattern1(){
   digitalWrite(pin7,HIGH);
        delay(400);
         digitalWrite(pin7,LOW);
          delay(400);
           digitalWrite(pin7,HIGH);
            delay(400);
             digitalWrite(pin7,LOW);
              delay(400);
return;
}

void pattern2(){
  digitalWrite(pin2,HIGH);
        delay(400);
         digitalWrite(pin2,LOW);
          delay(400);
           digitalWrite(pin2,HIGH);
            delay(400);
             digitalWrite(pin2,LOW);
              delay(400);
return;
}

void pattern3(){
  digitalWrite(pin2,HIGH);
        delay(200);
          digitalWrite(pin7,HIGH);
          delay(200);
         digitalWrite(pin2,LOW);
          delay(200);
           digitalWrite(pin7,HIGH);
            delay(200);
             digitalWrite(pin7,HIGH);
              delay(200);
return;
}
 

Thread Starter

James90s

Joined Mar 3, 2021
31
hi James.
Look at this option, you can add more patterns and call them in an order to suit the project.
E

C-like:
int button = 4;
  int pin2 = 2;
   int pin7 = 7;
    int oldstate = LOW;
     int count = HIGH;

void setup() {
  pinMode(button, INPUT);
   pinMode(pin2, OUTPUT);
    pinMode(pin7, OUTPUT);
    }

void loop() {
  int buttonstate = digitalRead(button);
//   if (buttonstate == oldstate && buttonstate == HIGH){    
    if (count == 1){
      pattern1();}
     
    if (count == 2){
      pattern2();}
   
    if (count == 3){
     pattern3();}
   
     if (count == 4){
     pattern3();
     pattern2();
     pattern1();}
   
      if (count < 4);
      else
      count = 0;
      count++;
      delay(50);
      }
//     oldstate = buttonstate;
     

void pattern1(){
   digitalWrite(pin7,HIGH);
        delay(400);
         digitalWrite(pin7,LOW);
          delay(400);
           digitalWrite(pin7,HIGH);
            delay(400);
             digitalWrite(pin7,LOW);
              delay(400);
return;
}

void pattern2(){
  digitalWrite(pin2,HIGH);
        delay(400);
         digitalWrite(pin2,LOW);
          delay(400);
           digitalWrite(pin2,HIGH);
            delay(400);
             digitalWrite(pin2,LOW);
              delay(400);
return;
}

void pattern3(){
  digitalWrite(pin2,HIGH);
        delay(200);
          digitalWrite(pin7,HIGH);
          delay(200);
         digitalWrite(pin2,LOW);
          delay(200);
           digitalWrite(pin7,HIGH);
            delay(200);
             digitalWrite(pin7,HIGH);
              delay(200);
return;
}
Thank you very much for this. Very much appreciated.
 

click_here

Joined Sep 22, 2020
545
Another nice little way of approaching this problem is to use an array of function pointers.

Each function in the array is a separate state machine (or just a normal function)

Here is a very generic implementation of this. I have not included a few functions, but it should be easy to work out what they do by their name.

"Please excuse the crudity of this model as I didn't have time to build it to scale or paint it"

Code:
typedef void (*functionPointer)(void);

int main(void) 
{
    functionPointer handleLeds[] = {AllOnOff, RollLeft, RollRight}; // Names of the different functions
    int indexOfHandle = 0;
    int handleLedsLength = sizeof(handleLeds)/sizeof(handleLeds[0]); 
   
    for(;;)  
    {      
        handleLeds[indexOfHandle]();
        Delay1mSec();
        
        if(ButtonPressed())
        {
            // Debounce and wait for button to be unpressed
            Delay20mSec();
            while(ButtonPressed())
            {
                continue;
            }
            
            // Go to next handle
            indexOfHandle = (indexOfHandle + 1) % handleLedsLength;
        }
    } 
         
    return 0; 
}
The advantage of this is that you add a level of abstraction, which makes your code easier to update/maintain
 

Thread Starter

James90s

Joined Mar 3, 2021
31
Another nice little way of approaching this problem is to use an array of function pointers.

Each function in the array is a separate state machine (or just a normal function)

Here is a very generic implementation of this. I have not included a few functions, but it should be easy to work out what they do by their name.

"Please excuse the crudity of this model as I didn't have time to build it to scale or paint it"

Code:
typedef void (*functionPointer)(void);

int main(void)
{
    functionPointer handleLeds[] = {AllOnOff, RollLeft, RollRight}; // Names of the different functions
    int indexOfHandle = 0;
    int handleLedsLength = sizeof(handleLeds)/sizeof(handleLeds[0]);
  
    for(;;) 
    {     
        handleLeds[indexOfHandle]();
        Delay1mSec();
       
        if(ButtonPressed())
        {
            // Debounce and wait for button to be unpressed
            Delay20mSec();
            while(ButtonPressed())
            {
                continue;
            }
           
            // Go to next handle
            indexOfHandle = (indexOfHandle + 1) % handleLedsLength;
        }
    }
        
    return 0;
}
The advantage of this is that you add a level of abstraction, which makes your code easier to update/maintain
Thank you very much for taking the time to do this for me. I very much appreciate all the help. As I find my way through Arduino.
 

click_here

Joined Sep 22, 2020
545
No worries - If you want any further help on anything suggested here, feel free to ask.

Here are two (quickly done) possible solutions to the functions - Remember that it will enter the function approx once a millisecond, so waiting 1000 is one whole second (ish...).

You would usually remove the "magic numbers", but once again, "Please excuse the crudity of this model as I didn't have time to build it to scale or paint it"...

Using a switch statement...
Code:
int AllOnOff(void)
{
    static unsigned int sequenceNumber;
    static unsigned int delayLoops;
    
    switch(sequenceNumber)
    {
        case 0:
            AllOff();
            delayLoops = 0;
            sequenceNumber++;
            
            break;
            
        case 1:
            if(++delayLoops >= 1000)
            {
                sequenceNumber++;
            }
            
            break;
        
        case 2:
            AllOn();
            delayLoops = 0;
            sequenceNumber++;
            
            break;
            
        case 3:
            if(++delayLoops >= 1000)
            {
                sequenceNumber = 0;
            }
            
            break;
            
        default:
            sequenceNumber = 0;
    }
}
Using a once per second fire...
Code:
void RollLeft(void)
{
    static unsigned int lastOutputNumber;
    static unsigned int loopCounter;
    const int numberOfLeds = 8;

    if(++loopCounter == 1000)
    {
        unsigned int currentOutputPin = 1<<lastOutputNumber;
    
        for(int i=0; i<numberOfLeds; i++, currentOutputPin>>=1)
        {
            if(currentOutputPin & 1)
            {
                LedOn(i+1);
            }
            else
            {
                LedOff(i+1);
            }
        }
    
        lastOutputNumber = (lastOutputNumber + 1) % numberOfLeds;
    
        loopCounter = 0;
    }       
}
Sure, the timing won't be spot on, but it will definately be close enough for christmas lights!
 

Thread Starter

James90s

Joined Mar 3, 2021
31
No worries - If you want any further help on anything suggested here, feel free to ask.

Here are two (quickly done) possible solutions to the functions - Remember that it will enter the function approx once a millisecond, so waiting 1000 is one whole second (ish...).

You would usually remove the "magic numbers", but once again, "Please excuse the crudity of this model as I didn't have time to build it to scale or paint it"...

Using a switch statement...
Code:
int AllOnOff(void)
{
    static unsigned int sequenceNumber;
    static unsigned int delayLoops;
   
    switch(sequenceNumber)
    {
        case 0:
            AllOff();
            delayLoops = 0;
            sequenceNumber++;
           
            break;
           
        case 1:
            if(++delayLoops >= 1000)
            {
                sequenceNumber++;
            }
           
            break;
       
        case 2:
            AllOn();
            delayLoops = 0;
            sequenceNumber++;
           
            break;
           
        case 3:
            if(++delayLoops >= 1000)
            {
                sequenceNumber = 0;
            }
           
            break;
           
        default:
            sequenceNumber = 0;
    }
}
Using a once per second fire...
Code:
void RollLeft(void)
{
    static unsigned int lastOutputNumber;
    static unsigned int loopCounter;
    const int numberOfLeds = 8;

    if(++loopCounter == 1000)
    {
        unsigned int currentOutputPin = 1<<lastOutputNumber;
   
        for(int i=0; i<numberOfLeds; i++, currentOutputPin>>=1)
        {
            if(currentOutputPin & 1)
            {
                LedOn(i+1);
            }
            else
            {
                LedOff(i+1);
            }
        }
   
        lastOutputNumber = (lastOutputNumber + 1) % numberOfLeds;
   
        loopCounter = 0;
    }      
}
Sure, the timing won't be spot on, but it will definately be close enough for christmas lights!
Thank you very much again for taking the time to help me. Very much appreciated.
 
Top