Teach me what I'm doing wrong (again)

Hey all,

You guys helped me cross the finish line with one of the arduino lessons I was trying to expand on in the last topic I posted, hopefully you can help again. I have two problems on this one.

The Setup:

Simulating a traffic light with a CA RGB led, three tactile switches, and a leonardo.

redSwitchPin, LOW fires a green light, followed by yellow delayed, and then solid red.

greenSwitchPin, LOW is supposed to turn the solid red to greenLEDPin, LOW - Not working for some reason, the code looks good but im not sure what im doing wrong that the greenSwitchPin does nothing when pressed.

failSwitchPin, LOW is supposed to simulate when a traffic light has failed and the red light just blinks. This works but a nested loop needs to be added to run indefinitely until another event (switch press) has occurred.

I researched nested loops and found some info on forLoop and While commands but not really sure how to implement them to create an indefinite loop within a loop until a switch command stops it.

And then of course the second problem why the greenSwitchPin commands are being completely ignored in the code.

Here is the code

int redLEDPin = 11;
int greenLEDPin = 10;
int blueLEDPin = 9;

int redSwitchPin = 6;
int greenSwitchPin = 5;
int failSwitchPin = 3;

void setup()
{
pinMode(redLEDPin, OUTPUT);
pinMode(greenLEDPin, OUTPUT);
pinMode(blueLEDPin, OUTPUT);
pinMode(redSwitchPin, INPUT_PULLUP);
pinMode(greenSwitchPin, INPUT_PULLUP);
pinMode(failSwitchPin, INPUT_PULLUP);
digitalWrite (redLEDPin, LOW);
digitalWrite (greenLEDPin, HIGH);
digitalWrite (blueLEDPin, HIGH);
}
void loop()
{
if (digitalRead(redSwitchPin) == LOW)
{
digitalWrite (blueLEDPin, HIGH);
digitalWrite (redLEDPin, HIGH);
digitalWrite (greenLEDPin, LOW);
delay (3000);
digitalWrite (redLEDPin, LOW);
delay (3000);
digitalWrite (greenLEDPin, HIGH);
}
if (digitalRead(greenLEDPin) == LOW)
{
digitalWrite (blueLEDPin, HIGH);
digitalWrite (redLEDPin, HIGH);
digitalWrite (greenLEDPin, LOW);
}
if (digitalRead(failSwitchPin) == LOW)
{
digitalWrite (blueLEDPin, HIGH);
digitalWrite (redLEDPin, LOW);
delay (2000);
digitalWrite (redLEDPin, HIGH);
delay (2000);
}
}

Any input would be awesomeness on your part,

Just trying to learn,

Mike

if (digitalRead(greenLEDPin) == LOW)

Did you mean to read the switch pin here?

Yes I did, damn, I looked over that 10 times and missed it, well that solves that problem. Now i just need to figure out the nested loop

Updated code since AWOL showed me the error of my ways

int redLEDPin = 11;
int greenLEDPin = 10;
int blueLEDPin = 9;

int redSwitchPin = 6;
int greenSwitchPin = 5;
int failSwitchPin = 3;

void setup()
{
pinMode(redLEDPin, OUTPUT);
pinMode(greenLEDPin, OUTPUT);
pinMode(blueLEDPin, OUTPUT);
pinMode(redSwitchPin, INPUT_PULLUP);
pinMode(greenSwitchPin, INPUT_PULLUP);
pinMode(failSwitchPin, INPUT_PULLUP);
digitalWrite (redLEDPin, LOW);
digitalWrite (greenLEDPin, HIGH);
digitalWrite (blueLEDPin, HIGH);
}
void loop()
{
if (digitalRead(redSwitchPin) == LOW)
{
digitalWrite (blueLEDPin, HIGH);
digitalWrite (redLEDPin, HIGH);
digitalWrite (greenLEDPin, LOW);
delay (3000);
digitalWrite (redLEDPin, LOW);
delay (3000);
digitalWrite (greenLEDPin, HIGH);
}
if (digitalRead(greenSwitchPin) == LOW)
{
digitalWrite (blueLEDPin, HIGH);
digitalWrite (redLEDPin, HIGH);
digitalWrite (greenLEDPin, LOW);
}
if (digitalRead(failSwitchPin) == LOW)
{
digitalWrite (blueLEDPin, HIGH);
digitalWrite (greenLEDPin, HIGH);
digitalWrite (redLEDPin, LOW);
delay (2000);
digitalWrite (redLEDPin, HIGH);
delay (2000);
}

Another error of your ways AWOL can help you with is to ask you to use code tags when posting code.

I missed that too.

Suggestion: to troubleshoot stuff like this, especially where there are branches like with your ifs, use Serial.prints liberally to show on the monitor where the logic has taken you. See below…

int redLEDPin = 11;
int greenLEDPin = 10;
int blueLEDPin = 9;

int redSwitchPin = 6;
int greenSwitchPin = 5;
int failSwitchPin = 3;

void setup()
{
 Serial.begin(9600); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Serial.println("In setup";  //<<<<<<<<<<<<<<<<<<<<<<<
  pinMode(redLEDPin, OUTPUT);
  pinMode(greenLEDPin, OUTPUT);
  pinMode(blueLEDPin, OUTPUT);
  pinMode(redSwitchPin, INPUT_PULLUP);
  pinMode(greenSwitchPin, INPUT_PULLUP);
  pinMode(failSwitchPin, INPUT_PULLUP);
  digitalWrite (redLEDPin, LOW);
  digitalWrite (greenLEDPin, HIGH);
  digitalWrite (blueLEDPin, HIGH);
}
void loop()
{
  if (digitalRead(redSwitchPin) == LOW)
  {
Serial.println("In redswitchpinif";  //<<<<<<<<<<<<<<<<<<<<<<<
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (redLEDPin, HIGH);
    digitalWrite (greenLEDPin, LOW);
    delay (3000);
    digitalWrite (redLEDPin, LOW);
    delay (3000);
    digitalWrite (greenLEDPin, HIGH);
  }
  if (digitalRead(greenLEDPin) == LOW)
  {
Serial.println("In greenswitchpinif";  //<<<<<<<<<<<<<<<<<<<<<<<
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (redLEDPin, HIGH);
    digitalWrite (greenLEDPin, LOW);
  }
  if (digitalRead(failSwitchPin) == LOW)
  {
Serial.println("In failswitchpinif";  //<<<<<<<<<<<<<<<<<<<<<<<
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (redLEDPin, LOW);
    delay (2000);
    digitalWrite (redLEDPin, HIGH);
    delay (2000);
  }
}

And please use code tags…

Another stupid question on my part, code tag? 30 years old and this is the first forum iv’e joined. Learning the rules.

mgttrottier:
Another stupid question on my part, code tag?

Read the how to use this forum sticky post, which we do our best to hide having it at the top of every section on this forum.

Code tags, got it! Any insight into the nested loop problem?

Code tags, got it! Any insight into the nested loop problem?

Perhaps I missed it, but I don't actually see a "nested loop" there. Perhaps your understanding of this phrase is different to mine.

It appears that your code will only work, if only one of your inputs can be active at a time.

There isn’t a nested loop in there right now. Essentially what I want the code to do is to continually repeat this code

 if (digitalRead(failSwitchPin) == LOW)
  {
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (greenLEDPin, HIGH);
    digitalWrite (redLEDPin, LOW);
    delay (2000);
    digitalWrite (redLEDPin, HIGH);
    delay (2000);

until one of the other buttons interrupts that code

Ive been researching and playing around with

for(int i = 0; i < 5; i++)

but can’t seem to get it in the right place or maybe i’m not using it correctly, so the code wont compile.

I’m really trying here, its just very frustrating.

here is the entire code

int redLEDPin = 11;
int greenLEDPin = 10;
int blueLEDPin = 9;

int redSwitchPin = 6;
int greenSwitchPin = 5;
int failSwitchPin = 3;

void setup()
{
  pinMode(redLEDPin, OUTPUT);
  pinMode(greenLEDPin, OUTPUT);
  pinMode(blueLEDPin, OUTPUT);
  pinMode(redSwitchPin, INPUT_PULLUP);
  pinMode(greenSwitchPin, INPUT_PULLUP);
  pinMode(failSwitchPin, INPUT_PULLUP);
  digitalWrite (redLEDPin, LOW);
  digitalWrite (greenLEDPin, HIGH);
  digitalWrite (blueLEDPin, HIGH);
}
void loop()
{
  if (digitalRead(redSwitchPin) == LOW)
  {
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (redLEDPin, HIGH);
    digitalWrite (greenLEDPin, LOW);
    delay (3000);
    digitalWrite (redLEDPin, LOW);
    delay (3000);
    digitalWrite (greenLEDPin, HIGH);
  }
  if (digitalRead(greenSwitchPin) == LOW)
  {
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (redLEDPin, HIGH);
    digitalWrite (greenLEDPin, LOW);
  }
  if (digitalRead(failSwitchPin) == LOW)
  {
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (greenLEDPin, HIGH);
    digitalWrite (redLEDPin, LOW);
    delay (2000);
    digitalWrite (redLEDPin, HIGH);
    delay (2000);
  }
}

I did figure out how to get the loop in the code in this part

 }
  if (digitalRead(failSwitchPin) == LOW)
  for(int i = 0; i < 5; i++) //loops command inside of a loop but only five times
  {
    digitalWrite (blueLEDPin, HIGH);
    digitalWrite (greenLEDPin, HIGH);
    digitalWrite (redLEDPin, LOW);
    delay (1000);
    digitalWrite (redLEDPin, HIGH);
    delay (1000);
  }

But as its written it only cycles 5 times, not indefinitely until interrupted by button press. Any insight into the code change?

Mike

Essentially what I want the code to do is to continually repeat this code

I just saw your latest post and see that it is the flashing LEDs that you want to repeat. The for loop will do that but will extend the delay time by 5 so the program will become unresponsive for longer. If you want to have the LEDs flash continuously until interrupted by an input then look at using the timing principle used in the BlinkWithoutDelay example in the IDE.

Save a start time and check frequently whether the required time period has elapsed. If so then do whatever is required next. If not then do something else such as reading an input and reacting to it. At any point in time your program will be in a known state so the BWD principle lends itself well to being used as part of a Finite State Machine, which sound scary but isn't.

When the timing period finishes or input is detected change a state variable to a new value. Then in loop() use if statements or switch/case to execute the required commands for that state. Start by writing out all the states on paper, the conditions needed to exit each state and the state number to move to on exit. The program then almost writes itself.

UKHeliBob:
Save a start time and check frequently whether the required time period has elapsed.

Excellent advise! I havn't looked at the blinkwithoutdelay set. Is it possible to set an indefinite period of time in which the loop will run with that sketch so the original program doesn't go unresponsive? (leaving an exit from the loop when the redSwitchPin or greenSwitchPin is pressed)

Using a FSM the system stays in a state until it is changed either by time elapsing of by an input changing. So, yes, you can have the system stay in a state for an indefinite period of time by not using elapsed time as an exit condition for the state.

Here is some psuedo code to illustrate the principle. It aims to wait with an LED off until a button is pressed then to blink the LED until the button is pressed again. It can of course be extended to do other things and have more states.

state = 0
start of loop()
  switch state
    case 0
      wait for a button press
      if button A becomes pressed 
        state = 10
        save start time
        turn on LED A
      end if
      
      case 10
        if period has elapsed 
          state = 11
          save start time
          turn off LED A
        end if
        
        if button A becomes pressed
          turn off LED A
          state = 0
        end if
        
        case 11
        if period has elapsed 
          state = 10
          save start time
          turn on LED A
        end if
        
        if button A becomes pressed
          state = 0
        end if
        
  end switch
end of loop()

It is, of course, not real code but should show you the shape of what you are aiming for.

Here's some light reading on state machines.....

Wikipedia http://en.wikipedia.org/wiki/Finite-state_machine
Robert C Martin Vacation Rental Hacks
Nick Gammon Gammon Forum : Electronics : Microprocessors : State machines
Grumpy Mike State Machine