Model railroad servo based turnouts

That's easily fixed

2 Likes

so the servos move the turnouts
which means each servo moves always to the same two positions.

if the servo-position is set with the command

before the function-call to

the function-call pointServo.attach() will start with a signal that moves the servo to the prior set position.

With this solution your turnouts would be set always to the same position on power-up but this position then can be straightforward or turnout

If you wish that
if a servo is switched to turnout
some other servo is switched to straight forward
and on powerup the servo shall stay at this position
it is nescessay to store the position into non-volatile memory (prefereable an FRAM) or maybe an SD-card

this enables that each servo can be on turnout or straightforward position and stays there on powerup

best regards Stefan

  • line 17, Srv not serv

  • line 23 servoLowPos not seservoLowPos

  • line 24 else not els

  • line 24 Srv not Serv

  • line 30, looks like you gave up on the code that moved the points slowly and got the braces, '{', '}', mixed up trying to follow the suggestion in post #6

i believe the following is what you want.
it's your original code with some modifications to set the points per the toggle switches in setup()

# include <Servo.h>

Servo pointServo[6];

byte servoPin[] =     {  2,   3,   4,   5,   6,   7, }; // pin numbers for servo signals
byte switchPin[] =    { 8,  9,  10,  11,  12, 13 }; // pin numbers for switch connections
// Uno analog pins      A5   A4   A3   A2   A1   A0
byte servoLowPos[] =  { 50,  60,  60,  60,  60,  50,  }; // degrees for low servo position
byte servoHighPos[] = {160, 140, 160, 170, 150, 160,}; // degrees for high servo position

byte servoPos[6];

void setup() {
    Serial.begin (9600);
    setupSwitches();
    setupServos();
}


void loop() {
    for (byte n = 0; n < 6; n++) {
        boolean servoMove = false;
        byte sw = digitalRead(switchPin[n]);
        if (sw == HIGH) {
            while (servoPos[n] != servoLowPos[n]) {
                servoPos[n] -= 1;
                pointServo[n].write(servoPos[n]);
                delay(10);
            }
        }

        if (sw == LOW) {
            while (servoPos[n] != servoHighPos[n]) {
                servoPos[n] += 1;
                pointServo[n].write(servoPos[n]);
                delay(10);
            }
        }
        if (servoMove) {  // only move the servo if the switch has changed
            pointServo[n].write(servoPos[n]);
        }
    }
}


void setupServos() {
    for (byte n = 0; n < 6; n++) {
        pointServo[n].attach(servoPin[n]);
        if (HIGH == digitalRead(switchPin[n]))
            servoPos[n] = servoLowPos[n];
        else
            servoPos[n] = servoHighPos[n];
        pointServo[n].write(servoPos[n]);
    }
}


void setupSwitches() {
    for (byte n = 0; n < 6; n++) {
        pinMode(switchPin[n], INPUT_PULLUP);
    }
}

This function does attach the servos before set to the correct position.
This means all servo-channels start creating a servo-signal for 90 degrees which is surely the wrong position

# include <Servo.h>

Servo pointServo[6];

byte servoPin[] =     {  2,   3,   4,   5,   6,   7, }; // pin numbers for servo signals
byte switchPin[] =    { 8,  9,  10,  11,  12, 13 }; // pin numbers for switch connections
// Uno analog pins      A5   A4   A3   A2   A1   A0
byte servoLowPos[] =  { 50,  60,  60,  60,  60,  50,  }; // degrees for low servo position
byte servoHighPos[] = {160, 140, 160, 170, 150, 160,}; // degrees for high servo position

byte servoPos[6];

void setup() {
    Serial.begin (9600);
    setupSwitches();
    setupServos();
}


void loop() {
    for (byte n = 0; n < 6; n++) {
        boolean servoMove = false;
        byte sw = digitalRead(switchPin[n]);
        if (sw == HIGH) {
            while (servoPos[n] != servoLowPos[n]) {
                servoPos[n] -= 1;
                pointServo[n].write(servoPos[n]);
                delay(10);
            }
        }

        if (sw == LOW) {
            while (servoPos[n] != servoHighPos[n]) {
                servoPos[n] += 1;
                pointServo[n].write(servoPos[n]);
                delay(10);
            }
        }
        if (servoMove) {  // only move the servo if the switch has changed
            pointServo[n].write(servoPos[n]);
        }
    }
}


void setupServos() {
    // set servos to correct position PRIOR to servo.attach()
    for (byte n = 0; n < 6; n++) {
        if (HIGH == digitalRead(switchPin[n]))
            servoPos[n] = servoLowPos[n];
        else
            servoPos[n] = servoHighPos[n];

        pointServo[n].write(servoPos[n]);
    }

    // start creating the servo-signals (right from the START with the correct position)
    for (byte n = 0; n < 6; n++) {
        pointServo[n].attach(servoPin[n]);
    }
}


void setupSwitches() {
    for (byte n = 0; n < 6; n++) {
        pinMode(switchPin[n], INPUT_PULLUP);
    }
}

best regards Stefan

huh?
it immediately sets the position after attach().

Hello Greatnorthern

Do you will have more than six turnouts in the future?

Thanks Greg, I made the changes below but the sketch wont compile. The following message comes up on line 25 & 26,` ``pointServo[n].attach(servoPin[n]); was not declared. If you could please look at this for me.```

Wally.

~WRD0000.jpg

Please - post all of the code, and all of the error message.

The code from gcjr in post # 23 does compile !
You simply use the forums copy & paste function

I have read this

Your code is far away from beeing "sophisticated"

I recommend that you learn some basics.
You should not depend on the grace of other users even for such simple things.

best regards Stefan

As requested I have posted the complete code
Thanks Wally

#include <Servo.h>

Servo Srv[6];

const byte servoPin[] =     {  2,   3,   4,   5,   6,   7, }; // pin numbers for servo signals
const byte switchPin[] =    { 8,  9,  10,  11,  12, 13 }; // pin numbers for switch connections
// Uno analog pins      A5   A4   A3   A2   A1   A0
const byte servoLowPos[] =  { 50,  60,  60,  60,  60,  50,  }; // degrees for low servo position
const byte servoHighPos[] = {160, 140, 160, 170, 150, 160,}; // degrees for high servo position

byte servoPos[6];


void setup() {
  Serial.begin (9600);

 for (byte n = 0; n < 6; n++) {
   pinMode (switchPin[n], INPUT_PULLUP);

  if (HIGH == digitalRead(switchPin [n] ))
  servoPos[n] = servoLowPos[n] ;

  else
      servoPos[n] = servoHighPos[n];

      pointServo[n] . attach (servoPin [n] ;
      pointServo[n] . write (servoPos [n]) ;

  

if (sw == LOW) {
    while (servoPos[n] != servoHighPos[n]) {
         servoPos[n] += 1;
         pointServo[n].write(servoPos[n]);
         delay(10);
     }
}
     if (servoMove) {  // only move the servo if the switch has changed
        pointServo[n].write(servoPos[n]);
     }
  }
}

void setupServos() {
  for (byte n = 0; n < 6; n++) {
    pointServo[n].attach(servoPin[n]); 
    servoPos[n] = servoLowPos[n]; // this is just a starting value and may be over-ridden immediately by a switch
  }
}

void setupSwitches() {
  for (byte n = 0; n < 6; n++) {
     pinMode(switchPin[n], INPUT_PULLUP);
  }
}

But not the error message(s), as requested.

Edit: I got this from Wokwi


New Arduino Uno Project - Wokwi Simulator
Build failed!
sketch.ino: In function 'void setup()':
sketch.ino:26:7: error: 'pointServo' was not declared in this scope
       pointServo[n] . attach (servoPin [n] ;
       ^~~~~~~~~~
sketch.ino:26:7: note: suggested alternative: 'Servo'
       pointServo[n] . attach (servoPin [n] ;
       ^~~~~~~~~~
       Servo
sketch.ino:26:44: error: expected ')' before ';' token
       pointServo[n] . attach (servoPin [n] ;
                                            ^
sketch.ino:31:5: error: 'sw' was not declared in this scope
 if (sw == LOW) {
     ^~
sketch.ino:31:5: note: suggested alternative: 'sq'
 if (sw == LOW) {
     ^~
     sq
sketch.ino:38:10: error: 'servoMove' was not declared in this scope
      if (servoMove) {  // only move the servo if the switch has changed
          ^~~~~~~~~
sketch.ino:38:10: note: suggested alternative: 'servoPos'
      if (servoMove) {  // only move the servo if the switch has changed
          ^~~~~~~~~
          servoPos
sketch.ino: In function 'void setupServos()':
sketch.ino:46:5: error: 'pointServo' was not declared in this scope
     pointServo[n].attach(servoPin[n]);
     ^~~~~~~~~~
sketch.ino:46:5: note: suggested alternative: 'Servo'
     pointServo[n].attach(servoPin[n]);
     ^~~~~~~~~~
     Servo

Error during build: exit status 1

It looks like you've just mashed two unrelated sketches together, and expected the compiler to sort out the naming.

The code in reply #23 looks promising.
Just cut and paste it into a blank sketch and see how it goes.

Compare

with

what is so hard about copy & paste a complete sketch?
where complete means from the very first line to the very last line
using this method

and apply this method to

I do not intend to do more. It is too much trouble to replace the PECO switch machines on my main statin section ( about 26 turnouts)

One can only get 6 turnouts per Arduino UNO.

Wally

~WRD0000.jpg

The Servo library claims 12 servos.
Of course, without some sort of expander, you'd need another 12 pins for switches, so with eighteen immediately available I/O pins, that's nine servos and nine switches per Uno.

Hello Wally

Many thanks for your reply.

Please post a picture of the turnouts including the PECO switch machine.

I guess this machine can be simple replace by a 3D printed mounting for the servo.

IIRC, a Mega will do 48 servos. You can also get Mega equivalents in a size similar (identical?) to a classic Uno if space is a constraint.

I need to take a picture of my Peco arrangement.
Wally.

Servo turnout panel, Peco turnout panel and Peco turnot mecnism.



To come back to the software-problem

You have 6 servos controlled by one arduino uno.
The servos shall move to pre-definable postions initiated by a button-press.

Even on power-on each turnout shall be in one of the two end-positions.
This means as soon as the arduino-uno gets power each servo shall move to a well-defined position. ( one end-position of the turnouts).

This is what the code in post # 23 is doing.

As you want a ready to use code with this functionality simply copy the complete sketch of post # 23 into the clipboard by using the copy-symbol that appears as soon as you move your mouse in the upper-right corner of the code-section and do a click

then paste the clipboard-content into an empty sketch and upload the sketch to your arduino.

In case If the sketch that you are using until now has additional code you should post this actually used sketch.

best regards Stefan