# Model railway Arduino control

I'm helping my dad build a model railway and unfortunately he doesn't have the space to build a full oval for his trains to run around, so we've built a u-shaped track for them to run end to end. I figured out a way to stop and reverse the trains automatically using a couple of relays and I've wrote a simple arduino code to control it with timing delays. This works fine but it's not the most accurate thing and its difficult to set it up so that they start and stop from the same positions. I have a couple of the HC-SR04 sensors and was wondering if anyone had any suggestions for using two of these to start and reverse the trains from either end in the same way. I've programmed a single sensor before but I'm unsure how to incorporate multiple sensors in order to change outputs like that.

My timing code:

int relayPin1 = 8;
int relayPin2 = 7;
int relayPin3 = 6;
int relayPin4 = 5;

void setup() {
// put your setup code here, to run once:
pinMode(relayPin1, OUTPUT);
pinMode(relayPin2, OUTPUT);
pinMode(relayPin3, OUTPUT);
pinMode(relayPin4, OUTPUT);
}

void loop() {
// put your main code here, to run repeatedly:

digitalWrite(relayPin1, LOW);
digitalWrite(relayPin2, LOW);
digitalWrite(relayPin3, LOW);
digitalWrite(relayPin4, LOW);
delay(2000);
digitalWrite(relayPin4, HIGH); //direction relays changed
digitalWrite(relayPin3, HIGH);
delay(2000);
digitalWrite(relayPin1, HIGH); //power relays set, train moves forward
digitalWrite(relayPin2, HIGH);
delay(10000);
digitalWrite(relayPin1, LOW); //power relays reset, train stops
digitalWrite(relayPin2, LOW);
delay(2000);
digitalWrite(relayPin3, LOW); //direction relays changed
digitalWrite(relayPin4, LOW);
delay(2000);
digitalWrite(relayPin1, HIGH); //power relays set train moves in reverse
digitalWrite(relayPin2, HIGH);
delay(10000);
digitalWrite(relayPin1, LOW); //power relays reset train stops
digitalWrite(relayPin2, LOW);

}


I'd suggest using a State Machine approach - it's a very powerful technique you'll benefit from learning. Although this is a fairly simple problem and can be solved relatively easily without it, it starts to get very messy and hard to understand and maintain, especially if you want to extend it to control other parts of the railway.

In this case, implement a variable that represents four states:

• Running left to right
• Waiting at right end
• Running right to left
• Waiting at left end

In the first state, you keep looking for the right hand sensor to become active. When it does, stop the train and go into the next state. In that state, wait for the desired time limit to expire, start the train in the opposite direction and go into the next state, and so on.

It's easy to see how you can extend this approach to solve far more complex problems.

In terms of coding, the easiest way is normally to use the state variable in a switch/case statement inside your loop to execute the appropriate section of code depending on the current state. And don't forget to carry out appropriate initialisation before starting the loop.

• Well from doing some research on state machines, that's probably the best solution I've seen so far. However I don't know if I have the time to learn something as complex as that, I think the simplest solution I can come up with would be more than sufficient and if I have more free time in the future I can always come back to it to replace the program with a state machine code. Thanks for bringing that to my attention though. – Joe Eason Feb 14 at 16:23

In setup get the train started. Ideally by first checking the sensors to see if a train happens to be at either end and then set it to go the other way. If no train is present direction doesn't matter.

Then in the loop check the sensors. If either of them trigger then stop the train, switch direction and get the train moving again in the other direction.

The loop should have a short delay, e.g. 0.01s so trains don't overshoot. But after changing directions you might want to sleep for 1s so the train can clear the sensor.

• In this configuration would you use a bool output to disable one sensor while the train is travelling towards the other? I've tried to get both sensors working at the same time but I only seem to get one set of measurements. I don't know if there is a conflict between the I/Os of the sensors when using two together? – Joe Eason Feb 14 at 16:37
• No, I would check both sensors. At start you don't even know where the train is and you have to check both anyway. Show us your setup and code for the sensors as that seems to be your problem. – Goswin von Brederlow Feb 15 at 16:25

Again thanks for the help guys. But I finally figured out a decent way to program the sensors how I needed them. I found an instructable for one of the little obstruction detecting, motor reversing car/ robots people like to build with the HC-SR04 sensors. I think I was overthinking how complicated it needed to be. But I have now managed to get a train to stop and reverse on my test track. I'll post a link to the instructable I modified to sort it out: https://www.instructables.com/id/Multiple-Ultrasonic-Range-Sensors-as-Motor-Control/