Introduction: Model Railway DCC Arduino Wireless Commands on a Dead Rail System

Picture of Model Railway DCC Arduino Wireless Commands on a Dead Rail System

Further to my previous Instructable on a wireless DCC control of a garden train, I have developed a method of wireless transmission of DCC packets from a Command Station to allow dead rail control of locomotives. The basic design is covered here on the circuits and Arduino coding required. The circuits fit into 'G' garden scale locos. However, I leave it to the reader to develop this system into a smaller size for mounting into HO / OO scale trains.

The system was originally developed using the uRF328 (Arduino Uno with wireless). The nRF24L01+ along with an Arduino Mini Pro provides a cheaper option, therefore the system has been adapted to use these modules.

Download the Arduino driver for nRF24L01

Step 1: DCC Packet Transmitter

Picture of DCC Packet Transmitter

Arduino Mini Pro

nRF24L01 wireless transceiver
SN754410 H-bridge
DC regulator 5v output
DC regulator 3v3 output
Rectifier diodes 1N4001 (2off)
Resistors 10K and 4K7
Capacitors 22uf, 3.3uf, 3.3uf

The circuit above, is the transmitter. A pair of resistors reduces the input voltage to acceptable levels for the Mini Pro. I used the 5volt version of the Mini Pro. The 3.3v version may be used which would eliminate the need for a 5 volt regulator. The Arduino code is based on great work done by Geoff Bunza in the Model Railroad Hobbyist Magazine forum.

The loco commands are extracted from the DCC signal. The packet data is therefore isolated from the signal and transmitted as digital instructions to the receiver via the nRF24.

// nrf24 - transmit DCC data 4 Oct 2016

#include "SPI.h"   
#include "RF24.h"  
#include "NmraDcc.h"

int msg[1];
 RF24 radio(9,10);
 const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
 NmraDcc  Dcc ;
 DCC_MSG  Packet ;
 struct CVPair{
  uint16_t  CV;
  uint8_t   Value; };

void setup() {

// Setup which External Interrupt, the Pin it's associated with, disable pullup., 2, 0);
// Call the main DCC Init function to enable the DCC Receiver
  Dcc.init( MAN_ID_DIY, 100,   FLAGS_DCC_ACCESSORY_DECODER , 0 ); 

void loop(){

extern void notifyDccMsg( DCC_MSG * Msg ) {
 if( ( Msg->Data[0] == 0 ) && ( Msg->Data[1] == 0 ) ) return;  //reset packlet
 if( ( Msg->Data[0] == 0b11111111 ) && ( Msg->Data[1] == 0 ) ) return;  //idle packet   
String s1 = String(Msg->Data[0], DEC) + ",";
String s2 = String(Msg->Data[1], DEC) + ",";
String s3 = String(Msg->Data[2], DEC) + ",";
String s4 = String(Msg->Data[3], DEC) + ",";
String theMessage = ("DD," + s1 + s2 + s3 + s4 + '\0');
  int messageSize = theMessage.length();
  for (int i = 0; i <= messageSize; i++) {
    int charToSend[1];
    charToSend[0] = theMessage.charAt(i);

Step 2: DCC Packet Receiver

Picture of DCC Packet Receiver

Arduino Mini Pro
nRF24L01 wireless transceiver
SN754410 H-bridge
Step up module 5v to 3v3 (or 3v3 battery)
Step down module 5v to 12v (or 12v battery)
Capacitors 220uf, 220uf, 100nf

The receiver decodes the wireless signal and extracts the loco instructions. These instructions include all DCC command data for loco ID, speed and various functions. The instruction data is combined with the DCC command clock that runs on the receiver Arduino Mini Pro. The output from pin 6 and inverse output from pin 5 provides the input for the H-bridge.

Update 4 Oct 2016:

To decrease processing time, the Arduino code has been modified and now only accepts one loco address in line 36 (int locoAdr = 3).
The use of preamble + 3 bytes or preamble + 4 bytes (depending on DCC Command station in use) must be entered into line 53 { { locoAdr, 0, 0, 0, 0, 0, 0}, 3} // enter 3 for 3 byte and 4 for 4 byte
I have not been able to complete this automatically in the Arduino code as yet.
Also, I have removed the 'printf' functions and other radio functions not required and the speed is a lot better.

The nRF24L01 internal supply is very unstable and a 220uf capacitor must be connected across the +/- supply pins.

I have used one pair of the SN754410 H-bridge, the load capacity may be increased by connecting the other pair in parallel.

By using a suitable set of LI-Poly batteries to provide 3v3 and 12v supplies, the step up and step down modules may be eliminated.


Martinkirkby (author)2016-11-24

hello Bill

Looks like it's just you and me getting excited about DCC over wireless, once again thanks for making it happen for me.

I think there is a fear of the small LiPo battery's etc, my "on track " charging circuit means that the battery becomes a "fit and forget" part of the equation when running with other locos on a DCC powered track and with over 2hours of running time with a converted Hornby OO gauge steam loco with no track power at all.

Yes it's day to day job is pulling the track cleaning unit, that's until we can get the other 50+ locos converted.

Still on the bench with Geoffs loco decoder, pin 6 to 2 showed no sign of life?

I hope you still think it was a good idea ;)

Thank you again


SimonD133 (author)Martinkirkby2017-11-07


There are many interested in this, but they generally frequent model railway forums, the most appropriate is the “Dead Rails” part of the freerails forum:

Hope that is useful!


Martinkirkby (author)SimonD1332017-11-07

Hello Simon
I see Bill and I are not alone ;) yes I follow the site you have linked, always looking for inspiration!
The rise of Arduino has offered one possible alternative to RC/battery Locos, we use them mainly as DCC Accessory decoders (for servos LEDs etc) also for S88n 0V detectors but if like Bill I can fit one in a loco along with a DCC Decoder I get a DCC WiFi/battery Loco.
Geoff Bunza has done many great Arduino/DCC projects and I will continue to develop them hopefully using Bills DCC WiFi code.
As for Bluetooth it’s looking expensive and without a DCC bridge it’s a dead end, most users like their “hand set” it’s usually the thing that decides which system they buy, like most tech they only use 20% of the features and here in the UK I really do not see the other 50% of the users ever moving to DCC at all! So the manufacturers are not looking to the UK for inspiration.
Thanks again for taking the time to post.

SimonD133 (author)Martinkirkby2017-11-07

I am in the U.K. as well.

The best handset I have is the one I just bought from Tam Valley, for their now defunct DRS. If I can get that to “drive” a base system, I will be happy.

BillC35 (author)Martinkirkby2016-11-28

I have upgraded 2 of my garden trains with the wireless DCC system. So yes I do think it was a great idea from you Martin. The old LGB loco needed a more powerful battery. I am currently using a small lead-acid 12v battery from an alarm system. It sits in a modified truck along with the Arduino circuit. This is much easier in these large scale trains of course. I agree, the Li-Po batteries are a bit scary for some. I use the Li-Ion type in my diesel engine which has space under the floor to house them.

Martinkirkby (author)2017-09-02

hello Bill

You are going to have to help me out here, are you transmitting all the NMRA DCC or just the speed values?

I have loaded your latest receiver version which is comparable with your new DCC command station according to your latest post but I can not get the F1 etc to function and also the motor control is still slowing above 60/70% power ?

Does the loco decoder need its speed table programming i.e. CV 5 +6 and a Start Voltage CV2? As I am writing this I now feel a little foolish to have not tried it!

As I have Geoffs Mobile Decoder on test I understand it does not have a "speed Table" function as it's really just an Accessory Decoder with Servo/Motor control added, so I might just focus my effort on getting a "off the shelf" loco decoder working.

Thanks in advance


BillC35 (author)Martinkirkby2017-09-02

Hi Martin

I think I may have confused you with my last reply. Are you using the 'DCC packet Transmitter' and 'DCC packet receiver' circuits as shown above? If so, the Arduino code in this intractable should work as it is simply taking the DCC commands from your Command Station and transmitting the complete DCC data (including functions). I was using a Bachmann and a Compact (Atlas) DCC command stations which both work fine. Maybe your system uses 4 bytes (plus preamble). I have included this option in the code but I have not tested it. The Arduino code in my new intractable is not relevant to the above circuit - sorry if I misled you. Maybe you could send me a copy of your circuit diagrams to let me understand what you are doing ?

Martinkirkby (author)2017-08-31

hello Bill

I hope you have enjoyed the garden layout this year, I have your project back on the bench and have it connected via pin 6 to Geoffs mobile decoder (also to a standard DCC loco decoder for comparison via the motor driver IC) the wire link between Arduino mini's needs to be < 20mm (pin6 to pin 2) to work.

All works as expected if the decoder address is set in the code, however the speed steps above 60% do reduce instead of increase? but only on Geoffs decoder.

Have you any progress on the code to make any more of the DCC commands

available ie F1 F2 etc or being able to pass the decoder address via the nrf24

instead of hard coding it for each loco/Arduino?

BillC35 (author)Martinkirkby2017-09-01

Hi Martin

Yes, weather permitting, I have run the garden train successfully without the problem of dead spots in the track. Only leaves and twigs spread on the line by foraging birds, need to be swept away first. What a difference the wireless system makes!

Some of your questions are answered in my latest intractable, see:

On further examination of the speed code required I found an error corrected in the new code within this intractable. A look up table is required to enable the speed steps.

garyk007 (author)2017-05-16

As as complete newby to Garden Railroads I think this is great.

Any chance someone could put down the RS product codes, as I would like to order the parts from one location.

When I search on the RS site I get about a dozen items for the same code, eg the 5 volt regulator.

Keen to have a try with my limited electronics knowledge.

BillC35 (author)garyk0072017-05-16

Buy the Arduino pro mini on eBay

You will need a CH340 driver also

RS stock numbers for other parts:

nrf24l01 885-5748

5 v reg. 298-8508

3.3v reg 686-9552

sn754410 h-bridge. 527-704

0.1uf cap. 108-2700

220uf cap. 526-1480

10k ohm resistor. 150-928

4.7k ohm resistor. 151-000

1n4001 diode. 628-8931

3.3uf cap. 475-9289

22uf cap 449-1012

garyk007 (author)BillC352017-05-17

Thanks so so much Bill

Just cant find the 3.3uf cap. 475-9289 on the RS site?

Any alternatives to this?

BillC35 (author)garyk0072017-05-17


You should find this cap here

If not any 3.3 uf 25 volt (or greater) capacitor will do.
Please note, the sn754410 h-bridge I use is suitable for train motors less than 2 Amps. If you have larger motors > 2Amps, you should use a more powerful H-Bridge.
Also, I found the 12v supply to be too low and now use 14.4v batteries (12 x AA re-chargeable NiMh (1.2v each)). These are mounted under the floor of the home made diesel (DMU) or can be placed within a truck or carriage of the train with connecting cables.
garyk007 (author)BillC352017-05-17

Thanks Bill

Plan on using this with some Bachmann G scale locos powered by 14volt batteries as you now do.

Not sure on the Amp draw but I don't think they should draw over 2A as I wont be running long trains and don't have any gradients.

Is there another H bridge that I should use just to be on the safe side?

Thanks again for all your help, really kind of you

BillC35 (author)garyk0072017-05-17

Hi Gary

Another h-bridge that supplies up to 3 Amps is this one on eBay (from Hong Kong). I have used this on my DCC Command Station project.

Happy to help.

Martinkirkby (author)2016-09-26

hello Bill

I will have to read this twice! But I think you have "nailed it" really can not wait to upload the code and give it a try.

Great idea to make it a DCC to DCC end to end wireless solution with the H-Bridge at the receiver end, if I want to use Geoffs "mobile decoder" can I just connect pin 06 PWM from the Arduino to pin 02 on the mobile decoder to give it a try? In the long term the plan would be to incorporate your code with Geoffs to give a single Arduino /nRF24 (basic wireless DCC Decoder) not sure if the clock/timings and I/O are compatible :(

Buts that's in the future, this gives me a great stepping stone to my Battery/wifi loco project and I can keep my very expensive sound decoders working :) without having to clean the wheels and track every few weeks.

Best Regards


BillC35 (author)Martinkirkby2016-09-27

It should work:- pin 6 Arduino to 2 on mobile decoder. To get the speed packets, your code in the mobile decoder should be similar to mine as Geoffs filters out all non-function packets.

I have found variations on the output of different DCC Command stations on both packet contents and voltage levels. e.g. Bachmann EZ operates from a 16 volt supply (dangerously high for some decoders!), whereas my own runs from 12volts. This will make a difference to the resistor chain (10k / 4k7) on the input to the Arduino.

Good Luck and thanks again for the ideas.


Martinkirkby (author)BillC352016-09-30

hello Bill

Finally got a couple of hours spare, put it all together with only one problem so far!

The Reciver code throws the error "void value not ignored as it ought to be" on line 182 .... done =, 1);

I have // it out to get it to upload, the serial monitor shows the rNF24 info but no received commands (the Transmitter does show commands in serial monitor) ?

Hope it's just a typo ?



BillC35 (author)Martinkirkby2016-10-01

Hi Martin,

I do not get this error. Have you got all the library files included for the nRF24.h and nRF24L01.h? There area few entries in the Arduino forum that cover this error code. Have you the latest Arduino IDE 1.6.12 ?

The radio will not work if this line is commented out (//)

By the way, what Command Station are you using ? Does it supply a 3 byte address or 4 byte ? My code is for 4 byte. I will develop code for 3 byte (or both soon). The nRF24 radio is quite slow and adds a noticeable delay to transmitted commands which might be a problem. Need to look into this further.



Martinkirkby (author)BillC352016-10-02

hello Bill

Thank you for the help with this as I assume the problem is with my setup!

Arduino is 1.6.12

RF24 library is TMRh20 Ver 1.1.7

My guess is this library is the problem,whilst up to date it is not the one you used? If I remove the done= from line 182 it builds and receives the DCC command but only once i.e the loop is stopped after the first run. Probably due to the Bool done test?

I am using the SPROG 2 as a bench test unit in service mode. (Have not tried it in Opps mode yet)

I also have ESU Ecos and Roco command stations.(no tested it yet with these)

Re the 3/4 Byte my understanding was that the Basic Packet Format (NMRA) is 4 Bytes, preamble (1byte) and 3 command Bytes.

The Extended Packet Format is upto 6 Bytes.

I see Geoff uses Alex Sheppards library NmraDcc.h to handle the Packet formats.

Re the speed of the RF24. Is it possible that the serial.println is slowwing thing up? I have seen others comment them out once they have their projects debugged.



BillC35 (author)Martinkirkby2016-10-04

Hi Martin

You should use the Maniacbug library driver for the nRF24

Arduino driver for nRF24L01RF24: Driver for nRF24L01(+) 2.4GHz Wireless Transceiver

RF24: Driver for nRF24L01(+) 2.4GHz Wireless Transceiver

I shall add this detail to the Instructable

To decrease processing time, the Arduino now only accepts one loco address in line 36 (int locoAdr = 3). The use of preamble + 3 bytes or preamble + 4 bytes (depending on DCC Command station in use) must be entered into line 53 { { locoAdr, 0, 0, 0, 0, 0, 0}, 3} // enter 3 for 3 byte and 4 for 4 byte
I have not been able to complete this automatically in the Arduino code as yet.

Also, I have removed the printf functions and other radio functions not required and the speed is a lot better.



Martinkirkby (author)BillC352016-10-04

hello Bill

You have been very busy!

It has been quite the learning curve on this one! Thank you for the library link, I looked at that one but it was quite old and there were a few more recent folks to it (newer is not always better it seems).

So my SPROG2 is 4 Bytes, not a problem setting that one, probably low on the "features list" to fix in software. As users give feedback you could create a list of command stations.

I have added a fixed wifi address of 108 (above most domestic wifi etc) also reduced the speed to 250kbps to help with data reliability and set the power to Low (as it's on a bench!) they can go back up once it's in a loco.

With the fixed decoder address 3 hard coded my set up is quite reliable forward/reverse and stop are all ok (just the odd time when at full speed it fails to respond to a slower speed? Serial monitor reset the Arduino so I am not sure why it stopped). The forward/reverse LEDs were working but have now stopped, not sure why yet?

I am still on "training wheels" when it comes to software so please forgive me if I say something inappropriate ;) but I am enjoying learning.

Good to hear the speed has improved, I have also seen the use of millis() to improve code speed? I read about it and had to have a lie down afterwards! :)

Thanks again


About This Instructable




More by BillC35:Garden Train - Arduino Wireless NMRA DCCArduino - adjustable & smart battery charger Model Railway DCC Arduino wireless commands on a dead rail system
Add instructable to: