Turnout Control with Arduino & Servos

Complete servo installation.

Complete servo installation.

[Since this was originally posted I’ve come up with a low-noise, low-profile side mounting method. The mounting method does not change the programming required to control one, or more, servos.]

This is a basic method for using an off-the-shelf micro servo as a turnout motor, in this case the

Tower Pro SG90

Tower Pro SG90

Tower Pro SG90 which can be purchased for $2 to $3 each.

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.

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

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.

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.

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.

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 mounted and ready

Servo Control by Button

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.

#include <Servo.h>

// constant variables used to set servo angles, in degrees
const int straight = 90; 
const int divergent = 110;

// constant variables holding the ids of the pins we are using
const int buttonpin = 8;
const int servopin = 9;

// servo movement step delay, in milliseconds
const int step_delay = 70;

// create a servo object
Servo myservo;  
 
// global variables to store servo position
int pos = straight; // current
int old_pos = pos; // previous

void setup() 
{ 
  // set the mode for the digital pins in use
  pinMode(buttonpin, INPUT);
   
  // setup the servo
  myservo.attach(servopin);  // attach to the servo on pin 9
  myservo.write(pos); // set the initial servo position
}

void loop() 
{ 
 // start each iteration of the loop by reading the button
 // if the button is pressed (reads HIGH), move the servo
  int button_state = digitalRead(buttonpin);
  if(button_state == HIGH){
    
    old_pos = pos;   // save the current position
    
    // Toggle the position to the opposite value
    pos = pos == straight ? divergent: straight;
       
    // Move the servo to its new position
    if(old_pos < pos){   // if the new angle is higher
      // increment the servo position from oldpos to pos
      for(int i = old_pos + 1; i <= pos; i++){  
        myservo.write(i); // write the next position to the servo
        delay(step_delay); // wait
      }
    } else {  // otherwise the new angle is equal or lower
      // decrement the servo position from oldpos to pos
      for(int i = old_pos - 1; i >= pos; i--){ 
        myservo.write(i); // write the next position to the servo
        delay(step_delay); // wait
      }
    }
    
  } 
}// end of loop

Finally, we can add one more refinement and have the Arduino feedback position status via two pins that we can use to power leds at the control panel. The circuit looks like this:

Servo Control with LED Feedback

Servo Control with LED Feedback

To update the sketch, we’ll add variables for the led pins and add commands to turn the leds on and off.

#include <Servo.h>

// constant variables used to set servo angles, in degrees
const int straight = 90; 
const int divergent = 110;

// constant variables holding the ids of the pins we are using
const int divergent_led = 6;
const int straight_led = 7;
const int buttonpin = 8;
const int servopin = 9;

// servo movement step delay, in milliseconds
const int step_delay = 70;

// create a servo object
Servo myservo;  
 
// global variables to store servo position
int pos = straight; // current
int old_pos = pos; // previous

void setup() 
{ 
  // set the mode for the digital pins in use
  pinMode(buttonpin, INPUT);
  pinMode(straight_led, OUTPUT);
  pinMode(divergent_led, OUTPUT);
  
  // setup the servo
  myservo.attach(servopin);  // attach to the servo on pin 9
  myservo.write(pos); // set the initial servo position
  
  // set initial led states
   digitalWrite(straight_led, HIGH);
    digitalWrite(divergent_led, LOW);
}

void loop() 
{ 
 // start each iteration of the loop by reading the button
 // if the button is pressed (reads HIGH), move the servo
  int button_state = digitalRead(buttonpin);
  if(button_state == HIGH){
    // turn off the lit led
    if(pos == straight){
              digitalWrite(straight_led, LOW);
          } else {
              digitalWrite(divergent_led, LOW);
          }
    old_pos = pos;   // save the current position
    
    // Toggle the position to the opposite value
    pos = pos == straight ? divergent: straight;
       
    // Move the servo to its new position
    if(old_pos < pos){   // if the new angle is higher
      // increment the servo position from oldpos to pos
      for(int i = old_pos + 1; i <= pos; i++){  
        myservo.write(i); // write the next position to the servo
        delay(step_delay); // wait
      }
    } else {  // otherwise the new angle is equal or lower
      // decrement the servo position from oldpos to pos
      for(int i = old_pos - 1; i >= pos; i--){ 
        myservo.write(i); // write the next position to the servo
        delay(step_delay); // wait
      }
    }
    // turn on the appropriate LED.
    if(pos == straight){
            digitalWrite(straight_led, HIGH);
        } else {
            digitalWrite(divergent_led, HIGH);
       }
  } 
}// end of loop

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.


 

For more on avoiding delay() and controlling multiple turnouts, see Multiple Turnouts and Other Multitasking.


 

30 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.

      Rob

    • I hear you can expand it out to 4 servo and a relay control up to change tracks,

  1. 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

    frantabarca@gmail.com

    • Francisco – Thanks for visiting!

      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.

      Rob

  2. 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:

      typedef struct TURNOUT_DEF {
      int pin;
      int pos_main; //main servo position in degrees
      int pos_div; //divergent servo position in degrees
      };

      To declare a variable and initialize its values for one turnout:

      TURNOUT_DEF turnouts = {2, 94, 121};

      To reference the values:

      turnouts.pin ( == 2)
      turnouts.pos_main ( == 94)
      turnouts.pos_div (==121)

      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.

      Declare and initialize the variables this way:

      #define NUMBER_OF_TURNOUTS 2
      Servo servos[NUMBER_OF_TURNOUTS];
      TURNOUT_DEF turnouts[NUMBER_OF_TURNOUTS] = { {2, 94, 121}, {3, 96, 119} };

      To reference the values, add the array subscript:

      turnouts[0].pin ( == 2)
      turnouts[1].pin ( == 3)

      So, the initialization loop in setup() looks like this:

      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.

    • WordPress is mangling the last bit — lets try that again:

      So, the initialization loop in setup() looks like this:

      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 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 Colin

          The example(s) are excerpts from much bigger sketches; all the extra stuff would confuse the issue.

          So maybe I can craft a full example, based on your specific needs, that would be useful to others with similar needs.

          How many turnouts are you trying to control, how do you want to control your turnouts (button(s), toggle switches, or something else?) and what Arduino board will you be using? Rob.

          • 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

  3. Hello
    thanks for your useful and beautiful blog
    and your willingness to share information

    I’m working on a project for diverters with Arduino

    could you kindly post a skeg

    to drive most servo with buttons (1 for switch button)

    thank you

  4. I would like to thank you for this information! Although I haven’t started my layout yet, your ideas are pure gold to get your imagination flowing! I have so many ideas that I have to write them down!

  5. 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.
    */

    #include
    #include

    unsigned long previousMillisSWITCH=0; //Button Millis() setup
    int intervalSWITCH = 20; //intervals for millis()

    Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // called this way, it uses the default address 0x40

    unsigned int SERVOMIN[11] = {172,172,172,246,246,172,246,200,200,150}; //servo lower setting to suit individual servo
    unsigned int SERVOMAX[11] = {565,530,500,492,492,565,492,550,550,525}; //servo upper setting to suit individual servo
    int InPin[11] = {2,3,4,5,6,7,8,9,10,11,12}; //array of input pins
    int PinCount = 11; //the number of pins used, lenght of array
    int Dir = 0;
    int OldDir[11];
    int NewDir[11];
    int thisPin;
    int degrees;

    void setup() {
    Serial.begin(9600);
    pwm.begin();
    pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates

    for (int thisPin = 0 ; thisPin < PinCount ; thisPin++) { //"thisPin" is array position
    pinMode(InPin[thisPin],INPUT); //sets all pins 2 -12 as INPUT
    }
    for (int thisPin = 0 ; thisPin = intervalSWITCH) { // time between button presses

    for (int thisPin = 0 ; thisPin < PinCount ; thisPin++) { //assess the direction settings
    Dir = digitalRead(thisPin+2);
    OldDir[thisPin] = NewDir[thisPin];
    Serial.print(InPin[thisPin]);
    Serial.print(" Dir ");
    Serial.println(Dir);

    if ((Dir == 1) && (OldDir[thisPin] == 0)){
    for (uint16_t pulselen = SERVOMIN[thisPin]; pulselen SERVOMIN[thisPin]; pulselen–) {
    pwm.setPWM(thisPin, 0, pulselen);
    Serial.print(InPin[thisPin]);
    Serial.print(” LOW “);
    Serial.println(pulselen);
    }
    NewDir[thisPin] = 0;
    }
    }
    }
    previousMillisSWITCH = currentMillis;
    }

  6. I do know if you can help me with this but here goes.
    I have typed the code as far as I can see correctly, but when I try to download it, it gets as far as

    // create a servo object
    Servo myservo;

    then gives me an error message

    ‘Servo’ does not name a type
    being a little old and never having tried this before I am a little baffled as to what this means. Can anyone explain please?
    Thanks in anticipation,
    Mike

    • Hi Mike,

      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.

      Best, Robin

      • 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

  7. 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.

    • I figured something like that from your description of the problem. Glad you worked it out.

      You are welcome. I’m thinking about setting up a Github repository for helpful code bits. Perhaps this Spring I’ll get around to it …..

      If you are interested in a multitasking technique that allows you to handle multiple servos and do other things too, see Multiple Turnouts and other Multitasking.

      Cheers! Robin

  8. 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

    • Hi Maurico,

      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.

      Best,

      Robin

      • 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!

        • Take a look at the test loop code and see if that helps you — you can download it here: https://github.com/rpsimonds/thenscaler/tree/Testloop.

          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.

          I’ll be writing more about multiple turnouts soon.

          Robin

  9. 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

    • If you haven’t seen it you might want to look at Running a Small Layout with An Uno.

      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.

Leave a Reply

Your email address will not be published. Required fields are marked *