ESP8266 DCC Controller



Introduction: ESP8266 DCC Controller

This is a DCC model railroad controller based on the nodeMCU ESP8266 IOT module. It makes use of other modules commonly available on eBay for the Arduino such as a 1602 LCD display, keypad, jogwheel and I2C backpacks.

The controller implements the JMRI protocol over WiFi and you can control your locomotives directly from one or more smartphones. You will need to download the free EngineDriver (Android) or WiThrottle Lite (Apple) App to your phone or tablet.

The system was designed around low cost components and can run 8 locomotives simultantously drawing a maximum 4 Amps. There are various build options. The lowest cost option is a nodeMCU, an INA219 current monitor and an L298 motor driver module. That's it! Control in this case is via a mobile phone over Wifi.

The local LCD display, keypad and jogwheel are optional. Personally I prefer this kind of tactile interface. Smartphones require you to look at the phone instead of the road...

I designed a system board to hold the nodeMCU, some discrete components, the INA219 monitor and it also gives the option to add an integrated LMD18200T motor controller.

The system can support:

  • 8 locomotives, short or long addresses, 126 or 28 speed steps, 16 functions.
  • 8 turnouts Holds the loco and turnout roster in EEPROM
  • Supports Service Mode programming (prog track) and Program on the Main (POM) for locos and accessory decoders.
  • Does NOT support LocoNet.
  • Does not support DCC++.

If you want a low-cost entry level DCC controller with Wifi support and quite a lot of features, based on open source Arduino software then give this project some consideration. Thanks!


core components

  • nodeMCU 1.0 which is the ESP8266, also known as 12-E.
  • INA219 current monitoring board.
  • 12V dc regulated power supply
  • system PCB
  • 5V regulator + heatsink
  • capacitors, diodes, resistors, headers, dupont jumpers

one of the following motor control boards

  • L298
  • LMD18200
  • IBT2 aka BTS7960B

optionally, for the local hardware user interace DSKY

  • 1602LCD with I2C backpack
  • 4 x 4 matrix keypad
  • I2C GPIO expander PCF8574 to fit the keypad
  • red pushbutton for emergency stop, green for mode
  • rotary encoder, 5 terminal type

Step 1: Choose Your Power Hardware

L298. Lowest cost option is the L298 motor board. The ones commonly available on eBay also have a bonus 5v regulator on them which neatly supplies the logic on the system board. Can support 2A, but you can common its outputs for a total 4A power.

LMD18200T as a separate module. Available on eBay as a stand alone H bridge motor controller. It's robust and can support 4A. If you use this device option you will need to put a 5v regulator on the system board.

LMD18200T built into the system board. You can populate the system board with 5v regulator, some discretes and build in an LMD18200T chip. Both the 5v regulator and LMD need a heatsink.

IBT2. Available on eBay. Dual H bridge claims to support 40Amps. That's an insane amout of power which will easily melt things if it shorts! The system INA219 will shut the system down at max 4A anyway (unless you modiify it to say 8A), but realistically with 8 modern sound decoder locos pulling 500mA each, 4A should suffice.

Chose from one of the above. The next two are required elements.

INA219 this is a current and voltage measuring module. It is an essential part of the design. This high-side device can measure up to 4Amps (as typically configured on a module) and uses an I2C bus to communicate with the nodeMCU. The system is capable of detecting shorts / current overloads within a few tens of milliseconds and will immediately shut down power. This protects your locomotives. A common short-circuit scenario is running a loco over a turnout set against it. If power is not shut down quickly, a couple of amps might flow thorugh the loco pickups and wiring. You don't want that.

12V power supply. A laptop power supply is good here. I have a box full of Dell 65 Watt supplies but these push out 17 or 19V. I step these down to 12V with a Buck Converter (eBay again). The DCC specifications suggest 12 to 14V as a suitable track voltage for HO scale. I prefer to keep it close to 12V. Locomotive decoders often have components which are only rated to 16V. If you can find a 12V laptop supply that can push out 2 or 3Amps, or in fact any modern switch mode PSU plug-pack, great, no need for a buck converter. Make sure it is a regulated output. Typically these will have a ripple of only a few mV. DO NOT use an old DC train set transformer. These push out 12V rectified but unregulated and will fry the electronics.

Step 2: Chose Your Interface Options

Bare bones. No local pushbuttons, display or keypad. No jogwheel. Control is via a mobile phone running EngineDriver (Android) or WiThrottle (IOS). With bare bones, one of the nodeMCU board pushbuttons acts as an emergency stop, or you can wire on a single pushbutton. Or you can hit the emergency stop in the EngineDriver app.

DSKY. Add local pushbuttons for Emergency Stop and Mode. Add a LCD 1602 display and a 4 x 4 matrix telephone style keypad. DSKY = display/keypad.

Jogwheel. If you go the DSKY option, you can also add a Jogwheel. This is my favourite method of control due to the tactile control. Rotate to go faster/slower. Push it down to apply a brake or reverse direction, and even better, if the DSKY is showing the turnout display, you can toggle the turnouts with the keypad AND still drive the active loco through the Jogwheel. Makes shunting operations easy.

Laptop. Some of the system hardware features such as current and voltage trip limits, the IP address and SSID can be set through a web browser. The DCC controller has a default SSID of ESP_DCC and IP of You can also manage the loco and turnout roster through a web browser and programme loco decoders in Service Mode or POM mode. You can also do most of these things through the DSKY. You cannot drive locos through the laptop. It's technically possible with more software, but little point given how good the mobile phone apps are.

Step 3: Hardware Build

OK, you have chosen your options and rounded up the components. Time to build it. I designed a system board PCB and this supports all the various build options. I have a limited number of these for sale, but I will make the Gerber files available to you so you can order your own. If you build the L298+bare bones option, you could hook all the elements up with dupont wires and avoid using the system board. For any of the more complete builds you really need a system board.

System board. This accepts a 12V power feed. Has an 5v regulator, space for the INA219 current monitor and LD18200 H bridge, some discretes and of course the nodeMCU. It also has various jumper options and provides a hookup for the I2C bus and jogwheel.

DSKY + emergency stop and mode buttons. This runs entirely over the I2C bus. The 1602LCD needs an I2C backpack module. You can buy the 1602 with backback as a complete unit on ebay. Several backpack versions are avaiable and the software allows you to set the configuration for the one you have. The keypad is a 4 x 4 telephone matrix keypad. Conveniently an I2C expansion board module is available which fits the keypad exactly and allows us to scan the key matrix over I2C. The emergency stop and mode buttons are wired as pulldowns onto this expansion pack also, which neatly integrates them. Note that the 1602LCD units typically are 5v units. This means we need to run the I2C bus at 5v. Luckily the I2C backpack, I2C expander for the keypad and the INA219 are all 5v tolerant. The nodeMCU is not, it needs to run at 3v3 and so the I2C bus clamping diodes are essential.

Side ramble: The system board provides a jumper option to run the I2C bus at 3v3 but you will find the 1602LCD won't display anything. This is because the LCD bias voltage needs to be 4V lower than Vcc, which is actually a negative voltage if you run the LCD at 3v3. You could unsolder one end of the contrast pot and connect this to a -ve voltage bias. In fact I provide for this on the system board. There's a charge pump that generates -3v on a pin next to the I2C bus pins. It does work.... but... the LCD brightness is then poor because the LED backlight is on 3v3 rather than 5V. Save yourself the fuss and run the I2C bus at 5V.

Jogwheel. Also known as a rotary encoder. You need the vanilla 5 pin type. 2 pins are wired to the pushbutton function. The other 3 are wired to the jogwheel itself. These devices detect which way you are rotating them by encoding a pulse on 2 pins vs ground in various phases. They are dreadfully noisy electrically, and the software uses some clever state-engine logic to clean up the signal. IMHO this is the best interface.

Please read the build.pdf for more detail.

Step 4: Software

Whichever option you build, the software load is the same. You do need to set up global.h to specify the type of LCD backpack and keyboard scanner you are using with the DSKY. If you are not using the DSKY or Jogwheel, no problem, theres no need to set a configuration specially for this, the software just never sees an input from these missing devices.

The nodeMCU can be loaded with the software through the Arduino IDE. Its unlikely you will ever lock yourself out, but if you do the easiest way to fix the system is just reload the software via the IDE.

The software is avaiilable on this github link ESP_DCC_Controller

Lets run through the various modules.

  • Global.h this header file contains the hardware configuration such as the 1602 LCD backpack and the I2C address of this and the keypad scanner. It also lets you set the power driver module you intend to use.
  • ESP_DCC_Controller.ino is kept to a minimum. It calls various start up routines and runs a few timed activities from loop()
  • DCCcore.cpp is the main logic. It manages the loco and turnout roster, generates DCC packets to go to the locomotives, handles the DSKY and current trip.
  • DCCweb.cpp handles the web interface and also supports Websockets to make these interactive.
  • DCClayer1.cpp is the low level code that generates the DCC signal on the track, driven from the DCC packets passed to it from DCCcore. A big shout out has to go to StefanBruens/ESP8266_new_pwm for his low level ESP code relating to PWM techniques which gave me the means through which I could generate a DCC signal directly from an ESP.
  • JogWheel.cpp handles the rotary encoder
  • Keypad.cpp handles the keypad matrix
  • WiThrottle.cpp implements a JRMI V2.0 server and communicates with the mobile apps over TCP sockets. It leverages the ESPAsyncTCP library.
  • You also need to load the Adafruit INA219 library.

See the build document regards the I2C addresses and the LCD backpack configuration. You need to set these in Global.h. After you compile and upload, remember to also select ESP8266 Sketch Data Upload. This will upload the content of the data folder to the ESP SPIFFs memory space. These are the web pages.

Step 5: Integrate and Test

Hardware built, software loaded. I remind you this is ENTIRELY AT YOUR OWN RISK. I take no responsiblity for you damaging any of your locos or decoders. Please double check your soldering and double check the power supply is the correct polarity and voltage is within limits.

First test is just the nodeMCU hanging on its USB cable. This allows us to test WiFi, web pages and the mobile apps.

Through the arduino serial monitor you should see a boot sequence which identifies all the I2C devices connected. It will say none, because there are none right now!

You should be able to see an SSID of ESP_DCC. Connect to this with a laptop and navigate to you should see a web page displaying power status and trip thresholds. Power will probably display as tripped, because the INA is missing and the voltage reading tends to jump to a random high value.

Fire up EngineDriver or WiThrottle on your mobile after connecting to ESP_DCC. the server connection is and port is 18090. The mobile app should connect, and you should see a roster of engines 3,4,5 and 6.

Second test is to fit the nodeMCU into the system board and power up with no locos on the track.

CAUTION: If you leave your laptop connected to the nodeMCU via the USB port, make sure the laptop is running on battery only. When you power up the system board from its own supply, this could create a ground loop if your laptop's own supply is still plugged into the wall. Generally USB ports on laptops are protected but don't take the risk. You are warned. Again its at your own risk and I take no responsiblity for damaged laptops. You do not have to keep the laptop connected. Only do so if you wish to observe the serial port trace messages.

If the laptop is connected you will see a message showing the ESP scanning for I2C devices as it searches for the DSKY. Then it will boot and you will see a welcome message on the DSKY assuming you added one. After a few more seconds, if you scan Wifi from your laptop or phone you should see DCC_ESP.

Final test is with a loco on the track.

Same caution as test 2 regards the laptop if you keep this connected. If trace is enabled in Global.h you will see all the various WiThrottle messages being passed as well as websocket broadcasts. Once you are happy it all works, disable trace in global.h and recompile the software and upload it again to the ESP. Running trace messages all the time is not good for a production environment as it does cause delays in the program loop which might result in Wifi throttle drop outs.

Step 6: Operate and Enjoy

Its time to power up and run some trains!

Please read the operating manual. Remember you can also access the web pages over your mobile phone.

If you have any bug reports, please post them here, or raise them at the Github page.

Step 7: Troubleshooting

DSKY problems

If you added a DSKY but the LCD display does not light up or there are no characters, then check the I2C wiring is correct, check you have set the jumper to the 5v I2C supply position and check you correctly configured the global.h file to match your specific LCD backpack. Also, when the unit boots and is reporting back to the Arduino IDE over the USB link (Serial Monitor) you should see the ESP find your backpack at the nominated address.

Also try adjusting the contrast pot on the backpack, sometimes the contrast is set so low that the characters are not visible.

Wifi problems.
The system will run and connect to laptops and mobiles even when it is just a nodeMCU board dangling on the end of a USB cable. From the IDE serial monitor you should see an I2C scan which will find no devices, and messages indicating start up of the webserver and websockets. At this point the ESC_DCC SSID should appear to your devices.

Microcontroller Contest

Participated in the
Microcontroller Contest

Be the First to Share


    • Barbecue Speed Challenge

      Barbecue Speed Challenge
    • Colors of the Rainbow Contest

      Colors of the Rainbow Contest
    • Arduino Contest

      Arduino Contest