The first thing I do is prepare the servo by setting the position of the shaft to 90 degrees, the midpoint of its 180 degree total travel. I do this by attaching the servo to an Arduino Uno and uploading this little sketch once to set the servo (for those who don’t know, “//” signifies the start of a comment ):

#include <Servo.h> // compiler directive to get the servo library
Servo myservo; // create a servo object
// from here on use the variable "myservo" to
// access and control the servo object
void setup() // the setup function is run once at boot
{
myservo.attach(9); // attaches to the servo on pin 9
myservo.write(90); // set the servo shaft at 90 degrees
}
// the loop function runs after setup until the board is powered off
void loop()
{
// do nothing
}

Here is the basic circuit for controlling a servo with an Arduino Uno, where the servo draws power from the Arduino. Servos can be independently powered, in which case only the signal wire and ground are connected to the Arduino.

Basic Arduino/servo circuit (from www.arduino.cc).

The Arduino can Source a maximum of 200 mA current, and can Sink a maximum of 400 mA current. As you connect and try to run more devices, you’ll get to those limits quickly. In Model Railroad applications, given that we’re already routing track power, routing a few amps of +5 volt power to supply actuators like servos is a no-brainer for performance and system integrity. Whenever you use a separate power supply, the servo ground has to connect to both the power supply ground and the Arduino ground.

I fabricate a simple mounting bracket with a small plywood plate and a couple of blocks. Now I mount the servo in the bracket, place the horn onto the shaft in the position shown and then screw it down to the shaft.

Micro Servo with shaft/horn set to 90 degrees

Using a 1/16″ bit, I drill out a hole in the horn (usually the second hole from the end of the horn) and a hole in the turnout actuator bar. Don’t over ream the holes; the soft, slightly flexible plastic will provide a snug fit so you don’t have to use adhesives. Then, I slide a piece of 1/16″ brass rod through the horn to establish the location for a hole in the mounting plate.

Establishing the location for the rod hole.

I mark and drill the hole in the base plate. I rock the bit along the axis the rod will move (left to right in the view below) to slightly elongate it, and give it a more hour-glass profile. This hole functions as a fulcrum for the rod.

Servo mounting bracket ready for use.

I mount the servo below the turnout. For this demonstration, I used hot glue to mount the bracket to the underside of the demonstration layout segment; screws are a better idea for most situations, allowing you to build in some adjustability. With the turnout set in the straight-through position, I carefully thread the rod through the turnout actuator bar, down through a prepared hole in the layout to the hole in the mounting plate and then the servo horn. The brass rod is perpendicular to the horn at the 90 degree setting. Moving the servo horn tilts the rod, moving the turnout above to its divergent position.

Threading the rod down from the turnout to the servo.

At this point I test the servo and make any adjustments necessary for smooth operation. When I’m satisfied everything is right, I trim the rod to its final size.

I’m planning to try music wire instead brass rod in the near future. The problem with brass rod is that it is stiff, and the servo can get fussy at the end of movement ranges because there is no give. Music wire is like spring wire and should allow me to apply pressure at the ends of movement ranges without overtaxing the servo. I’ll update this page with the results of those tests.

Servo mounted and ready

Servo Control by Button

The button takes power from the +5v board supply and, when the button is pushed, routes the power to a designated pin, putting the pin in a HIGH state. On the output side of the button a pull-down resistor routes stray power to ground to guarantee that the pin is in a LOW state whenever the button is not pushed.

Here is a simple sketch to control a servo and have it move over about 2 seconds every time a button is pressed. The straight position is always 90 degrees because of the way I install the servo. The divergent angle depends on how the servo was installed in relation to the turnout– it will either be a larger angle in the 110 – 120 degree range, or a smaller angle in the 60-70 degree range. With practice and consistent placement of servos, they can all be the same; but if not, storing unique settings for each servo is not difficult.

To control multiple servos with one Arduino, your sketch would need variables for each servo to hold its pin id and unique divergent angle. More advanced programmers will want to create something like an array of data structures to organize pertinent data about the servos.

Now lets put it all together:

NOTE: The delay() function is used a lot in small demonstration sketches to control timing. The problem with delay is that it throws the board into a do-nothing state that prevents anything else from happening. In more complex sketches it is often advisable to avoid delay() and use other methods to meter actions across multiple controller cycles. In this case, be aware that the board is tied up while the servo is in motion.

81 thoughts on “Turnout Control with Arduino & Servos”

I haven’t tried it myself yet (I will in due course as this project proceeds), but there are two ways that I know of. The simplest would be to attach the output of a stationary decoder to a digital input pin on an Arduino, and use the signal on that pin to trigger action. The decoder signal will likely be at full track voltage so you’ll need to protect the pin from excess current with a resistor and/or voltage limiter (unless the decoder supports or allows voltage/current limits on its signal line). Alternatively, using minimal additional circuitry and readily available code, you can turn the Arduino into a stand alone, smart decoder. Check out this project – http://model-railroad-hobbyist.com/node/19446 – where that has been done, turning an Arduino into a 17 function smart decoder.

Hello friend:
I am fond of N Scale model railroading. And I loved your video related to Arduino and control of turnout motors.
My question is this, that’s for moving one, but as it is in my case my model has 40 turnout motors and what I want is to change by servos, as could do. I would love that to your knowledge would help me to establish this system in my N Scale Model Railroading

If you want to stay in touch via email, here I leave my email to comment with more breadth of your knowledge.
many Thanks
regards

You can control as many servos with an Arduino as there are available digital pins. On an UNO like I used here, you have up to 12 digital pins available for servo control. On a Mega 2560, which as many more I/O pins than the UNO, you can control up to 48 servos. If you need digital pins for other uses, that would reduce pins available for servos.

On a large layout, the distance from your Arduino to your servos could become a problem. So on a large layout, or any layout where there are a lot of servos and other things to control, its probably easer to use multiple Arduino boards networked together (using usb, wifi, Ethernet, Xbee or something else). With 40 turnouts to control, I suspect you’d do best taking this approach.

Given the modular design of the L&NC, and the need to limit wiring between modules, I’m going to use the networked board approach. There will probably have to be a main controller board — a Mega in all likelihood — to tie all the pieces together.

Dear Sir
You have sent me off on a quest to find out how to program more than one servo, Without any real success my inability to take the programming examples and apply it to the the case in point. Have you got any clues or starting points that you could help with. Keep up the good work and thank you in advance
Kind Regards
Ron

Ron, Thanks for visiting! If I’m understanding correctly, is sounds like you have been able to control one servo but are having trouble extending that to multiple servos. What I’ll do is assume you have the sketch at the end of post above working, and explain how I would adapt the sketch to multiple servos.

Problem #1: All the variables in use are good for only one servo: “myservo”, “servo_pin” and so on can only refer to one device. We need a way to handle multiple sets of similar data that can be easily manipulated in the sketch.

The optimal solution is to gather all the data elements you need for a servo into a data structure (keyword struct – see playground.arduino.cc/Code/Struct) that can be referenced through a single variable.

I use a structure to hold the three key bits of mechanical data about a turnout and its servo: its pin, its main position in degrees and its divergent position in degrees:

I made the variable name plural deliberately to illustrate the ease of shifting to multiple turnouts and servos. To do that, variable “turnouts” is changed from being a single structure, to an array (www.arduino.cc/en/Reference/Array) of structures. Secondly the “myservo” servo object variable needs to become an array of servo objects.

for(i = 0; i < NUM_TURNOUTS; i++){ // for each turnout
servos[i].attach(turnouts[i].pin);
}
Ok this gets you to the point where you have an array of active servos you can move.
Problem #2: How do you keep track of positions and movement of multiple servos?
One way is to modify the TURNOUT_DEF struct this way, so that you have unique pos and old_pos elements for each turnout:
typedef struct TURNOUT_DEF {
int pin;
int pos_main; //main servo position in degrees
int pos_div; //divergent servo position in degrees
int pos;
int old_pos;
};
Now, you can modify the main loop in the example sketch like this:
for(int i = 0; i < NUMBER_OF_TURNOUTS; i++){
//place button or other command source check here
// assume we've got a buttons array buttons[NUMBER_OF_TURNOUTS]
int button_state = digitalRead(buttons[i]);
if(button_state == HIGH){
turnouts[i].old_pos = pos; // save the current position
// Toggle the position to the opposite value
turnouts[i].pos = turnouts[i].pos == straight ? divergent: straight;
// Move the servo to its new position
if(turnouts[i].old_pos < turnouts[i].pos){
and so on as in the example, adding 'turnouts[i].' to variable references as shown.
This should get you started and enable you to control more than one servo in a basic way. Let me know how you do with this or if you need help.
Be sure to note the limits of the servo library:
arduino.cc/en/Reference/Servo
There is one major flaw in the demonstration sketch --- if you want multiple servos to move at the same time, this sketch will move them sequentially instead of simultaneously (actually, the button reading algorithm in the demo sketch essentially guarantees you cannot move more than one servo at a time).
The solution that requires getting into time slicing your sketch to manage multiple simultaneous activities. Its doable and a worthy subject for a new post here in the near future.

for(int i = 0; i < NUMBER_OF_TURNOUTS; i++) {
//place button or other command source check here
// assume we’ve got a buttons array buttons[NUMBER_OF_TURNOUTS]
int button_state = digitalRead(buttons[i]);
if(button_state == HIGH){ turnouts[i].old_pos = pos; // save the current position
// Toggle the position to the opposite value
turnouts[i].pos = turnouts[i].pos == straight ? divergent: straight;
// Move the servo to its new position
if(turnouts[i].old_pos < turnouts[i].pos){
and so on as in the example, adding ‘turnouts[i].’ to variable references as shown.

This should get you started and enable you to control more than one servo in a basic way. Let me know how you do with this or if you need help.

Be sure to note the limits of the servo library: arduino.cc/en/Reference/Servo

There is one major flaw in the demonstration sketch — if you want multiple servos to move at the same time, this sketch will move them sequentially instead of simultaneously (actually, the button reading algorithm in the demo sketch essentially guarantees you cannot move more than one servo at a time).

The solution requires getting into time slicing to enable the sketch to manage multiple simultaneous activities. Its doable and a worthy subject for a new post here in the near future.”

Hi Rob
I’m not a programmer at all just a dedicated Dad trying to please a son and his train set. I’ve looked through all the posts and references but am still clueless as to how to design the code for multiple turnouts, just haven’t got the logical brain.
Is there any chance you can post the full sketch of the above explanation you gave to Ron above. You certainly would make our day if you could.
many thanks

Hi Rob
In essence we have 5 turnouts to control, using push buttons (push once from straight to divergence, push again it moves back to straight) and giving feedback using LED’s (yes he also wants a control board, the things we do for kids)
I am using an Arduino Uno
Thanks so much
Colin

Hi Colin,
Seems reasonable. One caveat: depending on the number of LEDS that need to be controlled on the control panel, you may run out of connections on your UNO. You can solve that problem using chained logic shifters (which require only three connections) to run all the LED indicators. Heck, if you do that you can even think about adding a signal or two (I’ll bet that touch would be a surprise!).

I think your son’s requirements would make a good concrete example for people trying to set up a small layout. So I think I’d like to do a post on the main blog, which will include a working sketch. I’ll put something together this week. Best, Rob

Both examples on this page use a button; the first example is the simplest. If you are interested in controlling more than one servo, go to the Multiple Turnouts and other Multitasking page for some ideas about how to do that.

I developed this, it may be an option, it uses a 16 servo board and a Arduino UNO R3

/*This sketch is designed to operate Model Railway Points that are driven by Servo Motors
*A SPDT switch connected to + and – 5vDC with the centre tap going to an Input Pin.
*
*This will scan a predefined set if Pins and allocate as INPUT then set them LOW.
*Dependant on the PIN STATE and whether or not it has changed it will rotate a SERVO on the active pin
*to a pre-determined location as set out in the SERVOMIN/SERVOMAX arrays.
*Millis() function has been used to streamline the operation.
*Serial.print can be removed, they are just for checking.
*
*Machine:- UNO R3 and 16 Servo Controller
*
*Created by Doug Reed 10/05/2016
*
*My thanks to the Forum Members who pointed me in the right direction.
*/

For PCA9685 PWM drivers I recommend the Adafruit Library. While you are at their site, take the time to look over their products … they have quite a few items of interest to Model Railroaders, and if we are going to use their software, the least we can do is see what they have!

Resolving compiler errors can be a pain. In your case, the most likely cause is a missing header declaration. Place this line at the top of the sketch (exactly as shown with no other punctuation):

#include <Servo.h>

so that the compiler knows was a “servo” object is and what to do with it. An idiosyncratic requirement of the C++ language is that “.h” or header files are used to formally define function types and parameters before they can be used. So any time you are invoking a library function (one that is not part of the language core), you must direct the compiler to the appropriate header file for that library function.

If you already have that line, then check your sketch line by line looking for punctuation or structural errors such as missing or inappropriate semicolons (compiler directives, such as the #include line, are an exception to the general rule and do not get a semicolon to mark the end of a line), or unbalanced curly braces (eg, an opening brace without a matching closing brace; a very common error).

General debugging tip: The IDE only shows the last error emitted, so the first thing you should do when the compiler fails is scroll through the output window and look at all the errors generated. In general, the first error emitted is the critical one, and following errors are usually just side effects. The most efficient way to debug a sketch is to track down and resolve them in the order they are emitted by the compiler.

Good morning Robert,
Thanks for the quick response. You were correct, I had missed out the #include even though I had spent ages going through the code before asking for help. I found a couple of other bits that were wrong and then low and behold the code downloaded.
There is one other question I would like to ask, and that is, should this code keep repeating each time I press the button. At present it only works the once IE, moves and stops, then returns to start when the button is pressed again. To make it work a second time I have to press the reset button on the Arduino.
Do I have to enter the second part of the code to get this action?
I will as usual be trying to sort the problem myself, but as this is my first time of dipping my toes in the Arduino pond I may finish up drowning myself.
Any help would be appreciated
Cheers,
Mike

Good afternoon Robert,
Panic over as I have found the problem. I had missed a > on the >= pos; .
Many many thanks for this code. I have been looking for this type of thing for ages but was getting seriously fed up as many people show you what is happening, but nobody gives you the code.
All I have to do now is look at the rest of the code to see how to get more than one servo to work, but having worked through your code I now have a far better idea of what should happen and a bit of an idea of where to look when it does not work (see how confidant i have become)
Once more thanks for your help.
Cheers
Mike.

Hello Robin, I’m trying to use the servos on my turnouts, but I’m have a trouble. When I turn on the arduino the servo moves (about 5-10° to each side) before stopping at the 90° position. This movement can damage the N-scale turnouts, which are very sensitive. Do you have any solutions to this problem? Thanks from Brazil

The tendency to move when powered up seems to be an issue with the standard servo library. I’ve seen it before, though it usually is not as bad as moving each way 5 – 10 deg before stopping in the middle. In fact, that seems extreme. I assume the servo works correct after startup — right?

My first thought is to suggest you recheck your grounds and make sure they are all tied together. #1 cause of weird servo behavior is grounds not being tied together. My second thought is to use a different pin on your arduino for the servo signal and see if that makes any difference.

If that does not solve your problem, I can think of two solutions:

1) Use a relay or a switching IC like a Darlington Array to control ground to the servo. You want to keep the servo powered off until after you have initialized the servo library and the servo object(s). After initialization, set the position then use the relay/IC to turn the servos on. You want to control the ground side because the servo has two “hot” inputs that share that ground.

2) Instead of attaching directly to your Arduino, use a servo shield (you should be able to find lots of options) or an external PWM Driver like the Adafruit 16 channel, 12 bit board. Either one should do the trick. I’m working on a new blog entry about working with the Adafruit board and should have that out soon.

Hi Robin, thanks for your quick reply! I’ll try these possibilities. At this moment I’m trying to use your code with “Typedef struct” but I’m not an expert and I’m having some difficulties. In your blog post of “Multiple Turnouts” the code is partitioned and I must be making a mistake when I put all the commands together. Could you send me a copy of the complete code? (I’m using 8 servos) Tks!

The test loop had only one turnout, but it used all the techniques described in the Multiple Turnouts post. Extending it to multiple turnouts is just a matter of supplying the turnout data. Hopefully it will help you see how the pieces fit together.

This looks like what I need to tie my CMRI Arduino nodes to turnout control. Now I just need to figure out how to fill in the blanks on the code to control my 4 turnouts. I guess I would need one shift register to control 4 turnouts, 4 push buttons, and 8 led’s? Thank You

One 8 bit shift register can control 8 LEDS. You cannot use a shift register to read buttons. If you had more than 4 buttons I’d suggest an I/O multiplexer chip, but for four that strategy wouldn’t save you any pins. Attach them to your analog pins (but still use digitalRead()) if those are available.

Shift Registers aren’t useful where you need PWM, such as with servos for turnouts. If need a pin-saving solution for PWM, try Adafruit’s 16 Channel PWM driver. For stall motor turnouts, you could use a shift register plus a darlington driver array so long as the motor draw is less than 500 mA per channel; that solution allows you to run 12 volt motors with 5 volt Arduino logic.

Hi rob i like you c++ turnout control. But am a littlee fuzzy on one aspect. I have servis going onto my turnouts and an adafruit 16 bit to run the turnouts. I can make them do a serco dance on the adfruit. But am stuck when it comes to putting 16 swithches in the loop somewhere.

Now i have a toggle switch for each servo. How would i use your c++ code to move servo 1 on adfruit pin 0 when the toggle switch is thrown?

I know i need some io extender ic2 board to do the 48 controls i need to get to. But for now if you could show me how to put tje toggle switch directly into the ardunio then call the adfruit to switch using your c++ code be so helpful

None of my recent examples use toggle switches because i use network control methods, but that’s not a big deal — you’ll just need to read your toggle switch connections on every loop, and trigger a turnout whenever it’s switch is changed. So at the start of your main loop (see the post on multitasking mentioned above) you do three things: 1) capture the time; 2) check the switches and call the triggers for any turnout switch that has changed; and 3) run the turnout.update() method to continue the movement sequence.

Don’t forget to download the example code. If you still have questions, let me know and I’ll try to help.

Hi
I am a backend LAMP dev on some huge projects, but i think i am over thinking what i need to do and hence stuck as you get.

What I need to see is a simple sample to talk back to the adfruit when a toggle or push button switch is pressed.

– what do I need to call xxxx.h as well as turnout.h
– if a switch into digital pin 6 (uno) and I toggle high move turnout into yard
– if a switch is in digital pin 6 (uno) and I toggle low to set the mainline straight threw

Parts i have uno R3, adafruit 16bit.

Can make my servos dance, but now need to switch them and am a little stuck as where to start I looked at your Organizing Turnout Data but as i mentioned before have a mind blank with how to use the switch to trigger things.

You probably are overthinking it a bit. I’ve been there; I’m buried in PHP and Javascript right now and sometimes the transition back to Arduino C++ can be head-snapping.

If I’m understanding correctly 1) you are ok using the adafruit board and setting a servo position with it; 2) you have my turnout class (turnout.h) and understand how it works and how to use it to move turnouts; but 3) you are uncertain how to use a button or switch to trigger movement.

OK. First all all, whether you use a button or a switch, you’ll need a pull-down resistor as shown on this page; that prevents false readings. A switch is wired the same way as a button except only one of its outputs connects to your Uno pin (leaving other outputs unconnected). The difference between the two is the button pulls the pin high momentarily, while the switch pulls it high continuously until toggled off. The code is similar, with a few differences due to the differences in the way buttons and switches work.

Button:
// turnout object created with the parameters that a correct for your installationturnout = new turnout(TURNOUT_PARAMS *parameters);
loop(){
unsigned long currentMillis = millis(); // get elapsed time as required for the turnout object

// check the button
if(digitalRead(6) == HIGH){
turnout.toggle(); // With buttons, use the toggle function to change position and trigger movement; toggle() will reverse a switch in motion
}

// update turnout objects for movement
turnout.update(currentMillis);

// do other stuff
....
}

Switch:
// turnout object created with the parameters that a correct for your installationturnout = turnout(TURNOUT_PARAMS *parameters, int movement_increment = 1);
loop(){
unsigned long currentMillis = millis(); // get time as required for the turnout object

// check your switch
if(digitalRead(6) == HIGH){
// if the switch reads HIGH, turnout should diverge into the yard
// check turnout state first
// call set() only if turnout is currently in wrong position and is NOT in motion
// in the turnout class, alignment is set to ALIGN_NONE while the turnout is in motion
if(turnout.getAlignment() == ALIGN_MAIN) { // if TURNOUT is aligned for main track
turnout.set(ALIGN_DIVERGENT);
}
} else {
// switch is currently LOW; turnout should be aligned for the mainline
if(turnout.getAlignment() == ALIGN_DIVERGENT { // if TURNOUT is aligned for yard track
turnout.set(ALIGN_MAIN);
}
}

// update turnout objects for movement
turnout.update(currentMillis);

// do other stuff
....
}

Other than turnout.h for the turnout CLASS (and the adafruit header) you don’t need any other .h files.

I will this a go a see where I get to but last night I had my head in the right place and things were working. I think I am over thinking the electronic sides of things as the understanding of some of the concepts/language used is making me over think.

I have another i2c board that is addressable along the lines of the adafruit where it can read and writes to put my switches (it only turned up yesterday) into I think this will solve the problem of running out of pins on the Arduino, and I think this board will handle the diodes as well well we will see.

My thinking around this is to make things easy for people is this single pin addressable board for switches on i2c (I think the lull up resistor is on the board) linked to Arduino — then i2c to adafruit. A class called switching and your turnout class, we have a nice pluggable solution that a few of my model club members could work out as the heavy lifting portions of the code are will be done.

Hi Robin: in the past month I have been trying your code and diagram to control the turnout with a single button and 2 LEDs. I have gotten a single servo working on my Arduino Uno and I am trying to get 2 servos working at the same time. I am wondering if you can give me some code to do so. I have been trying to “copy & paste” (not literally) the code. So in the end I have a single servo controlled with a single button and 2 LEDs and in the same code have another running the same thing, of course on the Arduino Uno.

Robin, could you give some more guidence on how to avoide using delay in the code I have read “other turnouts and other mulitacking” and “blink without delay” but still dont understand how to modify the code to do so. Thank you.

Your work has inspired me to jump in on a large project in HO scale. I have been reading and learning some from your posts but most of those Aha moments come from the answers to questions others have posted to you.

I can control 23 turnouts with 2 Adafruit 16ch pwm boards. I am also using 2 Adafruit 12 key capacitive touch sensor board to pick up the “NX” style controls and have that working to select the routes. I was trying to figure out how to add the address/variable of each pwm board to the array and call it to perform the action without the need to start each line with “pwmX”. Probably so easy I am just overlooking it. Here is a sample of the routines I have to align everything.

Its been a busy month and I’m way behind on almost everything. Sorry to take so long to respond.

This is a route setting problem at its heart. Each each pwmX represents a unique instance of the Adafruit pwm object that matches one board, right? It looks like you have an array of turnout objects/structs for your data. So far, so good.

To simplify your code, you want to encapsulate more of your functionality inside an object. I did that in my turnout class so that it can be used with either the Adafruit board or the standard servo library. Since my class does not yet support multiple Adafruit boards, you will want to add a parameter (and use it in the object) to reference the board associated with a turnout. Taking that post as a starting point (read that first), the new class member of the turnout class might look like:

This is not a complete solution …. rather I’m suggesting a different approach to the problem that would improve code simplicity and readability. The main point is to 1) create an object that wraps around and hides the nitty-gritty of moving servos, and knows what alignment is required for each route; and 2) to hold all references to your turnout objects in a single array that your can step through with a “for loop.” You could extend this to support multiple routes by loading each object with a data array so it has alignments for each route. Just call all turnouts with a given route # and they should set themselves accordingly.

Hi Robin:
Thank you for posting your article regarding turnout control using Arduinos. Your turnouts control is exactly what I am looking for. Your article was easy to follow. Iing 1 pushbutton to control the 2 way point movement. As I would like to control all my turnouts using something like this I have some questions:
1. Can more than one turnout be installed on an Arduino uno?
2. Would it be best to order a Mega rather than an uno for multiple turnouts?
3. Could a command control and/or signalling system be attached at a later date?
Again, thank you for posting your tutorial…it is appreciated.
Regards
Geoff Danish

Thanks for the response. I know all about busy too. I will try adding the “elegance” of your suggestion as soon as I figure out either the 12 channel cap touch issue or change the input method to something reliable like momentary push buttons. I can’t get the cap touch to read consistently even after changing some of the suggested parameters. Then I have enough sensors I added a second cap board (different address) but when I test the second board it screws up the primary and the code doesn’t seem to run just hangs during Setup. Oh well I know you aren’t using cap touch and to keep the rest of my hair on my head I don’t think I will either so I can get this project moving forward. I may revisit the cap touch later for a sleek control panel.

Always good to limit your variables in the beginning and get one piece working at a time. I’d definitely get the turnouts themselves functional before creating an advanced control system.

You might consider touch screen control. Adafruit has compatible touchscreens. 800 x 600 is your max resolution for Arduino based projects; higher resolutions require a different solution such as Raspberry PI, but you could use a large commercial HDMI touchscreen which would be nice. Come to think of it, using using “Processing” for Raspberry PI, or Javascript, it should be straight forward to getting a Pi to talk to your Arduino via serial or network protocols. That gains you powerful graphics capabilities using HDMI displays plus access to any device a PI can access — including printers. I’ve always thought that it would be fun to have a system create and spit out waybills and dispatch orders for operating sessions… but I digress.

I’ve worked with an UNO driving a 4″ touch screen successfully. Adafruit has a 7″ one that, with a TFT Graphics interface board, works with Arduino.

My long term plan is to create a master control center with 2 or 4 7″ touchscreens (a 14 x 14 display), using graphics drivers plus a MEGA to do the processing. Additionally, I’ll create 2 or 3 convenience panels with 4″ screens and Unos in places where you would do a lot of switching ops. Everything talks via the network so it shouldn’t be too hard pull it all together.

Sometime in the future is a CTC system for the club and I had planned on the Pi to run the whole show so we could talk to our guests while trains operated in the background or we could actually have an op session.
As an update I did tweak the registers on the MPR121 to reliably read each board reliably but I still get the freeze when both boards are on the I2C bus. The illuminated momentary PBs are here so I will get this working and continue to tinker with bigger better things.

When I get a few hours to tinker with all I2C stuff I will try all the address combinations (0x5A-0x5D) available for the cap touch. The lighted momentary PBs work with the servo boards and for now that is phase 1 (a working system).

I am helping my son setup his layout and I am interested in setting up his turnouts to use this control method that you have come up with. I was talking to some other model RR friends and the one concern they had was about the servos and if they could withstand the wear and tear to the gears. They were wondering how has this system worked for you and have you had to replace any servos due to stripped gears? Their concern was about dirt/ gravel getting stuck in the switches which would prevent the turnouts from being completely thrown. If this occurs would the servo keep trying to complete the position change and possibly strip the gears over time?

I’ve never had a servo strip its gears. The only mishaps I’ve had so far are a couple of broken servo->throw rod linkages, probably because I didn’t have the alignment quite right.

Servos stopped before the intended destination will exert pressure, and if the remaining travel is significant they will get buzzy and hot. Eventually something ought to break, but I haven’t seen that yet. I’ve blown out parts on the layout, so I’d say the servos are proving resilient.

I use fairly stiff music wire to actuate my turnouts, and I intentionally set the servos to put a little pressure on the turnout at both ends of travel — my Peco electrofrog turnouts seem to like that — so I can say that servos can take some mild resistance without breaking. If you want to make a servo more forgiving of obstructions, increase the flex of the actuating wire and let the wire take the stress of the interrupted travel.

I recommend music wire for this application. I use .062 (1.57mm) dia wire; in 4 – 6 ” lengths it will bend about 1/4″ or so (the longer the wire the more bend you get). Try different diameters to get the flexibility you need.

Robin, Thank You so much for this information. I recently retired and decided that the time had finally come to get back into Model Railroading. I was introduced into it by my father about 60 years ago. Most of my equipment is 40 to 60 years old. Anyway, in planning I had decided the regular switch machine were not to my liking and stumbled onto an article talking about Ardino. Since I had a past that included programming in BASIC, sounded like I was set. Little did I know. So for the last month I have been pouring over every tutorial I could find to re-educate myself. The common thread was none teach you how to take arrays and operate from them. That’s been where I was stuck. So with your examples and explanations I hope to move forward.

If the array version is making sense, take a look at the object-oriented version at C++ Objects for Layout Control, Part 2 — Turnouts (you’ll probably want to look at the Part 1 Post first). Once you get your head around how C++ objects work, its even easier to implement reliably than the array version.

Robin, I took a look at the 2 parts and with just coming to grips with C++ don’t feel I am ready. Still working on getting totally working code using arrays. But as I mentioned before, the info you have in your write ups really expands on the on line tutorials out there.
Do you have a direct email address I could use to ask a question about using your code?

Hi Robin,
Have found your page helpful. Would appreciate some help. I have a hidden storage yard 3 roads either side of single main. The roads can be entered from either end off the main. I have tortoise motors rather than servos. My concept is using Arduino Mega processor to select a route for any of the roads by pressing a button. Once button is pressed and released the motors would be set to the selected route. This would stay until another button is selected and another route is chosen. At present 7 buttons are required. One for each road.

Stage 1 is to use a mimic board with buttons positioned on each road and bi polar LEDs indicating route selection. LEDs to be driven by tortoise motors. Switching via Mega

Hi Robin
I am very new in the Arduino universe 🙂 and are not ready yet for programming Arduino.
I have used your turnout project and modified a little for railway crossing. It is working well with one button, but Is it possible to change to two buttons. One button for opening gate and number two button for closing the gate
Best Peter

The second button would be assigned to its own pin, with a pull-dwon resistor to ground as with the first button.

Secondly, you will have to modify the code to read both buttons and decide which button has been pressed–and you will need to reject situations where both buttons are pressed at the same time. So the code structure would have be be modified along these lines (this is outline code, not final working code):

b1 = digitalread(button1);
b2 = digitalread(button2);
if(b1 == b2){
// do nothing
// act only when one is high and other is low; never act when they are the same
} else {
if(b1==HIGH){
//set target position to open
pos = OPEN;
} else if (b2 == HIGH) {
//set target position to close
pos = CLOSED;
}
}

thank you for the n scaler, without it I would be totally lost. I mastered your servo/momentary buttton sketch but this is the limit of my abilities. I want to control my turnouts with an arduino uno and servos, is there a sketch that maximizes the number of servos controlled by one button each (no leds). Adjusting each servo individually is a must. If you can steer my in the right direction, I would appreciate it. Thanks Bob

In general, the Servo library limits you to 10 servos. If you want to handle more than that, you will need one or more PWM Driver Boards, like the Adafruit 16-Channel 12-bit PWM/Servo Driver (see Running Lots of Turnouts).

Your other limitation is the number of pins you have available for buttons. It you use the Servo Library, the practical limit on servos & buttons will be 8 of each, leaving 4 pins for other uses on an UNO. With a PWM Driver, your practical limit is 16 servos & buttons on most Arduino boards. With a MEGA and two chained PWM Drivers you could handle 32 servo/button combos.

Hope this helps. Feel free to ask questions after you check out the other posts.

GOOD MORNING, I HAVE MUCH LIKED YOUR WORK Complete servo installation. THERE WOULD BE A POSSIBILITY TO MAKE THE CODE EASIER FOR ME TO DO IT WITH TWO TWO-COLORED LEDS (RED AND GREEN).
GREETINGS AND MANY THANKS

Hi,
i’m new to the JMRI world, i’m running a Arduino connected to JMIR via CMRI protocol, i can’t find any sketch that works with Arduino using 5 servos, I’m using an external 5v psu for the servos, but i can only make 1 servo move from JMRI with the sketch, i’ve tried adding turnout2 to the sketch, but it doesn’t work, surely it shouldn’t be that hard? looking aat york previous posts, it looks like i need to define my extra turnouts?.

Any help would be greatly appreciated

Here is the sketch i’m currently working on below:
#include
#include
#include

This gets to the problem we all face in one form or another: money vs. time.

If you are going to fabricate your own mounts, make them one-piece or they will be prone to breakage under stress. The way I originally did it with multiple pieces and hot glue is not reliable.

Agree that $12 seems like a lot for one mount — but if you compare it to other servo mounting options on the market, it’s actually one of the lowest cost options. At $15 with the servo ready to install, the cost is a little less than tortoise switch machines (the de facto standard in this area). They also offer additional discounts for multiple units. With even the cheapest, old fashioned switch machines running around $10 ea, there aren’t any cheaper options other than roll-your-own.

Hi, I have searched long and hard to find an Arduino project to turn servo’s on a Model Railway layout using either a push button or a toggle switch without success and using the PCA9685, yours is the only one I have found that I think I can modify, as being an old git my program skills are just about zero, I did build one that I found on Dronebot Workshop using Analog inputs using a Mega which I modified for 9 inputs including controlling a scissor crossing and that does work but I have to use a voltage divider to get 60deg but as of yet not found a way of adding LED’s, and also giving me a digital output to feed to a second Mega which controls the polarity on a 4 Line crossing on 10 diamond crossings, nightmare, so I will try your setup and try and incorporate the PCA9685 and add 5 single servo’s and 2 x 2 servo’s for scissor crossing. Wish me luck ….

That’s quite a complex setup. Since you are already at 2 MEGAS, may I suggest you look at my current series on layout control: Building Blocks for Layout Control which explains my current thinking on how to handle complexity of this kind, and the next in the series, Basic Layout Control Nodes. Next post in the series coming soon.

Hi Robin,
I’ve been reading a great deal about using an Arduino Uno and servos to change my points and along the way, discovered the limitation of 1 Uno – I need to change 18 points. Then I discovered the PCA9685 and, with the help of a professional coder on another board, ended up with a sketch the turns the servos slowly. All good. In my testing, I’m using a breadboard and jumper wires for connection, nothing is permanently soldered yet. Occasionally, when testing, one or more of the servos in test would jerk violently when power was applied. More recently, after fitting 5 servos to the underside of a section of my layout, when power was applied, one servo reacted so strongly that it pulled itself out of my mounting. The next thing I know is one of the servos is spinning 360 degrees. These are SG90 servos, supposed to be 0 to 180 degrees and each controlled via a toggle switch. The plan is flick the switch and the servo will move left or right and a led will display the position on a panel.
Last night, I went out to a friend’s place to operate on his layout and inadvertently, left power on in my train room. Although there was no action on the toggle switches, when I returned, the servos, which I had disconnected from the layout but still connected to the PCA9685, were all spinning madly 360 degrees!

I’m sure I read somewhere in your posts that you touched on the subject of servos spinning? Can you repeat it here or point me in the right direction?

Hi David — I apologize for the long wait. Thanks for stopping by and taking the time to comment.

Wow. I don’t have a solution for you off the top of my head. A standard SG90 has stops that prevent movement past 180 degrees — and attempting to do so would usually burn out the motor. However, some servos are the free spinning type that do not have stops … is that what you have?

That tendency of the servos to jerk when power comes up is common and usually harmless. If it is causing a problem, use the OE pin of the PC9685 to control the PWM driver. When the OE is pulled HIGH, output is disabled. So with OE high you can set PWM levels where they are supposed to be, then pull OE LOW to enable output. Any out of position servos will move, but the jerking thing should be better.