Operating model railway turn outs with servos

Hello. I am a beginner. I want to operate model railway turnouts with servos and push button control using Arduino Uno revision 3. I have managed to get one servo with push button control working using the following sketch which I copied from the web but have been unable to get a second servo with push button control to work. I would appreciate advice on coding and wiring to achieve this. As stated I am an absolute beginner and hope my question is not too naïve!
Thank you.

#include <Servo.h>

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

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

have been unable to get a second servo with push button control to work

If the code for 1 servo works then the easiest way to add a second one is to duplicate the code. Is that what you did ?

What did you try ?
Did you use differently named variables for the second servo and its control pin ?

NOTE : If you have more than 2 servos to control with the corresponding number of buttons then I can foresee the use of arrays in your future

Note that your use of delay will cause the switches to be unresponsive during a movement, so simultaneous operation may not be possible.

there are plenty of articles on arduino servo controllers on MRH

I wonder if the following (tested) code is more obvious.

#include <Servo.h>

int turnoutAStraight = 1100; // microseconds
int turnoutATurned = 1900;
byte buttonAPin = 5;
byte buttonAState = HIGH;   // LOW = pressed
byte prevButtonAState;
int turnoutAPos = (turnoutAStraight + turnoutATurned) / 2; // the mid point for the initial position
int newTurnoutAPos = turnoutAPos;
int turnoutAStep;

Servo turnoutAServo;
byte turnoutAServoPin = 8;


void setup() {
    pinMode (buttonAPin, INPUT_PULLUP);
    turnoutAServo.writeMicroseconds(turnoutAPos);
    turnoutAServo.attach(turnoutAServoPin);
}

void loop() {
    prevButtonAState = buttonAState;
    buttonAState = digitalRead(buttonAPin);

    if (buttonAState == HIGH and prevButtonAState == LOW) {
        if (turnoutAPos == turnoutAStraight) {
            newTurnoutAPos = turnoutATurned;
        }
        else {
            newTurnoutAPos = turnoutAStraight;
        }
    }

    if (turnoutAPos != newTurnoutAPos) {
        if (turnoutAPos < newTurnoutAPos) {
            turnoutAStep = +10;
        }
        else {
            turnoutAStep = -10;
        }
        turnoutAPos += turnoutAStep;
        turnoutAServo.writeMicroseconds(turnoutAPos);
        delay(30);
    }
}

If you just want to add a single extra turnout then you need to repeat everything that has an 'A' in it and change the 'A' to 'B'

If you are planning to have several turnouts then it will be easier to use arrays to hold the values - or better still an array of structs.

...R

You will likely need a separate power supply for the servos. The Arduino can't provide enough current for one, let alone several, especially when they're actually doing some work.

“Turnouts” are conventionally controlled using solenoids , of which many are available to fit model railways . Why not use these , and control with Arduino , if you wish ?

Solenoids "snap", but servos allow a more realistic movement.

There are some google hits for people doing this - worth you having a look.These people sell the bits

http://heathcote-electronics.co.uk/servo.html

hammy:
With a servo you will need to be careful that the holding force is sufficient - if the servo is stalled when in any position it will over heat and burn out , so , you can’t drive it hard against a stop; given linkage play it’s a difficult ask to use a servo in this type of application to get the points repeatably closed with the servo holding position but not stalled .

All the point motors and solenoids that I've seen have spring actuators to limit the force applied to the turnout.

I have several model railway turnouts controlled by servos. It is quite common and a helluva lot cheaper than the slow motion Tortoise turnout motors that are very popular.

I only attach() a servo when I want to move it and detach() it when the move is finished. The normal gearbox friction is quite sufficient to hold the turnout in place. I remove the over-centre springs from the turnouts as that makes smooth operation with the servo much easier.

...R

Sorry guys - I put my post up then googled a few things , saw people were doing that , went back and corrected it . I think you replied whilst I was doing that ! ( I was only gone a moment lol )

Hello
Thank you very much for your reply's. I have managed to get two servos working but have to upload the sketch (as attached to my post) for each one separately which is not ideal! I tried putting both sketches in to a single sketch i.e. one copied below the other with just the servo pin and button pin numbers as variables. Only one servo would work. Clearly I am not understanding how this should be done. The wiring (as diagram attached to my post) for the second servo and button is a duplicate of the first servo except for the servo and button pins used of course. I can see that 'Arrays' could be the future but one servo at a time for now will be an achievement for me. Any continuing help for this duffer will be much appreciated.

Thank you

If you post your code (in code tags this time), we can help.

Thank you. The code I tried is as below, I guess there are either too many or not enough commands? Also I should have said that I am using an external 4.5v source to power the Arduino.

#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

#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 = 10;
const int servopin = 11;

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

Please follow the advice on posting code given in posting code

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

What people usually do in this situation to start with is take all the variables relating to the original servo like buttonpin and call them buttonpin1. When you add another servo you add buttonpin2 and all the other variables. There will be quite a few of them. Then you replicate the code using the second set.

Around the time you get to servo four you will think (hopefully) "There must be a better way". There is and as you already surmise, it is arrays. Probably arrays of structs in this case.

The painful way is easy to understand, but easy to mess up as you use the wrong variable somewhere because of a copy & paste error. You will appreciate arrays all the more afterwards though.

wildbill:
n and call them buttonpin1. When you add another servo you add buttonpin2

That's what I suggested in Reply #4 except that I used A and B rather than 1 and 2

...R

Sorry, should have said 4.5v to power servos!!

Hello

Can anyone assist with my query about a code for two servos with buttons to operate model rail turnouts from Arduino Uno. In response to an earlier reply to my query (for which thank you) I did post a code which I tried, but which didn't work. Any help will be much appreciated.

Thank you