So I am very happy with arduino so far. My intention is to automate parts of the Lego layout that we create for events. I managed a lot o small projects with the arduino, and even manged to use extra libraries and control my layout with IR leds.
Issue I have now is the following.
I have a small loop where a train is running. It has 2 ir beams, where in between a rail crossing should. In another area also a light sensor is there.
Light sensor is supposed to stop the train to wait at a station (not implemented yet)
IR beams are supposed to blink LEDs and close/open a bar that blocks the road.
I build this setup using state machines. I build a part of my own code, and borrowed parts I found on the internet
What should happen is:
- train runs
- ir beam west or east is blocked -> blink LEDs (etcetera)
- if both ir beams are blocked also blink LEDs
- if both are unblocked -> blinking should stop (after a small time)
Currently I can have the LEDs blink, but I cannot get it to stop blinking again.
Sketch (copied below) will not stop blinking
State that trigegrs the blinking is " case crossingOccupied:"
Can somebody look at my code and tell me what I am doing wrong?
/*
Sketch to let 9V train run with L298N motor and :
- stop at light sensor
- let leds blink between ir sensor 1 and 2
*/
//Pins
const int IN1=24; //Connects to IN1 on L298N
const int IN2=26; //Connects to IN2 on L298N
const int ENA=7; //PWN motor switch
const int irsensorPIN_01 = 3; //IR sensor pin that detects (un)broken east
const int irsensorPIN_02 = 4; //IR sensor pin that detects (un)broken west
const int LDR = A0; //Pin connecting to Light sensor
const int LED_RIGHT = 9; //LED red right
const int LED_LEFT = 10; //LED red left
//Variables
int LDRValue=0; //LDR value used to write to serial monitor
int LDRValNow; //Variable to save light sensor value
unsigned long previousMillis=0; //Save time to prevent object blocking the sensor
int sensorState_01 = 0; // variable for reading the ir sensor 01 status
int sensorState_02 = 0; // variable for reading the ir sensor 02 status
//Settings
const int lightSensitivity=500; //Set switching point for light sensor (LDR)
int interval=5000; //Pause period
const int numberBlinks = 5; //Minimum number of blinks
//Possible states of the state machine
const byte CHECK_IRBEAM = 0; //Check if Beams are broken
const byte crossingOccupied = 1; //Blink LEDs if train is within 2 IR beams
const byte CHECK_LDR = 2; //Check if light sensor is blocked
const byte TRAIN_GO = 3; //Let train move
const byte eastBoundApproach = 4; //Train comes in from east
const byte westBoundApproach = 5; //Train comes in from west
const byte approachCommon = 6; //Generic stuff to set
byte state = TRAIN_GO; //Default state
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); //Write to log
pinMode(IN1,OUTPUT); //Motor pin 1
pinMode(IN2,OUTPUT); //Motor pin 2
pinMode(LED_RIGHT, OUTPUT); //Write to red led on the right
pinMode(LED_LEFT, OUTPUT); //Write to red led on the left
// initialize the sensor 01 pin as an input:
pinMode(irsensorPIN_01, INPUT);
digitalWrite(irsensorPIN_01, HIGH); // turn on the pullup
// initialize the sensor 02 pin as an input:
pinMode(irsensorPIN_02, INPUT);
digitalWrite(irsensorPIN_02, HIGH); // turn on the pullup
//Set fixed train direction which is stopped
digitalWrite(IN1,LOW);
digitalWrite(IN2,LOW);
}
void loop() {
// put your main code here, to run repeatedly:
switch(state) {
case TRAIN_GO: //Let train move
if(millis() - previousMillis > interval){ //Time to start train
// digitalWrite(IN2, LOW); //This sketch goes only one direction
// digitalWrite(IN2, HIGH); //This sketch goes only one direction
// analogWrite(ENA,80); //Motor speed
previousMillis=millis(); //Save the time
state = CHECK_IRBEAM;
}
break;
case CHECK_IRBEAM: //Check if Beams are broken
if(millis() - previousMillis > interval){
sensorState_01 = digitalRead(irsensorPIN_01); //reads ir sensor 01 value
sensorState_02 = digitalRead(irsensorPIN_02); //reads ir sensor 02 value
// check if the sensor beam is broken, sensorstate is LOW
if (sensorState_01 == LOW && sensorState_02 == HIGH) {
state = eastBoundApproach; } //Sensor 01 is broken
else if (sensorState_01 == HIGH && sensorState_02 == LOW) {
state = westBoundApproach; } //Sensor 02 is broken
}
break;
case eastBoundApproach: //Train comes from east
state = approachCommon;
break;
case westBoundApproach: //Train comes from west
state = approachCommon;
break;
case approachCommon:
interval = 5000;
state = crossingOccupied;
break;
case crossingOccupied: //Close bars and blink leds
animateLEDs();
//do other stuff
// Hang out in occupied state until both detectors are showing clear
if ((digitalRead(irsensorPIN_01) == HIGH) && (digitalRead(irsensorPIN_02) == HIGH)) {
interval--;
if (!interval) {
turnOffLEDs();
state = TRAIN_GO;
}
} else {
interval = 5000;
}
break;
default:
break;
}
}
////////////////////////////////////////////////////////
// LED Animation Routines
////////////////////////////////////////////////////////
enum {
kLEDsOff = 0,
kLEDLeftOn,
kLEDRightOn
};
int ledState = kLEDsOff;
int ledTimer = 0;
void turnOffLEDs(void) {
digitalWrite(LED_RIGHT,HIGH);
digitalWrite(LED_LEFT,HIGH);
ledState = kLEDsOff;
}
void animateLEDs(void) {
if (ledTimer) ledTimer--;
switch (ledState) {
case kLEDsOff:
ledTimer = 0;
// fall through
case kLEDRightOn:
if (!ledTimer) {
ledState = kLEDLeftOn; ledTimer = 10000;
digitalWrite(LED_LEFT,LOW);
digitalWrite(LED_RIGHT,HIGH);
}
break;
case kLEDLeftOn:
if (!ledTimer) {
ledState = kLEDRightOn; ledTimer = 10000;
digitalWrite(LED_LEFT,HIGH);
digitalWrite(LED_RIGHT,LOW);
}
break;
}
}