Arduino + DCC Interface = Accessory Decoder

By combining an Arduino and a DCC Interface you can easily produce your own DCC Accessory Decoder.

Here is a simple sketch showing how to create an accessory decoder that has 2 LEDs driven by 2 accessory addresses.

An example can be seen on YouTube here : DCC Accessory Decoder Example

 

 

Using the MynaBay DCC Library, create the following sketch…..

// Accessory Decoder - www.dccinterface.com

#include <NmraDcc.h>
#include <Wire.h>

typedef struct
{
	int address;
	uint8_t arduinoPin;
}
DCCAccessoryAddress;

// this is designed for 2 addresses, if you want more decoder functions, increase this to 3 for 3, 5 for 5, etc etc etc
DCCAccessoryAddress gAddresses[2];

NmraDcc  Dcc;
uint16_t lastAddr = 0xFFFF;
uint8_t lastDirection = 0xFF;

//
// Decoder Init
//
void ConfigureDecoder()
{
	// this is address number 1
	gAddresses[0].address = 200;
	gAddresses[0].arduinoPin = A6;

	// this is address number 2
	gAddresses[1].address = 201;
	gAddresses[1].arduinoPin = A7;

	// if you wanted more, make sure the array on line 13 is bigger, and start adding lines as follows
	//gAddresses[2].address = 202;
	//gAddresses[2].arduinoPin = A8;

	//gAddresses[3].address = 203;
	//gAddresses[3].arduinoPin = A9;

	// the above are commented out, and just for example only

	// set the pin for output
	for (int i = 0; i<(int)(sizeof(gAddresses) / sizeof(gAddresses[0])); i++)
	{
		pinMode(gAddresses[i].arduinoPin, OUTPUT);
	}
}

// This function is called whenever a normal DCC Turnout Packet is received
void notifyDccAccTurnoutOutput(uint16_t Addr, uint8_t Direction, uint8_t OutputPower)
{
	Serial.print("notifyDccAccTurnoutOutput: ");
	Serial.print(Addr, DEC);
	Serial.print(',');
	Serial.print(Direction, DEC);
	Serial.print(',');
	Serial.println(OutputPower, HEX);

	for (int i = 0; i < (sizeof(gAddresses) / sizeof(DCCAccessoryAddress)); i++)
	{
		if ((Addr == gAddresses[i].address) && ((Addr != lastAddr) || (Direction != lastDirection)) && OutputPower)
		{
			lastAddr = Addr;
			lastDirection = Direction;

			Serial.print(F("Activating Decoder Address "));
			Serial.println(i, DEC);

			if (Direction)
			{
				Serial.print(F("Turning Accessory On : "));
				Serial.println(gAddresses[i].arduinoPin, DEC);
				digitalWrite(gAddresses[i].arduinoPin, HIGH);
				break;
			}
			else
			{
				Serial.print(F("Turning Accessory Off : "));
				Serial.println(gAddresses[i].arduinoPin, DEC);
				digitalWrite(gAddresses[i].arduinoPin, LOW);
				break;
			}
		}
	}
}

void setupDCCDecoder()
{
	Serial.println(F("Setting up DCC Decorder..."));

	// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up 
	Dcc.pin(0, 2, 1);

	// Call the main DCC Init function to enable the DCC Receiver
	Dcc.init(MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0);

	// Configure the Decoder
	ConfigureDecoder();
}

void setup()
{
	Serial.begin(9600);

	Serial.println(F("Accessory Decoder - www.dccinterface.com"));

	Serial.println(F("Initializing...."));

	setupDCCDecoder();
}

void loop()
{
	// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
	Dcc.process();
}

The DCC Library reads the DCC Input via the D2 ( Digital Pin 2 ) external interrupt pin on the Arduino – if you are using the DCC Interface standalone board – connect the “ARD” pin to D2 as shown here…

The sketch turns on 2 LEDs, which are connected to A4 and A3.

As you operate accessory addresses on your DCC handset, you will see the addresses and the enabled status ( point open or closed ) appear on the serial monitor ( Open Serial Monitor from Tools ) and depending on if you turn on or turn off the accessory decoder, the LED will turn on or turn off.