Introduction: Model Railroad DCC Command Station V2

28th July 2023: Added PCB Fritzing file for download.

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) The Fritzing file is attached here for download.


Circuit Diagram.

1 off PCB - contact me here for availability

Step 1: Components:

Components available on eBay:

4x4 Matrix Array 16 Key Membrane Switch Keypad £2

2.2 inch 240x320 ILI9341 Serial SPI TFT LCD Display Module £11

15V 2A 30W POWER SUPPLY eBay item 142514174804 £14

Nano V3.0 For Arduino with CH340G 5V 16M compatible ATmega328P 2 x £6 = £12

Motor Driver Module LMD18200T for Arduino £15.

*Voltage Regulators: 3v3 (UA78M33C) 5 for £7

*Voltage Regulators: 9v (7809) in TO220 packages £2

3v3 zener diode £1 for 10

1N4004 rectifier diode £3 for 10

1N5817 Schottky diode £2 for 5

Connectors, wire, vero board, resistors, potentiometer: approx £5

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

The Arduino sketch 'Command_Station_with_keypad_v2.ino' must be loaded onto the Nano next to the DC supply terminal block and 100uf capacitor. Note: the code is in text format, please copy and paste into an Arduino sketch

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

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

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

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

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 Arduino sketch 'Command_Station_Display_jun_2019.ino' must be loaded onto the Nano next to the LCD display pins. Note: the code is in text format, please copy and paste into an Arduino sketch.

"Adafruit_GFX.h" library here

"Adafruit_ILI9341.h" library here

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.