I definitely need a state machine. I'm trying to follow Robin's logic, and it seems to turn off the Green train as soon as a Red train is detected, and vice versa, rather than waiting for the second sensor to be blocked. I'm trying to include a "trainPresent" boolean, but I'm not sure how it would work.
This is the current Finite State Machine. I know it's cleaner to break it up into separate voids, but I want to get it working rudimentarily first.
/* this program examines two light sensors.
When either light sensor is triggered, it deactivates
the LEDs based on the state table.
*/
//the analog pins used for each sensor
const byte RED_TRAIN_SENSOR = 0; //Red train
const byte GREEN_TRAIN_SENSOR = 1; //Green train
//possible states of the state machine
const byte TRACK_SECTION_CLEAR = 0; //both light sensors off, power to both trains
const byte RED_TRAIN_DETECTED = 1; //Red train detected, power to both trains
const byte GREEN_TRAIN_DETECTED = 2; //Green train detected, power to both trains
const byte RED_TRAIN_OFF = 3; //Both trains detected (Green first), turn off Red train
const byte GREEN_TRAIN_OFF = 4; //Both trains detected (Red first), turn off Green train
byte state = TRACK_SECTION_CLEAR;
//variables
boolean TrainPresent = false;
unsigned long previousMillis = 0;
int RedTrainSensorValue = 0;
int GreenTrainSensorValue = 0;
int light_sensitivity = 500;
int interval = 5000;
//the digital pins for the LEDs
const byte RED_LIGHT = 40; //power to Red train
const byte GREEN_LIGHT = 26; //power to Green train
void setup() {
//enable output on the digital pins
pinMode(RED_LIGHT, OUTPUT);
pinMode(GREEN_LIGHT, OUTPUT);
//turn on LEDs
digitalWrite(RED_LIGHT, HIGH);
digitalWrite(GREEN_LIGHT, HIGH);
Serial.begin(9600); //configure serial communication
}
void loop() {
switch(state)
{
case TRACK_SECTION_CLEAR: //both light sensors off, power to both trains
{
RedTrainSensorValue = analogRead(RED_TRAIN_SENSOR);
GreenTrainSensorValue = analogRead(GREEN_TRAIN_SENSOR);
digitalWrite(RED_LIGHT, HIGH);
digitalWrite(GREEN_LIGHT, HIGH);
if (GreenTrainSensorValue > light_sensitivity) {
previousMillis = millis(); //save the time
TrainPresent = true;
state = GREEN_TRAIN_DETECTED;
}
if (RedTrainSensorValue > light_sensitivity) {
previousMillis = millis(); //save the time
TrainPresent = true;
state = RED_TRAIN_DETECTED;
}
}
break;
case RED_TRAIN_DETECTED: //Red train detected, power to both trains
{
GreenTrainSensorValue = analogRead(GREEN_TRAIN_SENSOR);
if (GreenTrainSensorValue > light_sensitivity) {
state = GREEN_TRAIN_OFF;
}
else if(millis() - previousMillis > interval){
TrainPresent = false;
state = TRACK_SECTION_CLEAR;
}
}
break;
case GREEN_TRAIN_DETECTED: //Green train detected, power to both trains
{
RedTrainSensorValue = analogRead(RED_TRAIN_SENSOR);
if (RedTrainSensorValue > light_sensitivity) {
state = RED_TRAIN_OFF;
}
else if(millis() - previousMillis > interval){
TrainPresent = false;
state = TRACK_SECTION_CLEAR;
}
}
break;
case RED_TRAIN_OFF: //Both trains detected (Green first), turn off Red train
{
if(millis() - previousMillis < interval){
digitalWrite(RED_LIGHT, LOW);
}
else {
state = TRACK_SECTION_CLEAR;
}
}
break;
case GREEN_TRAIN_OFF: //Both trains detected (Red first), turn off Green train
{
if(millis() - previousMillis < interval){
digitalWrite(GREEN_LIGHT, LOW);
}
else {
state = TRACK_SECTION_CLEAR;
}
}
break;
}
}
RESULTS:
Block Sensor0 - nothing happens (good).
Block Sensor 0, then Sensor1 - GreenLED turns off (good). It turns back on if Sensor0 is blocked or unblocked (good). It turns back on after 5 seconds whether Sensor1 is blocked or unblocked (good). If Sensor1 is blocked after 5 seconds, RedLED turns off (bad).
Block Sensor1 - RedLED turns off (bad). It stays off for 5 seconds regardless of Sensor1 state (strange).
Block Sensor 1, then Sensor0 - RedLED off, GreenLED on (bad). If sensors stay blocked for 5 seconds, GreenLED turns off and RedLED turns on (strange).
So it seems the Finite State Machine SORT of works, in the sense that both LEDS are responding to both sensors. But I'm completely confused about how to fix the results.