Adding Servo-Controlled Turnouts to DCC-EX Using a PCA9685 and EXRAIL
How to Add Servo-Controlled Turnouts to DCC-EX Using a PCA9685 and EXRAIL
If you're looking for a reliable way to add servo-operated points or turnouts to your DCC-EX layout, the PCA9685 16-channel servo controller is one of the simplest and most cost-effective solutions available.
Combined with DCC-EX EXRAIL, it allows you to control individual points from your throttle while also building automated routes, signalling and interlocking.
In this guide we'll show you how to connect a PCA9685 to your DCC-EX CommandStation, configure the hardware abstraction layer, define servo turnouts and calibrate them for reliable operation.
If you're using the ACI CSB1 Command Station, the Qwiic connector makes connecting a PCA9685 particularly simple, although the same principles also apply to other compatible DCC-EX CommandStations.
For anyone starting from scratch, this is also where a ready-to-run DCC-EX system such as the ACI CSB1 can make life easier. The command station is already assembled and configured, so you can spend more time adding servos, routes and EXRAIL automation rather than building the command station first.
Hardware You Need
- PCA9685 16-channel I2C servo board
- Servos, one per turnout
- Regulated 5V power supply for the servos
- I2C connection to your CommandStation, such as Qwiic on the CSB1 / EX8874 or SDA/SCL pins
- Cables and a common ground connection
Common ground required: the CommandStation GND, PCA9685 GND and 5V servo power supply GND must all be connected together.
Power warning: Do not power servos directly from the CommandStation. Use a separate regulated 5V power supply connected to the PCA9685 servo power input.
Wiring and Initial Setup
- Connect PCA9685 SDA to SDA on the CommandStation.
- Connect PCA9685 SCL to SCL on the CommandStation.
- Connect VCC and GND for the PCA9685 logic side.
- Connect the separate 5V servo power supply to the PCA9685 servo power rail.
- Connect the grounds together: CommandStation GND, PCA9685 GND and 5V PSU GND.
Power up the CommandStation and watch the console log. DCC-EX should list any detected I2C devices, including the PCA9685 address. The default address is commonly 0x40, but always verify this from the log.
If you see:
< No I2C Devices found >
check the SDA/SCL wiring, connector orientation and power connections.
HAL Configuration for the PCA9685
The PCA9685 is declared in myAutomation.h using the HAL(...) macro.
// start vPin, count, I2C address
HAL(PCA9685, 100, 16, 0x40)
The PCA9685 does not appear as normal physical GPIO pins. Instead, DCC-EX assigns each servo channel a virtual pin, known as a vPin. These vPins are then used in your EXRAIL turnout definitions.
vPin to PCA9685 Channel Map
- vPin 100 = PCA9685 channel 0
- vPin 101 = PCA9685 channel 1
- vPin 102 = PCA9685 channel 2
- vPin 103 = PCA9685 channel 3
- ...
- vPin 115 = PCA9685 channel 15
Connecting Multiple PCA9685 Servo Controllers to DCC-EX
If you need more than 16 servo outputs, additional PCA9685 boards can be connected to the same I2C bus. However, each PCA9685 must use a unique I2C address.
A new PCA9685 normally uses the default address:
0x40
You only need to change the address of additional boards - the first PCA9685 can normally be left at its default 0x40 address.
The small A0-A5 solder pads on the PCA9685 are used to change this address. With all of the pads left open, the board remains at 0x40. Bridging one or more pads adds a binary offset to the base address.
| PCA9685 Board | I2C Address | Address Pads to Bridge |
|---|---|---|
| First board | 0x40 |
None |
| Second board | 0x41 |
A0 |
| Third board | 0x42 |
A1 |
| Fourth board | 0x43 |
A0 + A1 |
| Fifth board | 0x44 |
A2 |
| Sixth board | 0x45 |
A2 + A0 |
| Seventh board | 0x46 |
A2 + A1 |
| Eighth board | 0x47 |
A2 + A1 + A0 |
For example, when using two PCA9685 boards, leave the first board unchanged at 0x40 and bridge the A0 solder pad on the second board. This changes the second board to address 0x41.
DCC-EX can then register each controller separately:
// First PCA9685 - vPins 100 to 115
HAL(PCA9685, 100, 16, 0x40)
// Second PCA9685 - vPins 116 to 131
HAL(PCA9685, 116, 16, 0x41)
Both controllers can share the same SDA and SCL connections, but their unique addresses allow DCC-EX to control them independently.
Defining Servo Turnouts in myAutomation.h
Once the PCA9685 has been registered using HAL(...), each servo-operated turnout must be defined in myAutomation.h using SERVO_TURNOUT(...).
Syntax
SERVO_TURNOUT(turnout_id, pin, active_angle, inactive_angle, profile [, "description"]|HIDDEN)
Parameters
- turnout_id - Turnout ID number used by throttles and automation
- pin - Virtual pin assigned to the PCA9685 servo channel
- active_angle - Servo position used when the turnout is thrown
- inactive_angle - Servo position used when the turnout is closed
- profile - Motion profile, such as Instant, Fast, Medium or Slow
-
description - Optional label shown for the turnout, or use
HIDDENwith no quotes to hide it
Start by Centring the Servo
When initially installing a servo, it is good practice to set both the active_angle and inactive_angle to the same midpoint value.
For example:
// First servo, channel 0, vPin 100
SERVO_TURNOUT(1, 100, 250, 250, Fast, "Turnout 1")
// Second servo, channel 1, vPin 101
SERVO_TURNOUT(2, 101, 250, 250, Fast, "Turnout 2")
Setting both positions to the same midpoint value places the servo at a known central position instead of allowing it to move immediately between two widely separated end positions.
This is particularly useful when fitting the servo horn, linkage or mounting arrangement beneath the turnout, because you can establish the mechanical centre before setting the final closed and thrown positions.
Initial myAutomation.h Configuration
Your initial myAutomation.h configuration therefore contains both the PCA9685 HAL declaration and the centred SERVO_TURNOUT(...) definition.
// Register the PCA9685
HAL(PCA9685, 100, 16, 0x40)
// Define the servo at its initial centre position
SERVO_TURNOUT(1, 100, 250, 250, Fast, "Turnout 1")
Save myAutomation.h, recompile the CommandStation firmware and upload it to your CommandStation.
When the CommandStation restarts, the PCA9685 and turnout definition will be loaded and the servo can be centred before its final travel is calibrated.
Calibrating the Servo with EX-Toolbox
Once the servo has been centred and the mechanical linkage is correctly positioned, the next step is to determine the final closed and thrown positions.
The EX-Toolbox Android application includes servo controls that allow you to adjust the servo position interactively without repeatedly editing and recompiling myAutomation.h while searching for the correct values.
Before adding final ballast and scenery around your pointwork, spend time testing each servo and adjusting its travel. It is much easier to correct servo movement, linkage geometry or point alignment while the track is still fully accessible.
- Start with the servo defined at its midpoint, for example
250, 250, inmyAutomation.h. - Compile and upload the configuration, then reboot the CommandStation so the servo moves to its centred position.
- With the servo centred, position the servo horn and linkage so the turnout mechanism is approximately centred mechanically.
- Open the servo control in EX-Toolbox.
- Adjust the servo carefully towards one turnout position until the point blades close correctly without excessive pressure or strain.
- Record this value as either the active or inactive position.
- Move the servo in the opposite direction until the turnout is correctly positioned at the other end of its travel.
- Record the second value.
- Enter the two final values into the corresponding
SERVO_TURNOUT(...)definition inmyAutomation.h. - Save
myAutomation.h, recompile the CommandStation firmware and upload it again. - After the CommandStation restarts, test both turnout positions and make any final adjustments if required.
Making the Calibrated Positions Permanent
The values found using EX-Toolbox are used to determine the correct travel for the individual turnout. Once you are happy with both positions, enter those values into the servo definition in myAutomation.h.
For example, if EX-Toolbox shows that the turnout operates correctly at positions 120 and 400, update the definition to:
SERVO_TURNOUT(1, 100, 120, 400, Fast, "Turnout 1")
Save the file, recompile the CommandStation firmware and upload it again. These calibrated values are then part of the permanent CommandStation configuration and will be restored whenever the CommandStation starts.
Testing the Finished Turnout
You can then test the calibrated turnout directly using turnout commands.
Closed:
<t 1 C>
Thrown:
<t 1 T>
Many throttles and consoles require the angle brackets < > around the turnout commands. Do not omit them.
Example Block: Four Servos
Once each servo has been centred and calibrated, several turnout definitions can be added to the same PCA9685 configuration.
// PCA9685 mapped at vPins 100 to 115
HAL(PCA9685, 100, 16, 0x40)
// Define four calibrated turnouts
SERVO_TURNOUT(1, 100, 150, 300, Fast, "Turnout 1")
SERVO_TURNOUT(2, 101, 180, 280, Fast, "Turnout 2")
SERVO_TURNOUT(3, 102, 140, 280, Fast, "Turnout 3")
SERVO_TURNOUT(4, 103, 200, 300, Fast, "Turnout 4")
Note: The servo angle values shown above are examples only. Every turnout installation is different, so the final active and inactive angles will vary depending on the type of servo, mounting position, linkage geometry and turnout being used. Use EX-Toolbox to determine the correct values for each turnout.
Using EngineDriver or Other Throttle Apps
When using EngineDriver on Android to control turnouts:
- Connect EngineDriver to your DCC-EX system.
- Once connected, EngineDriver should briefly display Points Loaded.
- Tap the three dots in the top-right corner.
- Select Turnouts/Points.
- You should see the turnouts you have configured.
- Tap Throw or Close to operate each turnout.
Once configured, EngineDriver automatically lists every turnout you've defined, allowing you to operate them directly from your Android device.
Using ONTHROW and ONCLOSE
This is where things start to get interesting.
ONTHROW and ONCLOSE let you trigger other actions automatically when a turnout moves. This is useful for pairing points, setting signals, building simple interlocking or triggering other layout automation.
These commands are one of the reasons EXRAIL is so powerful, allowing point movements to trigger other automated actions around your layout.
This is exactly the approach used on the Holgate exhibition layout, where EXRAIL automatically sets routes during public demonstrations, helping trains move reliably through complex trackwork.
Example: Linking Two Turnouts Together
ONTHROW(1)
THROW(2)
DONE
This will throw turnout 2 automatically when turnout 1 is thrown. You are not limited to just one extra action inside an ONTHROW() block.
Example: Setting a Signal When a Turnout Closes
ONCLOSE(3)
RED(Signal_ID)
DONE
In this example, a signal is set to red when turnout 3 is closed.
Once you start using ONTHROW and ONCLOSE, they open the door to far more automated operation without needing complex logic.
For a condensed version of the setup and configuration process, see our DCC-EX Servo Configuration Guide .
Troubleshooting
| Problem | Likely Cause | Solution |
|---|---|---|
| PCA9685 not detected | Wrong wiring or I2C address | Check SDA/SCL wiring and verify the address in the console log |
| Servo not moving | Power issue | Confirm the 5V supply and common ground connection |
| Servo chatters or jitters | Over-travel or weak power supply | Adjust the servo angles and use a stable 5V supply |
| Servo buzzes continuously | End stop is too tight | Reduce the travel angle slightly so the servo is not under constant strain |
| Wrong channel moves | Incorrect vPin mapping | Recheck the vPin to PCA9685 channel mapping |
Taking It Further
Once you're comfortable controlling servo turnouts, EXRAIL allows you to:
- Automatically align routes
- Control colour light signals
- Build simple interlockings
- Operate hidden staging yards
- Trigger accessories and layout animations
- Automate train movements
The same principles can be used on small home layouts or larger exhibition layouts where reliable turnout control and automation are important.
If you would rather begin with a ready-to-run DCC-EX command station, the ACI CSB1 provides a simple starting point for train control, servo-operated turnouts and future EXRAIL automation.
With the PCA9685 configured, your servo turnouts calibrated and EXRAIL handling the automation, your DCC-EX CommandStation is ready to control individual points or fully automated routes with confidence.