Introduction: Garden Train - Arduino Wireless NMRA DCC

Further to previous instructable with DCC on dead rail system, I have developed the idea further with a hand held DCC Command Station with keypad and LCD display. The Command Station contains all the coding required for NMRA DCC instructions, however instead of connecting to the rails, the data is transferred by radio module RF24L01+ to a receiver mounted in a truck or under the loco - wherever room permits.

Of course, your locos must be fitted with a decoder of load capability suited to the engine motors.

Step 1: Design of System

The Arduino Pro Mini is at the heart of the design. Using Fritzing to develop the circuit and to produce PCBs.

I was able to use the same PCB for both transmitter and receiver thus saving some costs.

The transmitter has connections for keypad and LCD while the receiver does not require these and uses the H-bridge to supply the DCC output for the loco.

A further development includes connections for a larger H-bridge if required for more powerful locos.

The PCF8574 can be deleted if you use an LCD display that comes with the backpack allowing SCA / SCL connections on the Arduino to feed the display using only 2 wires.

Parts list: Total = approx £60 for DCC Command Station + 1 receiver
Additional receivers cost = £10.00 approx each. + batteries

Arduino Pro Mini. x 2 = £4.00

4x3 membrane keypad = £3.00

20 x 4 LCD display = £7.00

PCF5874 = £1.80

NRF24L01+. radio modules x 2 = £5.80

PCB manufacture for 10 off (or Vero board may be used) = £24 or £4.80 for 2off

3.3 v Regulator = £0.17 (pack of 25 from RS Comp)

5v Regulator LM7805 = £0.30

H-bridge SN754410ne = £3.00

Lloytron re-chargeable 2700 maH AA batteries x 12 = £22.00. (lower maH rated batteries are cheaper)

Capacitors, pots, pins, connectors, etc = £2.00 approx

Enclosure 190x110x60 mm = £8.00

Transmitter - phone charger / battery = £2.00

Step 2: Transmitter

The circuit diagram is shown where D2 to D8 pins on the Arduino Pro Mini are connected to the keypad.
A 100k ohm potentiometer is connected to Analog pin A0 for speed adjustment.
The SDA and SCL pins form the PCF8574 chip are connected to pins A4 and A5 on the Arduino Pro Mini by means of soldered wires to the pins on the top layer of the Pro Mini.

The Arduino sketch is attached for download.

I have used a 20 x 4 LCD display allowing 4 lines of information with 20 characters per line.
The keypad provides the following menu:

1 to 9 = loco address
* = direction
0 = lights
# = Function menu for keys 1 to 8

Basic description of Arduino Pro Mini sketch:
This line of the code arranges the DCC message in HEX format.
struct Message msg[MAXMSG] = {

{ { 0xFF, 0, 0xFF, 0, 0, 0, 0}, 3}, // idle msg

{ { locoAdr, 0, 0, 0, 0, 0, 0}, 3} // 3 byte address


To store the settings for each loco, a series of arrays are set up as follows:

int la[20];// array to hold loco numbers

int sa[20];// array to hold speed values

int fda[20];// array to hold dir

int fla[20];// array to hold lights

int f1a[20];// array to hold fun1

int f8a[20];// array to hold fun8

To enable the DCC instructions to be amended as we go:

For speed instructions:
void amend_speed (struct Message & x) {[0] = locoAdr;[1] = 0x40; // locoMsg with 28 speed steps

For Function instructions:

void amend_group1 (struct Message & x) {[0] = locoAdr;[1] = 0x80; // locoMsg with group one instruction 0x80

The main loop of the sketch:

void loop(void) {
if (read_locoSpeed()) {

send_data_1(); // send data by wireless


send_data_3(); // display data on LCD display

send_data_4();// display data on serial monitor

if (read_function()) {





Update data when the speed changes:

boolean read_locoSpeed()
This detects a new loco address, speed or direction setting and amends the HEX 'data' accordingly.
Here I have specified 28 speed steps and to meet NMRA standard S 9.2, the speed data must be found from a look up table in 'speed_step()'

void speed_step(){
switch (locoSpeed){

case 1: data |= 0x02; break;

case 2: data |= 0x12; break;

case 3: data |= 0x03; break;


case 28: data |= 0x1F; break;

Update data when the functions change:

boolean read_function()

if (fla[locoAdr] == 0) {
data = 0x80;

} //head lights off

if (fla[locoAdr] == 1) {

data = 0x90;

} //head lights on

For each Function:

if (f2a[locoAdr] == 0) {
data |= 0;
}. // Function 2 off

if (f2a[locoAdr] == 1) {

data |= 0x02; // Function 2 on
'data' is built up by combining [ '|=' compound bitwise or] the HEX codes for each Function.

Step 3: Receiver

The circuit diagram is shown where pins 5 and 6 of the Arduino Pro Mini are used to provide the DCC signal supplied to the H-bridge. The H-bridge pairs are connected in parallel to increase current capacity. Depending on the current drawn by the loco, a heatsink may be required to be attached to the 16 pin DIP device, or a heavy duty H-bridge may be connected externally.

The Arduino sketch is attached for download.
The DCC signal is made up from a clock running at 2MHZ

void SetupTimer2() does this job.

The clock include 'short pulses' (58us) for '1' in DCC data and 'long pulses' (116us) for '0' in DCC data.

The loop void, gets data from the radio and if a valid string is found, the data is converted to DCC data.

void loop(void){
if (radio.available()){
bool done = false;
done =, 1); // read the received data

char rc = inmsg[0]; // put character read into this array

if (rc != 0){. // if character is not equal to zero

inString.concat(rc); // build up the message

if (rc == '\0') { // if character is '/0' end of message

Serial.println(inString); // print the assembled message

string(); // de-construct the string message to get DCC instructions

} }}

Step 4: Run the Locos

To avoid interruption of data from running multiple trains on the same track, you must disconnect the contacts between the wheels and the track for each loco and truck employed.

Enjoy free running trains regardless of track conditions - what a difference ! No hassle, no start-stop and no cleaning required.

The batteries I used are re-chargable LLoytron AA x 12. I have built a charger especially for them that charges 6 at a time. (see instructable)