Connecting a Servo Module

To connect a servo module to DCC++EX, you first need to get a module, based on the PCA9685 chip.

PCA9685 Servo Module

These are widely available from eBay, Amazon, etc. for a few dollars.

Note the pin connectors along the left side of the module - these are where you connect to the Arduino.

The 16 columns of three pins along the bottom of the module are where you connect the servos. The pins are arranged so that you can just plug a servo connector directly onto them, but be sure that the wire colours match the colours of the pins, i.e. yellow to yellow, red to red and black to black.

The servo module itself is powered from the Arduino, but the servos themselves contain motors that consume more current than the Arduino is able to supply, and so a separate 5V supply is required for the servos. This is connected to the green terminal block at the top of the module, with terminals labelled V+ and GND. The V+ terminal is connected to 5V and the GND to the 0V (ground) wire of the supply.

Connections to the Arduino are made with four jumper wires (+5V power and GND, and SCL and SDA), as shown on the following diagram:

PCA9685 Servo Module

In DCC++EX, the drivers for the PCA9685 module is already installed, and made available to for use as pin numbers 100-115. A servo is shown in the diagram, connected to the first set of pins on the module. This will be accessed using pin number 100.

Once you’ve made all of the connections, apply power to the Arduino.

Then, in the Serial Monitor, enter the command <D SERVO 100 450>. The servo should move, as long as it isn’t (by some fluke) already in that position.

Enter <D SERVO 100 110> and this time it should definitely move. For the last parameter (servo position) you can use any value between about 105 and 490.

Try <D SERVO 100 450 3> and the servo should move slowly back.

You can use the servo to control turnouts, semaphore signals, engine shed doors, and other layout components, to make your layout more dynamic and exciting. In the picture below, you can see a servo mounted below the baseboard with a piece of wire passing through a slot cut in the baseboard, to operate a turnout.

Servo mount to operate a turnout

And in the next picture you can see a servo that operates a semaphore signal. The signal, and its servo mounting bracket, were 3d-printed on a Creality Ender-3 printer.

Servo mount to operate a Semaphore Signal

Using Servos with EX-RAIL

EX-RAIL supports two methods of controlling servos:

  • Turnouts via the SERVO_TURNOUT directive

  • Animations via the SERVO or SERVO2 directives

Controlling Servos for Turnouts

The SERVO_TURNOUT directive defines a servo based turnout in EX-RAIL, which will appear in WiThrottle apps, Engine Driver, and JMRI in addition to being defined as a turnout within the CommandStation.

As per the EX-RAIL reference, turnouts are defined with the following syntax:

SERVO_TURNOUT(id, pin, active_angle, inactive_angle, profile [, "description"])

The valid parameters are:

  • id = Unique ID within the CommandStation (note these are shared across turnouts, sensors, and outputs).

  • pin = The ID of the pin the servo is connected to, which would typically be the VPin ID of the PCA9685 controller board.

  • active_angle = The angle to which the servo will move when the turnout is thrown (refer below for further detailed information).

  • inactive_angle = The angle to which the servo will move when the turnout is closed (refer below for further detailed information).

  • profile = There are five profiles to choose from that determine the speed at which a turnout will move: Instant, Fast, Medium, Slow, and Bounce (note we don’t recommend Bounce for a turnout definition).

  • description = A human-friendly description of the turnout that will appear in WiThrottle apps and Engine Driver. Note that this must be enclosed in quotes “”.

An example definition for a servo connected to the second control pins of the first PCA9685 connected to the CommandStation, using the slow profile for prototypical operation:

SERVO_TURNOUT(200, 101, 450, 110, Slow, "Example slow turnout definition")

Controlling Servos for Animations

The SERVO and SERVO2 directives allow for servos to be used in various automations within EX-RAIL.

Note that unlike a SERVO_TURNOUT these are not definitions that appear within WiThrottle apps, Engine Driver, or JMRI, but are instead actions designed to be used within EX-RAIL automations.

As per the EX-RAIL reference, these are defined with the following syntax:

SERVO(vpin, position, profile)
SERVO2(vpin, position, duration)

The valid parameters are:

  • vpin = The ID of the pin the servo is connected to, which would typically be the VPin ID of the PCA9685 controller board.

  • position = The angle to which the servo will move when the turnout is thrown (refer below for further detailed information).

  • profile = There are five profiles to choose from that determine the speed at which a turnout will move: Instant, Fast, Medium, Slow, and Bounce.

  • duration = The time (in milliseconds (ms)) for the servo to be actively rotating.

As an example, consider a lineside worker that needs to be moved away from the track when a train approaches, which is controlled by an infrared sensor.

The SERVO is attached to VPin 101 (second control pin on first PCA9685), with a sensor attached to VPin 164 (first pin on the first MCP23017):

AT(164)
SERVO(101, 400, Fast)
DONE

AFTER(164)
SERVO(101, 100, Slow)
DONE

This tells EX-RAIL that when the sensor at VPin 164 is activated, the lineside worker moves quickly back from the track for safety, and then after the sensor has been deactivated, he can leisurely move back to his working position (no one wants to rush back to work right?).

Technical Discussion for Engineers

There are three types of servos, standard or “Positional Rotation”, “Continuous Rotation” and “Linear”

A Standard, positional rotation servo allows a shaft to spin around a central axis to position something like an arm or disk at specific angles. A standard servo can be positioned between 0 and 180 degrees. An example is the SG90 9g Micro Servo

A Continuous Rotation Servo can spin around a full circle continuously like a motor. Instead of providing an angular position that the servo should rotate to, the continuous rotation servo simply has a speed and direction, clockwise or counterclockwise.

Linear Servos use a rack and pinion gear that converts rotary motion to linear motion. A linear servo works just like a Standard Servo and you can control its position along a straight line, forward and back in a similar way by giving it a position.

Pulse width modulation (PWM) sends an electric pulse of variable width to the motor. With PWM there is a minimum pulse, maximum pulse, and a repetition rate. The rotor will turn to the desired position based on the duration of the pulse. When servos are commanded to move, they move to the position and hold the position. A feedback mechanism (usually a potentiometer that rotates with the shaft) adjusts the speed and direction of the motor to be able to hold the correct position.

For our analog servos, the signal or repetition rate is 50Hz, that is once every 20 milliseconds (ms). The duration of the pulses are between 544 and 2400 microseconds (µs) representing 0 and 180 degrees. To derive our 12-bit PWM value, we divide the pulse durations by 20ms and multiply by 4096. That gives us a range of 111 to 491.

Another way to look at this is that with our 12bit ADC (Analog to Digital Converter), which can measure from 0 to 4095, 4096 (100%) is 20ms pulse length and 0 (0%) is 0ms pulse length. We convert 4095 to 100% since you can’t represent the value 4096 in 12 bits.

Note

It is a bit difficult finding datasheets for different servos. For the SG90, we have seen a range listed of 1000-2000µs, which maps to 205-410, and 500 to 2400µs, which is 102 to 490. You define these in JMRI, or in the command station in mySetup.h or via command with “<T id SERVO vpin thrownPos closedPos profile>”.

Tip

Keep a spare slot (we recommend 100) open on your first PCA9685 board so that you can test servo positions with the <D SERVO …> command to connect your servos to and get the exact positions you need.

Servo motors have three wires: power, ground, and signal. The power wire is typically red, and should be connected to the an external 5V power supply. Do NOT connect this to the 5V power of the Arduino! The ground wire is usually black or brown and connects to a ground pin. The signal pin is typically yellow, orange or white and should be connected to a digital pin of the PCA9685.