Fun with Arduino 29 DCC Accessory Decoder

Modern model railroads are digital controlled, using the Digital Command Control (DCC) protocol, whereby data is embedded in the AC voltage that is put on the track to drive the trains. DCC accessory- and servo decoders are available on the market to decode the DCC data and to act on it if the command was meant for their address. If we can use an Arduino to control our accessories and servos via DCC we can reduce cost by a factor 10. The good news is … we can!

Read on below the video …

 

Hardware

The DCC signal is an alternating voltage somewhere between 12 and 24V, depending on your DCC Command Station settings. We use a small electronic circuit to translate this to 5V, to safely connect it to our Arduino.

DCC-Opto

Beware that standard resistors have a 1/4W power rating … the 1k input resistor can get hot if your track voltage exceeds 15V. In that case use 2x2k2 in parallel.

We can’t use just any opto-coupler. The 6N137 is a fast one, which is needed because DCC decoding relies on measuring pulse width: 50µs is a ‘1’, 100µs is a ‘0’. A slow opto-coupler could distort this timing.

The output of the opto-coupler is connected to Arduino pin 2. This pin provides the hardware interrupt mechanism that is used with the Arduino DCC data decoding library. Do not change this pin or your DCC decoder won’t work.

Software

The software for a DCC accessory decoder is remarkably simple. Well … this is not entirely true, it is complex, but the complex part is taken care of in the DCC library … all we have to do is: #include <DCC_Decoder.h>

The DCC library can be downloaded here. Unzip it and move the folder to your Arduino libraries folder, usually found in My Documents/Arduino/libraries.

We need to configure our accessories. We fill in how many accessories are connected to this Arduino:

#define NUMACCESSORIES 2 // Enter the number of accessories here

Then in void setup() we fill in their Arduino pin numbers and the DCC addresses we want them to react to:

accessory[0].address   =  1; // DCC address
accessory[0].outputpin = 13; // Arduino pin

accessory[1].address   =  2; // DCC address
accessory[1].outputpin = 12; // Arduino pin

In this example only 2 accessories are configured. To add more, copy & paste, change the index pointer, pin number and DCC address.

The code for a complete DCC accessory decoder. The code contains a function (more about functions in a later later video) called: void BasicAccDecoderPacket_Handler(). This function switches our accessories on or off, based on DCC data read via the library. IMPORTANT: Roco decided to shift the addresses by 4. I don’t know why they did that, but if you use a Roco Maus or Z21, uncomment the line that says address = address  – 4.

#define NUMACCESSORIES 2 // Enter the number of accessories here

// GO TO setup() TO CONFIGURE DCC ADDRESSES AND PIN NUMBERS

#include <DCC_Decoder.h>

typedef struct DCCAccessoryData {
  int   address;   // User Configurable DCC address
  byte  outputpin; // User Configurable Arduino pin
  byte  dccstate;  // Internal use DCC state of accessory, 1=on, 0=off
};
DCCAccessoryData accessory[NUMACCESSORIES];

// The DCC library calls this function to set / reset accessories
void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data) {
  address -= 1;
  address *= 4;
  address += 1;
  address += (data & 0x06) >> 1;
  // address = address - 4; // uncomment this line for Roco Maus or z21
  boolean enable = (data & 0x01) ? 1 : 0;
  for (byte i=0; i<NUMACCESSORIES; i++) {
    if (address == accessory[i].address) {
      if (enable) accessory[i].dccstate = 1;
      else accessory[i].dccstate = 0;
    }
  }
}

void setup() { 
// CONFIGURATION OF ACCESSORIES
// Copy & Paste as many times as you have accessories 
// The amount must be same as NUMACCESSORIES
// Don't forget to increment the array index
  accessory[0].address   =  1; // DCC address
  accessory[0].outputpin = 13; // Arduino pin

  accessory[1].address   =  2; // DCC address
  accessory[1].outputpin = 12; // Arduino pin
// END OF CONFIGURATION OF ACCESSORIES

  DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);
  DCC.SetupDecoder( 0x00, 0x00, 0 );

  for(byte i=0; i<NUMACCESSORIES; i++) {
    pinMode     (accessory[i].outputpin, OUTPUT);
    digitalWrite(accessory[i].outputpin, LOW);
  }
}

void loop() {
  DCC.loop(); // Call to library function that reads the DCC data

  for(byte i=0; i<NUMACCESSORIES; i++) {
    if (accessory[i].dccstate)
      digitalWrite(accessory[i].outputpin, HIGH);
    else
      digitalWrite(accessory[i].outputpin, LOW);
  }
}

Just 60 lines of code … that’s it. The video shows it under test with my DR5000. I have 6 LEDs connected to pins 14-19 (A0-A5). The DCC output is connected to the opto-coupler input, a Switch window is opened and when I toggle DCC addresses 1 – 6 the LEDs switch on or off. Yes … that works perfect!

In the next video we are going to make a DCC servo decoder.

— 0 —

 

 

9 thoughts on “Fun with Arduino 29 DCC Accessory Decoder

  1. Hallo Rudy,

    Als ik je voorbeeldbestand compileer, dan krijg ik de onderstaande melding. Ik heb dan nog niets aangepast en alleen van te voren de DCC bibliotheek geïnstalleerd. Wat gaat er fout?

    ——————-
    C:\Users\Gebruiker1\Documents\Arduino\sketch_dec14c\sketch_dec14c.ino:7:1: warning: ‘typedef’ was ignored in this declaration

    typedef struct DCCAccessoryData {
    ——————-

    Groeten, Mark

    Like

  2. Hi Rudy,
    This is a great code and circuit, thank you. When trying to use it to control 16 outputs through 2 sets of 8 x relays, the digital ports 3 to 12 work fine but with the analog pins A0 to A5 (13-18) the reaction is terribly slow, useless in practice. Any clue? Thank you. Joaquin.

    Like

    • Well, that is strange, I never noticed any delay on A0-A5. Could it have anything to do with A0-A5 having pin numbers 14-19, and not 13-18 like you mentioned?

      Like

      • Thank you for your reply. Yes, the analog pins are 14-19, sorry, was a mistake. I begin to think this is not a problem with the analog pins. It is some kind of saturation (optocoupler?). I have tried with a Mega 2560 (so with lots of digital pins) and everything goes well until I increase the number of pins connected to the relay array. The connectivity is fast until 8 relays are connected but when I index more accesories the control progressively slows down. Everything above 11 is impossible. I think I will use and independent card for every 8-array. the only way i find.

        Like

      • Well, this is very strange of course, since the Arduino is not aware what kind of unit is connected to its outputs. Have you checked the speed if you test the outputs with an LED plus resistor?

        Like

      • Rudy, I may confirm now that the problem is reproduced with led+resistor array. So this is not a poblem with the load or any other problem with the relay array. I have checked the relay array with a simple script and the arduino board is able to control the array with no problem. Any other idea? thank you!

        Like

  3. OK, that is what I expected, the type of unit connected to output pins should not make any difference. So the issue is that with the DCC decoder software, when you try to control ports 14 – 19 they respond slow? Weird, because in the code it makes no difference if you control pin 5 or pin 15. What happens if you configure it to only control 6 outputs on pins 14 – 19. Then add outputs 3 -12. Are you sure your DCC signals are coming through with the speed you expect?

    Like

    • I agree, the type of output is irrelevant. It seems that there is no difference with the order or pin type. For example you can use 14-19 plus 3-4 efficiently -no problem at all- but then as soon as you incorporate 5-6 then you begin to get troubles. So it is not related to the nature of the pins but connected with the number of pins (>8 pins = trouble). In fact, as I told you you, I can use a Mega just with logical pins and the problem is exactly reproduced; cannot control more than 8 pins efficiently. What about the DCC signal converter through the optocoupler, may be a problem with the number of signals being controlled?

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s