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
If you add another PCA9685, give it a different I2C address and a new vPin block:
HAL(PCA9685, 116, 16, 0x41) // vPins 116 to 131
Defining Servo Turnouts in myAutomation.h
After registering the PCA9685, define each servo turnout using SERVO_TURNOUT.
Syntax
SERVO_TURNOUT(id, vPin, active_angle, inactive_angle, profile, description)
Parameters
- id - Turnout ID number used by throttles and automation
- vPin - Virtual pin assigned to the servo
- active_angle - Servo position for thrown
- inactive_angle - Servo position for closed
- profile - Motion profile, such as Instant, Fast, Medium or Slow
- description - Label shown for the turnout, or use HIDDEN with no quotes to hide it
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")
Both active and inactive angles are initially set to the same value, such as 250. This prevents the servo from unexpectedly sweeping across its full travel when first powered. Once everything is wired correctly, each position can be adjusted individually.
Adding the Configuration to myAutomation.h
The HAL(...) and SERVO_TURNOUT(...) commands shown above are added to your myAutomation.h file, which is part of your DCC-EX CommandStation configuration.
Start by adding the HAL(...) declaration to register your PCA9685. Then add one SERVO_TURNOUT(...) entry for each servo-operated turnout you wish to control.
// Register the PCA9685
HAL(PCA9685, 100, 16, 0x40)
// Define your servo-operated turnouts
SERVO_TURNOUT(1, 100, 150, 300, Fast, "Turnout 1")
SERVO_TURNOUT(2, 101, 180, 280, Fast, "Turnout 2")
Once you have added or updated these entries, save myAutomation.h, recompile the CommandStation firmware and upload it to your CommandStation. When the CommandStation restarts, your new turnout definitions will be available for calibration and operation.
Calibrating Servo Angles
Before adding final ballast and scenery around your pointwork, spend time testing each servo and adjusting the travel. It is much easier to correct servo movement, linkage geometry or point alignment while the track is still fully accessible.
- Start with both angles equal, for example
250, 250. - Use the EX-Toolbox Android application to make small adjustments to the servo position.
- Move the servo carefully until the turnout blade aligns correctly without stressing the mechanism.
- Record the correct closed and thrown values.
- Update your
SERVO_TURNOUT(...)entry inmyAutomation.h. - Save
myAutomation.h, then recompile the CommandStation firmware and upload it to your CommandStation. - Test the turnout using EngineDriver, EX-Toolbox or EXRAIL commands. Repeat the process until you are happy with the servo positions.
Once the updated firmware has been uploaded, you can test the turnout using EngineDriver, EX-Toolbox or EXRAIL 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 After Tuning
SERVO_TURNOUT(1, 100, 120, 400, Fast, "Turnout 1")
Example Block: Four Servos
// PCA9685 mapped at vPins 100 to 115
HAL(PCA9685, 100, 16, 0x40)
// Define four 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.
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.