Rafael
Rafael

Reputation: 25

How can I optimize this code so that it pauses the main function that is looping?

So I have this traffic light code that I made for Arduino, but I am having trouble trying to make it efficient as possible. I am only going to show the parts I am trying to optimize so the code won't be so cluttered.

const int redLedPin=5;
const int yellowLedPin=6;
const int greenLedPin=4;
const int redLedPin1=10;
const int yellowLedPin1=9;
const int greenLedPin1=8;
const int blueLed=11;
const int button=3;
const int button2=2;
volatile int num = 0;
volatile int val = 0;
void setup() {

  pinMode(redLedPin, OUTPUT);
  pinMode(yellowLedPin , OUTPUT);
  pinMode(greenLedPin, OUTPUT);
  pinMode(redLedPin1, OUTPUT);
  pinMode(yellowLedPin1 , OUTPUT);
  pinMode(greenLedPin1, OUTPUT);
  pinMode(blueLed,OUTPUT);
  pinMode(button,INPUT_PULLUP);
  pinMode(button,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(button2), blink1, RISING);
  attachInterrupt(digitalPinToInterrupt(button), cycle, RISING);
}



 void loop() {
  //runs when the button is pressed then ends after the while loop is 
  //executed once and resets the value of the button
  while(val==1){
    digitalWrite(greenLedPin, HIGH);
    digitalWrite(redLedPin1,HIGH);
    digitalWrite(redLedPin,LOW);
    digitalWrite(blueLed,HIGH);
    delay(4000); 
    digitalWrite(greenLedPin, LOW);
    digitalWrite(redLedPin, HIGH);
   for(int i=0; i<=4;i++)
   {
      digitalWrite(blueLed,LOW);
      delay(500);
      digitalWrite(blueLed,HIGH);
      delay(500);
   }
    for(int i=0; i<=9;i++)
    {
      digitalWrite(blueLed,HIGH);
      delay(100);
      digitalWrite(blueLed,LOW);
      delay(100);
    }
    digitalWrite(blueLed,HIGH);
    delay(1000);
    digitalWrite(blueLed,LOW);
    val=!val;
  }
  //blinks three leds repeatedly till the button is pressed again
  if(num){
    digitalWrite(redLedPin, HIGH);
    digitalWrite(yellowLedPin1,HIGH);
    digitalWrite(blueLed, HIGH);
    digitalWrite(redLedPin1, LOW);
    delay(500);
    digitalWrite(redLedPin, LOW);
    digitalWrite(yellowLedPin1, LOW);
    digitalWrite(blueLed,LOW);
    delay(500);}
      else{
        changeLights();
      }

}

// the main function that gets repeated throughout the code
void changeLights() {
digitalWrite(greenLedPin, HIGH);
digitalWrite(redLedPin1,HIGH);
digitalWrite(redLedPin,LOW);
delay(4000); 
digitalWrite(yellowLedPin, HIGH);
digitalWrite(redLedPin1,HIGH);
digitalWrite(greenLedPin, LOW);
delay(2000); 
digitalWrite(yellowLedPin, LOW);
digitalWrite(redLedPin, HIGH); 
delay(2000);
digitalWrite(greenLedPin1, HIGH);
digitalWrite(redLedPin1,LOW);
delay(4000); 
digitalWrite(greenLedPin1, LOW);
digitalWrite(yellowLedPin1, HIGH); 
delay(2000);
digitalWrite(redLedPin,HIGH);
digitalWrite(redLedPin1,HIGH);
digitalWrite(yellowLedPin1,LOW);
delay(2000);
}
void blink1()
{

num=!num;

}

void cycle()
{

 val=!val;
}

So I am using buttons to make some loops execute then it returns to the changeLights() function. What I want to do is make it so everytime I press one of the buttons it stops the changeLights() function wherever it is at and execute the buttons code. So how would optimize so it doesnt have to wait till the end of the loop to execute one of the buttons code. Sorry if I am causing trouble I just really want to make the code flow better.

Upvotes: 1

Views: 77

Answers (1)

linzwatt
linzwatt

Reputation: 117

Instead of using delay(ms) which blocks (does not return until the time is up), you could re-structure your code to use a non-blocking method to wait a certain amount of time. By using the millis() function, you can get number of milliseconds since the Arduino was reset, and therefore measure how much time has passed between successive calls.

So if you do something like this, the do_things() function will be called every 1000ms. (Adapted from this example)

unsigned long prev_millis, curr_millis, interval = 1000;

void loop() {
    curr_millis = millis();
    if ((curr_millis - prev_millis) > interval) {
        do_things();
    }
}

I would suggest re-structuring your code to something like this rough example

unsigned long prev_millis, curr_millis, interval;
int state, next;

void loop() {
    switch (state) {
        case 0:
            <set LEDs to certain state here>
            interval = 4000; // wait 4s before changing state
            next = 1;
            break;
        case 1:
            <set LEDs to another state here>
            interval = 500; // wait 0.5s before changing state
            next = 2;
            break;
        case 2:
            <set LEDs to yet another state here>
            interval = 100; // wait 0.1s before changing state
            next = 0; // loop back to start
            break;

        <add more states here for button sequences>
    }

    curr_millis = millis();
    if ((curr_millis - prev_millis) > interval) {
        state = next;
    }

    // check if buttons were pressed
    if (num) {
        state = 3; // state 3 is where the button1 sequence starts
    }
    if (val) {
        state = 7; // state 7 is where the button2 sequence starts
    }
}

Using this type of structure, state 3 could start a sequence 3-4-5-6 and in state 6 next gets set to 0, and the 0-1-2 sequence happens continuously until a button is pressed. And state 7 could start a sequence 7-8-9-7-8-9... that repeats continuously until the button is pressed again (you would need to set state back to 0).

Hope this helps :D

Upvotes: 1

Related Questions