Model Railroad DCC Command Station V2




Updated 19 Sep 2019: new sketch for Nano (with keyboard) to correct CV1 write of TCS decoders. Please use sketch 'Command_Station_with_keypad_v2.ino'

Updated 1 June 2019: use of Adafruit libraries that now work with the ILI93411 / 2.2 inch 240x320 Serial SPI TFT LCD Display. In the Arduino sketch, replace:
#include "Adafruit_GFX_AS.h" // Core graphics library
#include "Adafruit_ILI9341_AS.h" // Hardware-specific library

#include "Adafruit_GFX.h" // Core graphics library
#include "Adafruit_ILI9341.h" // Hardware-specific library
Download these libraries on GitHub here and here

Minor changes to lines 45 to 47 within the sketch
- new version attached in step 'Arduino Nano With TFT LCD Display'


Update 11th May 2019: amended sketch to display opening screen after 4 seconds delay. Download updated file 'Command_Station_with_keypad_11_may_2019.ino' in step 2

Update 2 May 2019: Modified sketch to fix bug in E-stop where moving the speed pot started loco motion
download latest sketch 'Command_Station_with_keypad_may_2019.ino' in step 2

Update 8 April 2019: Modified sketch to eliminate timing issue when sending repeat data packets. Please download latest sketch 'Command_Station_with_keypad_apr_2019.ino' in step 2

Update 27 Jan 2019: Now includes option of momentary F2 F3 functions for horn sounds, if not required simply comment out the new lines of code in void loop()

if (f2a[locoAdr] == 1){ // momentary action on F2
fun2 = 0; }
if (f3a[locoAdr] == 1){ // momentary action on F3
fun3 = 0; }

Update 16th Aug 2018:
Now includes a CV1 write function to programme loco address numbers. This is a software modification only with no change to hardware. See updated Arduino Nano sketch. To access this CV1 write facility, hold down button 'A' on membrane keypad while turning on power. Ensure that only the loco to be addressed is on the track. Choose loco number 1-19 from the keypad then press 'A' again to programme new value for CV1. See step 3 for more details.

This is version 2 of my original DCC Command Station Instructable.

I have learned a number of things from the original experience about the Arduino Nano, the h-bridge LMD18200t and the TFT LCD display.

1. The analog pins on the Nano may be used for serial communications e.g. A3/A4 for Rx/Tx. The original used D0 and D1 making serial monitoring impossible. I have also used A2 and A5 as a digital outputs to control the on/off of the bridge output in event of over-current. Note: A6 and A7 cannot be used as digital output pins on the Nano.

2. The LMD18200t current sense pins on the actual IC package, do not work well and in some cases not at all. Therefore, I have added a 0.1 ohm 5 watt resistor to monitor current through the bridge. This is sensitive to within 50mA which is ok for the purpose of detecting overloads/shorts.

3. The TFT LCD used here requires a voltage divider from 5v to 3v on the input pins, 1k0 and 1k5 ohm values work fine. Check your TFT requirements and if it can take 5v inputs, the 1k5 resistors are not required. The TFT is slow in response compared to response of turning the speed pot and recording on the display. The time lag gives incorrect values. I have included a special void in the Arduino sketch to transmit speed data only and change one line on the display instead of refreshing the whole display.

4. The DCC command signal timing has been improved by switching state of the output using binary register coding instead of digitalWrite(D10, High) e.g.
DDRB = B00000100; // register B for digital pin 8 to 13, pin 10 as an OUTPUT
PORTB = B00000100; // using register control to speed up switching speed pin 10 switched HIGH (DIR)
PORTB = B00000000; // pin 10 switched LOW (DIR)

5. The input keys on the membrane key pad are selected in void get_key() I have improved the response time taken in the void by using 'case' and 'return' rather than 'if' statements.

6. The NMRA standard requires a continuous flow of DCC data every 30 ms. This has been added to the sketch for speed and direction on all running locos (not for function controls which are only sent when keypad is pressed).

7. The DCC Command packet for 128 speed steps is 4 bytes long whereas the function Commands are 3 bytes long. I have included a means to assemble 4 or 3 byte packets by altering the length of the Message array:
void amend_len4 (struct Message & x) { x.len = 4; z = 4; }
void amend_len3 (struct Message & x) { x.len = 3; z = 3; }

8. On review of the power requirements of the Nano and LCD and the H-bridge voltage (12v to 14v) I have used a 9v regulator to supply the Vin pins of the Nanos and the input of the 3.3v regulator for the LCD. This gives optimum power dissipation on the regulators. The Arduino Nanos should not be relied upon to supply enough current to the LCD display from their 3v outputs.

9. A PCB design from Fritzing and manufacturing in China has enabled me to provide bare PCB's of the circuit included here. If you are interested purchasing one, please search e-bay for 'DCC Command Station PCB' (now available from August 2018)

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Components:

All available on eBay:

1 off PCB eBay link
4x4 Matrix Array 16 Key Membrane Switch Keypad £1. eBay

2.2 inch 240x320 Serial SPI TFT LCD Display Module £5 eBay
Nano V3.0 For Arduino with CH340G 5V 16M compatible ATmega328P 2 x £3.50 = £7 eBay

Motor Driver Module LMD18200T for Arduino £5. eBay
*Voltage Regulators: 3v3 (UA78M33C) £2.53 eBay
*Voltage Regulators: 9v (7809) in TO220 packages £1 eBay

3v3 zener diode £1 for 10 eBay
1N4004 rectifier diode £1 for 10 eBay
1N5817 Schottky diode £1 for 50 eBay
Connectors, wire, vero board, resistors, potentiometer: approx £3
PCB (available on e-bay from Aug 2018) £5.50
Box / Enclosure

*Note: Voltage regulators will run at 23 degrees C above ambient and may require a require heatsink, depending on air circulation within enclosure. If Vsupply is 14v , then a temp rise of 36 degrees C above ambient on 9v Regulator will probably need a heat sink.

Step 2: Arduino Nano With Keypad

Make serial communications between the Nanos using Analog pins A3/A4:

#include "SoftwareSerial" // download this library
SoftwareSerial dcc(A3,A4); // RX TX

The 4x4 membrane keypad is configured in the sketch as follows:

#include "Keypad.h" // download this library

const byte ROWS = 4; //four rows const byte COLS = 4; //four columns
char keys[ROWS][COLS] = { {'1','2','3', 'A'}, {'4','5','6', 'B'}, {'7','8','9', 'C'}, {'*','0','#', 'D'} };
byte rowPins[ROWS] = {2,3,4,5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6,7,8,11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
char key = keypad.getKey();

void SetupTimer2()
This void starts the clock which is amended by the DCC binary code to provide a DCC signal.
Each of 4 byte of loco/speed commands:
byte 1 = loco number
byte 2 = speed steps
byte 3 = speed value / direction / front light on/off
byte 4 = checksum (error)

For function commands, 3 bytes:
byte 1 = loco number
byte 2 = function (F1 to F8) on/off
byte 3 = checksum (error)

A current sense resistor 0.1 ohm 2 watt monitors the current through the h-bridge.
The LMD18200t module used has a max current of 3 Amps
I have set the working limit to 2.6 Amps in the sketch:
void current(){
sensorValue = analogRead(AN_CURRENT);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V) = 4.9mv per division
// 0.1 ohm resistor on current sense gives 200mv at 2 Amps or, 100mv per Amp
// 100/4.9 = 20 divisions per Amp or 20 divisions per 1000mA or 1 division = 50mA
A = 50 * sensorValue ; // mA }

Within void setup() :
Amax = 2600; // max current

Within the void read_loco() :
if (A >= Amax){ // current limit
Atrig = 1;
changed_l = true;
return changed_l; }

The system can control 1 - 19 engines, direction, lights, 8 functions, emergency stop and auto current limit.
The max current of 2.6 amps makes it suitable for all scales including G-scale (garden trains). The mains power supply and electronics are suitable for indoor use only unless you can make it all weather proof. I have the command station in the summer house with rail connecting wires running out through the wall to the track.

Step 3: CV1 Loco Address

Holding the 'A' key down while turning on power, will provide access to the CV1 write feature.

This is achieved in the Arduino Nano sketch through a sequence of reset, page preset and write packets as specified in NMRA S-9.2.3

//CV1 coding for Address only mode

void cv1_prog(){
4 x (preamble (16 x '1') plus reset_packet) // 3 or more required
6 x (preamble (16 x '1') plus page_preset_packet) // 5 or more required
7 x (preamble (16 x '1') plus reset_packet) // 6 or more required
6 x (long preamble (24 x '1') plus cv1_write_packet() // 5 or more required
11 x (long preamble (24 x '1') plus cv1_write_packet() // 10 or more required

void reset_packet()
Creates 'preamble' of 2 bytes of (8 x '1') followed by 3 bytes of '0'

void page_preset_packet()
Creates 'preamble' of 2 bytes of (8 x '1') followed by 3 bytes 01111101 00000001 01111100

void cv1_write_packet()
Creates 'long preamble' of 3 bytes of (8 x '1') followed by 3 bytes 0111C000 0DDDDDDD EEEEEEEE
C=1 write address used here (C=0 verify address)
Value of DDDDDDD is written into CV1
The decoder must be powered off after each CV1 write and switched on again prior to another CV1 write.
This is done by switching the pins on the h-bridge:
Turn ON : PWM = High : Brake = Low. Turn OFF : PWM = Low : Brake = HIGH
To sense the smaller currents, Analog Internal Ref is used during CV1 write
1.1v ref gives 1.08 mv per division, current Acv = 10.8 X sensor value using 0.1 ohm sense resistor
If Acv > 15mA then a valid CV1 write is achieved.

Step 4: Arduino Nano With TFT LCD Display

The Nano used to control the TFT display is configured as follows:

// wac 1 June 2019 used updated Adafruit libraries

#include SoftwareSerial dcc(A3,A4); // RX TX
#include "Adafruit_GFX.h" // Core graphics library
#include "Adafruit_ILI9341.h" // Hardware-specific library
#include "SPI.h"

// hardware SPI pins for Nano
#define _sck 13
#define _mosi 11
#define _cs 10
#define _dc_rs 9
#define _reset 7
Adafruit_ILI9341 tft = Adafruit_ILI9341(_cs, _dc_rs, _reset);

A valid command received from the Nano with keypad must start with 'A', end with '\n' and have 18 ',' characters.
Each valid command is decoded and the result displayed.

4 People Made This Project!


  • Made with Math Contest

    Made with Math Contest
  • Multi-Discipline Contest

    Multi-Discipline Contest
  • Robotics Contest

    Robotics Contest

38 Discussions


Question 4 months ago

Hi Bill, I cannot write CV1 to TCS decoder, "after press "A", it display the current 21mA.

9 answers

Answer 24 days ago

Hi Tao, I have solved the problem with TCS decoders on CV1 write. Please download the latest Arduino sketch 'Command_Station_with_keypad_7_sep_2019.ino'
Sorry it took me so long !!


Reply 21 days ago

Hi Bill
Thanks for your help ! the new version solved the problem, I can run more than one loco in the track.
Thks !


Reply 24 days ago

Thanks ! I’ll try it on monday.


Answer 4 months ago

Hi Tao,
How are you connecting the TCS decoder to the DCC Command Station ?
It must have the loco motor on its output to change CV1. The decoder must be in the loco or it should be ok with a 150 ohm resistor between the motor wires.
Hope this helps.


Reply 4 months ago

Hi Bill
I can control the engine at default address to control it, how to connect the 150ohm resistor ? parallel or series to motor.


Reply 4 months ago

Hi Tao,
If the decoder is installed in the loco, you will not need the resistor.
What value are you trying to give CV1 ?
Ensure the track and wheels are clean.
Not sure what else to suggest.
I am away on holiday till mid next week. I will have another look at this problem then.


Reply 3 months ago

Hi Tao,
Do you still have issues with the writing of CV1 on a TCS decoder ?
I could look at increasing the time delay between write packets to try and resolve this.


Reply 3 months ago

I can't solve the problem yet.


Question 2 months ago

Hi Bill
dave3054 again. I noticed that you uploaded the two older libraries for another question a while ago. I have used them both in the Jan 2019 sketch and the whole thing works perfectly! Points, functions and locos working a treat.
even better now that I have turned my screen round as it was upside down :)

2 answers

Answer 2 months ago

Hi Dave, sorry I did not reply sooner. However you seem to have found a way round the problem! I was going to suggest the issue with the Arduino loading may have been due to the latest Arduino IDE update includes a faster loader for Nanos. The older or clone Nanos require us to choose the older loader from the file menu.
With your success on using the older files makes that unlikely. There may have been a problem with the downloaded libraries for the newer version ?
Thanks for you support and enjoy using your completed project.


Reply 8 weeks ago

Thanks for your reply Bill. The controller is flipping awsom. Works a treat.
all the best


Question 2 months ago on Step 4

Hi Bill
I have your dcc command station board and have fitted all the components. I have downloaded the latest sketches. The "with keypad may 2019" sketch compiles and uploads fine. The "display June 2019" will not compile, error "exit1 error compiling for Arduino nano". I assume I need both sketches one for each Nano, or has my stupidity reached new levels?
any advice please.
kind regards


Question 4 months ago

Bill, by the way, I cannot find the library Adafruit_ILI9341_AS.

4 answers

Answer 4 months ago

Thanks again, Bill.
Have a nice day.


Reply 4 months ago

Thank you vey much, Bill.
An another question: can I manage in some way the DCC Sattion without the display?


Reply 4 months ago

Hi Juan, I have attached the Adafruit GFX AS library for you.
You could use the DCC system without display if you want to try it out using keyboard only.


4 months ago

Hello Bill,
have finally started the construction of the DCC Command Station. It's almost finished, but I have a doubt: instead of your TFT screen I have this shield, whose photos I send you. Can I use my screen? How should the connections be?
Thank you very much for your help.