Hi all,
I've had a few inquiries about the Arduino-based system I built to automate my two-track staging yard. It's an extension of the home-built DCC system I made to run my railroad, the details of which are here: http://cs.trains.com/mrr/f/744/t/253905.aspx. I wanted to be able to run a train into staging without having to stick my head behind the backdrop to keep an eye on it.
In this part, I'll be outlining the hardware used and in part two I'll be covering the program logic.
Hardware
The system is driven by a Crowduino, which is essentially an Arduino Duemilanove with a built-in socket for an XBee wireless module. I used XBees when I was building the DCC control system, and had a spare one left over. So I decided to use it.
In the above photo, the XBee can be seen between the Crowduino (red board) and the shield. I usually use a prototyping shield to connect the layout to the Arduinos, as this makes it easy to remove the Arduinos for maintenance.
The XBee is configured with identical settings to the ones in the DCC throttle and base station. This allows for communication between the devices, and this will be covered in the section on software.
These components are mounted in a box on the corner of the layout, next to the staging track. The lid of the box is just screwed shut, so I can easily access inside.
In order to determine if a train is entering staging or not, there are three sets of sensors installed along the staging track. The first is an optical sensor just behind the gap through the backdrop:
Next is a pair of optical sensors, installed at the clearance points of the two diverging tracks:
All three of these optical sensors have LEDs installed above them, to provide a constant level of illumination when a train is not present.
The final sensors are two ultrasonic detection modules, one at the end of each track:
These modules have a 'blind spot' in front of them, and are positioned so that the end of the track is beyond this.
In order to control the turnout and track power, the Arduino drives four relays
I used a bank of eight as that was what I had on hand. I'd bought it for a turntable automation project that didn't get off the ground. Having eight there also provides redundancies, in case any of the relays fail.
Next to the relays is a capacitor discharge unit (CDU). One of the CDU outputs is connected to both coils of the point motor, on the one side. This is the common return. The other output from the CDU is connected to one side of both turnout control relays. Each of these relays is then wired to one of the two switch coils, completing the circuit. This allows the Arduino to set the points, by activating the coil (via the relay) for the required turnout direction.
On top of the turnout motor is an accessory switch. This is wired up to the Arduino, with the common terminal going to one of the pins, one input going to the positive 5v rail and the other going to ground. There are appropriate resistors in place to ensure that the pin doesn't receive too much current. With this in place, the Arduino is able to read the orientation of the turnout off that pin - a high signal is one way, low is the other.
In order to display which trains are in staging and provide some output, I mounted a control panel on the fascia. The main component of this is the four-line, 20-character wide LCD display. Lines one and three of this display show the DCC address of the locomotive in staging tracks one and two respectively, or the word 'empty' if there is no train in that track. The word 'clear' is displayed when the clearance points are not obstructed. The word 'set' is shown next to the track for which the turnout is currently aligned. When there is a train in staging, the second line for each track (line two for track one, line four for track two) shows a bar graph. This indicates how close the train in that track is to the end of the line. This is what it looks like with a train on one of the tracks:
Unfortunately, there's a bit of a programming bug that I haven't quite been able to work out. Instead of starting at an empty bar graph and filling it as the train approaches the end of the siding, the bar graph starts full and empties as the train approaches the end. So it counts down to the end of the siding, rather than counting up.The push button below the screen serves two purposes. If it's pressed once, it will cause the Arduino to throw the points. In order to retain information between sessions, the program saves the DCC address of the loco on each track to the Arduino's memory. As such, I configured this pushbutton to erase this saved data and reboot the Arduino when double-pressed.After the CDU has been used to change the points, it needs to recharge before it can be used again. This is where the LED on the control panel comes into play. I measured how long it took the CDU to recharge after use, and rounded it up to the nearest second. When the points have been thrown, this LED will light up until the CDU charge time has passed.
The Location: Forests of the Pacific Northwest, OregonThe Year: 1948The Scale: On30The Blog: http://bvlcorr.tumblr.com
Very nifty. Sort of what I had been working on for my old layout, with 2 indications per staging track - clear of the turnout and train on the track. I was getting fancy, since I only had room for 2 tracks but they could be very long, I was trying to do serial staging with 2 trains on each track, so I had 2 sets of sensors and 2 sets of indications per track. I sort of had the logic worked out but then I never got much firther - I was doing it with PIC then.
I assume the bar graph is only approximate anyway, unless your trains are all unit trains with the same length cars in every consist. You could make it fancy and put a vertical bar | on each end of the = signs so it's like a brakeman bringing his hands together to indicate distance. Or fill in from the right to the left rather than erase = signs, to show the train filling up the space. I'm thinking your code is somethign like:
<start, no train> bars=20
<each time distance to sensor goes down> bars = bars -1
<display bars on LCD>
You can flip it around a couple of ways, either by using the ability of the LCD library to address a location, which you calculate based on the sensor return, or by using a display string:
<start, no train> dstring = "" (empty string)
as sensor distance goes down, string = (distance) spaces + (20-distance) =
(all this assumes the max is 20). SO as the scaled response from the ultrasonic sensor goes down, the number of blank spaces at the front (left) of the string goes down and the number of = at the right side of the string goes up. Or you could start the emptry track as a single | to indicate the bumping post and add the 20 spaces and = to that. So you'd get somethign that appears on the LCD like this:
| =====
| ==========
| ===============
--Randy
Modeling the Reading Railroad in the 1950's
Visit my web site at www.readingeastpenn.com for construction updates, DCC Info, and more.
Randy,
I'm not sure what you mean by the bar graphs being approximate. The trains go into staging locomotive-first, so the ultrasonic sensors are measuring how far the front of the locomotive is from the end of the track.
With regards to the bumping post idea, I do like the sound of it. However, that would decrease the resolution of the bar graph, as it would have to take up one of the characters used for the graph.
What I mean is that while the bar graph may be proportional to the distance remaining, it doesn't indicate actual cars (unless yoour trains all have cars the same length and you can calibrate it for number of cars). Dropping 1 out of 40 in the resolution isn't that much, and the functionality would be the same, the less space between the train, represented by the = signs, and the bumping post represented by |, the closer you are to hitting it. Just how close when that last space disappears and the display is |===(39 x) depends on your calibration of the ultrasonic sensor in your code. I know they're not super accurate, but depending on your scaling factor in the analog read, that last = could mean 1 more car length, or it could simply mean "stop now" Maybe one and the same if you have momentum on the locos.
That's correct, it doesn't represent the number of cars remaining. It's an indication of how close the locomotive is to the end of staging. Generally, I need to stop when it gets down to about 6 of the = signs remaining.
Car length and train length come into play with the second set of optical sensors. If those are still blocked when the train has stopped, then the clearance point between the two tracks is fouled. In this case, the system will display an indication that this is the case, and will not cut power to the tracks until the train has been moved.
My layout has been designed to accommodate a maximum train length of 100 feet (i.e. 5 x 20-foot freight cars), and the staging tracks are long enough for such a train + my longest locomotive (the 4-4-0).
Well there you go then, losing one of the = signs to have a | sign to represent the bumper at the end won't really impact anything. I was pretty much saying to use the | for the bumper if you reverse the = signs and have them represent the train moving onto the track - so as the distance between the train and the bumper got smaller, the blank space would go down and the = signs would fill in from the other side. Like I drew in my first response. Top to bottom, would be the train moving in. Still with the secondary sensor to indicate the clearance point. Same as before, just slightly different graphical representation - when you get down to 4-5 spaces between the | and the left most =, and the clearance indicatore is saying you are clear of the turnout, you can stop.
I only look at the UI this way because to me, an = indicates somethign is there whereas a blank tells me nothing is there. So as more of the train is on the siding, there is less blank space and more 'something' like the =. You can even make your own characters for those displays, but the character resolution is too small to make a decent little train symbol.
And in all my examples I'm assuming the bumper is to the left and the turnout to the right, so as the train backs in to the staging track it's moving right to left. If your reality is the opposite, that may be causing confusion with my examples.
Just an alternative way of doing the display, with a couple of extra lines of code. Though more critically, it may need some 40 bytes more RAM for variable storage, which, with a mere 1K limit, could be an issue.
My concept for the previous layout wasn't even going to have any sort of graphical indication, just a couple of LEDs for each spot and 3 sensors. One right by the bumper, the "stop NOW or else!, one for "you're close (couple of car lengths)" and one at the clearance point on the other end.
My staging plan for the new layout is mostly concentric loop tracks for staging. The basic form of the layout is a double deck dogbone, one loop on the lower lve, then the shank of the bone traverses the lower level, climbs the helix, traverses the upper level, and then arrives in the upper loop end. Around the outside of these loops will be the staging tracks. Some form of indication will be needed as the loops and staging will be in a seperate room and not visible to operators. My other idea to go with that would be to have the computer drive the next train to a visible sport for the actual crew to 'board'.
In fact I threw a small kit of parts like the IR emitter/detector pair used in Steve's Arduino Speedometer and the ultrasonic module like yours, along with one of my Nanos and a breadboard in my bag to take on my business trip coming up as something to do after hours in my hotel room. For driving trips I usually take my toolbox and some model kits, but for flying - a little box of Arduino parts fits in my luggage quite nicely.