Red/yellow/green signal

I am struggling with a sketch which has to do the following:
An infrared sensor is mounted under the track of a model railway.
If it is covered by a passing train it has to switch a signal (which is green in its original state) to yellow and after 2 seconds to red.
Once the sensor is no longer covered it has to switch back to the original state (green).
The one second delay is only to see what is happening,
The sketsch:

#define Red 10
#define Yellow 9
#define Green 8
#define Sensor 7
int val = 0;

void setup() {
  pinMode(Red, OUTPUT);
  pinMode(Yellow, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Sensor, INPUT_PULLUP);

  digitalWrite(Red, LOW);
  digitalWrite(Yellow, LOW);
  digitalWrite(Green, LOW);

}
void loop() {
  digitalWrite(Green, LOW);
  val = digitalRead(Sensor);
  if (val == LOW)
  {
    digitalWrite(Green, LOW);
    digitalWrite(Yellow, HIGH);
    delay(2000);
    digitalWrite(Yellow, LOW);
    digitalWrite(Red, HIGH);
    delay(1000);
  }
 else
  {
    digitalWrite(Red, LOW);
    digitalWrite(Yellow, LOW);
    digitalWrite(Green, HIGH);
  }
}
1 Like

Great, you correctly posted your code. Thank you very much. You cannot image how refreshing it is going to be to not have 30 postings on just how to post the code.

I am struggling as well, and I hope this part does not take 30 postings to get right. What's the problem?

If the sensor has not been triggered then the code for the else will be run and the Green pin will be set HIGH then immediately set LOW again at the start of loop()

Do you want it HIGH or LOW when the sensor is not triggered ?

The problem is that once the sensor is covered the signal goes to yellow and after 2 seconds it goes to red.
However the signal keeps switching between red and yellow with the 2 seconds interval.
I want it to stay on red as long as the sensor is covered.
If the sensor is no longer covered the signal switches back to green as expected.

You need to trigger on the sensor becoming low rather than when it is low. Take a look at the state change detection example in the IDE.

@wildbill,
I already did that but I cannot figure out how to incorporate it into the sketch.

@UKHeliBob,
I want the Green pin set HIGH if the sensor is not covered,

Then don't set it LOW at the start of loop()

That doesn`t matter, it will always become HIGH after the first loop.
That does not change anything in repeatedly changing between Yellow and Red as long as the sensor is covered.

#define Red 10
#define Yellow 9
#define Green 8
#define Sensor 7
int val = 0;
int prevVal=0;

void setup()
{
  pinMode(Red, OUTPUT);
  pinMode(Yellow, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Sensor, INPUT_PULLUP);
  digitalWrite(Red, LOW);
  digitalWrite(Yellow, LOW);
  digitalWrite(Green, LOW);
}

void loop()
{
  digitalWrite(Green, LOW);
  val = digitalRead(Sensor);
  if (val == LOW && prevVal==HIGH)
  {
    digitalWrite(Green, LOW);
    digitalWrite(Yellow, HIGH);
    delay(2000);
    digitalWrite(Yellow, LOW);
    digitalWrite(Red, HIGH);
  }
if(val==HIGH)  
  {
    digitalWrite(Red, LOW);
    digitalWrite(Yellow, LOW);
    digitalWrite(Green, HIGH);
  }
prevVal=val;  
}

@wildbill,

Thanks for this! I will try it tomorrow as I have to leave now.

If the sensor is not triggered it will be set HIGH then immediately be set LOW

@wildbill's code from #9 works, but catches contact bounce when the train leaves the sensor.

I used a pushbutton, perhaps the OP's sensor has clean edges and would work fine.

I placed a commented line in the code where a poor man's debounce delay can be used. Just to be sure that's what was going on.

In the wokwi simulation, you can also add an attribute

"bounce": "0"

to the pushbutton and enjoy perfect simulated do-not-bounce pushbuttons.

a7

It works!
Thanks for your effort.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.