Inspired by some of some of Geoff Bunza’s work, John Cornell used an Arduino Uno to control level crossing (grade-crossing) booms and LED flashers. The details of John’s project are described below.
The booms are controlled by small servo-motors. Occupation detection is done via a simple circuit using a small toroidal transformer to detect the DCC feed to the track, in a block extending either side of the crossing. The occupation detection circuit and the Arduino are powered directly from the track as well.
The NmraDcc library has been updated to version 1.3.0 and contains the following significant changes:
Thanks to Franz-Peter Müller the core DCC decoding logic no longer uses the Timer0 Compare Match B interrupt and only relies on the INTx External Hardware Interrupt and the micros() library call for DCC signal decoding. This will make the library much more portable to other non-AVR platforms in the future.
Geoff Bunza’s SMA examples have been updated to version 5.1
You can now install or update this library from within the Arduino IDE Library Manager by searching for “dcc”
Iowa Scaled Engineering have developed a very flexible and capable DCC Decoder Shield that interfaces the Arduino to a DCC System and supports CV Read/Write via the CV ACK facility.
Here is a photo of the DCC Decoder Shield connected to an Arduino UNO showing the jumper settings:
Once you have configured the jumpers you can load up the code below to exercise the DCC Interface.
The example code will allow you:
See all the DCC Packets printed as HEX values to the Arduino Serial Monitor
Read and Write CVs
Reset to Factory Defaults by writing a value of 8 to CV8
// This Example shows how to use the library with the Iowa Scaled Engineering ARD-DCCSHIELD
// You can find out more about this DCC Interface here: http://www.iascaled.com/store/ARD-DCCSHIELD
// For more information refer to the file: README.md here: https://github.com/IowaScaledEngineering/ard-dccshield
// This demo assumes the following Jumper settings on the ARD-DCCSHIELD
// JP1 - I2C Pull-Up Resistors - Don't Care
// JP2 - (Pins 1-2) I2C /IORST JP2 - Don't-Care
// JP2 - (Pins 3-4) - DCC Signal to Arduino Pin - OFF
// JP3 - I2C /INT and /OE - Don't-Care
// JP4 - DCC Signal to Arduino Pin - D2 ON
// JP5 - Arduino Powered from DCC - User Choice
// JP6 - Boards without VIO - User Choice
// JP7 - Enable Programming ACK - 1-2 ON 3-4 ON
// It is a very basic DCC Accessory Decoder that does nothing except allow CV Read/Write and
// you can also print every DCC packet by uncommenting the "#define NOTIFY_DCC_MSG" line below
// You can also print other Debug Messages uncommenting the line below
// Un-Comment the line below to Enable DCC ACK for Service Mode Programming Read CV Capablilty
#define ENABLE_DCC_ACK 15 // This is A1 on the Iowa Scaled Engineering ARD-DCCSHIELD DCC Shield
NmraDcc Dcc ;
CVPair FactoryDefaultCVs  =
uint8_t FactoryDefaultCVIndex = 0;
Serial.println("notifyCVResetFactoryDefault: Settings CVs to Factory Defaults") ;
#endif // Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
// to flag to the loop() function that a reset to Factory Defaults needs to be done
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
// This function is called by the NmraDcc library when a DCC ACK needs to be sent
// Calling this function should cause an increased 60ma current drain on the power supply for 6ms to ACK a CV Read
// Configure the DCC CV Programing ACK pin for an output
pinMode( ENABLE_DCC_ACK, OUTPUT );
// Generate the DCC ACK 60mA pulse
digitalWrite( ENABLE_DCC_ACK, HIGH );
delay( 10 ); // The DCC Spec says 6ms but 10 makes sure... ;)
digitalWrite( ENABLE_DCC_ACK, LOW );
void notifyDccMsg( DCC_MSG * Msg)
Serial.print("notifyDccMsg: ") ;
for(uint8_t i = 0; i < Msg->Size; i++)
void notifyCVChange(uint16_t CV, uint8_t Value)
Serial.print("notifyCVChange: CV: ") ;
Serial.print(" Value: ") ;
Serial.println(Value, DEC) ;
Value = Value; // Silence Compiler Warnings...
CV = CV;
Serial.println("NMRA DCC Iowa Scaled Engineering ARD-DCCSHIELD Example");
// 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, 0 );
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
if( FactoryDefaultCVIndex && Dcc.isSetCVReady())
FactoryDefaultCVIndex--; // Decrement first as initially it is the size of the array
Dcc.setCV( FactoryDefaultCVs[FactoryDefaultCVIndex].CV, FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
The MRRwA Project source code has been moved from the single SVN Repository on SourceForge into separate GitHub repositories. They have also had the appropriate Arduino IDE library.properties files added to enable operation with the new Arduino Manage Libraries… & Add .ZIP Library… features. More details can be found here.
The LocoNet library now supports the AVR ATTiny84 and ATMega32U4 processors.
Geoff ‘s projects needed support for mobile decoder functions 13..28, but that was not supported by the library, so he had to add a work-around. This needed support has now been added to the NmraDcc library and all of Geoff’s decoder variations have been added to the examples folder.
While I’ve not had much to post about or new releases to the libraries over this last year, there have been changes going on slowly in the background (when I get a few hours to dedicate to it) from time to time, as I do have a few small projects in the works that need new capabilities. The things I’ve been working on are:
I’ve got the DCC library working with the AVR Tiny 85 processor to use as a signal decoder. I had a friend design a small Signal Decoder PCB for driving 4 LEDs. I’ve not got the LED PWM dimming all sorted yet, but it should be nice once I do…
There’s also some work being done to provide support for the LocoNet SV and LocoNet CV protocols. This will let me port my LocoBOD project to the Arduino environment.
Hopefully in a few months I’ll have these projects working, so keep an eye out for another update… 😉
IMPORTANT: I introduced a major bug with the NmraDcc library when I added the Mega 1280/2560 support as it broke the Mega168 support and it took me hours to figure out why my code, that has worked for years, suddenly stopped working on my Mega168 dev board.
To work around the problem of how best to support multiple AVR MPUs, I have refactored the library to add a new pin() method that lets you explicitly define the External Interrupt (INTx), the associated Arduino Pin to use and to enable the Pull-up or not. I’ve updated the example to show the new usage.
If you’re using the NmraDcc library and you sketch has suddenly stopped working after you updated to the 2012-06-10 release, you should download the update from here and not use the 2012-06-10 release.