Category Archives: Projects

Arduino based – Level Crossing Control – by John Cornell

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.

Details of the project are shown below – enjoy!

John Cornell

Read more »

Using the Iowa Scaled Engineering – Arduino DCC Decoder Shield

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
#include <NmraDcc.h>

// 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:
// For more information refer to the file: here:
// 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
#define DEBUG_MSG

// 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 ;

struct CVPair
 uint16_t CV;
 uint8_t Value;

CVPair FactoryDefaultCVs [] =

uint8_t FactoryDefaultCVIndex = 0;

void notifyCVResetFactoryDefault()
#ifdef DEBUG_MSG
 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 
void notifyCVAck(void)
#ifdef DEBUG_MSG
 Serial.println("notifyCVAck") ;
 // Configure the DCC CV Programing ACK pin for an 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++)
 Serial.print(Msg->Data[i], HEX);
 Serial.write(' ');

void notifyCVChange(uint16_t CV, uint8_t Value)
#ifdef DEBUG_MSG
 Serial.print("notifyCVChange: CV: ") ;
 Serial.print(CV,DEC) ;
 Serial.print(" Value: ") ;
 Serial.println(Value, DEC) ;
 Value = Value; // Silence Compiler Warnings...
 CV = CV;

void setup()
 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, 2, 1);
 // Call the main DCC Init function to enable the DCC Receiver
 Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER, 0 );

 Serial.println("Init Done");

void loop()
 // 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);

EmbeddedLocoNet and OpenDCC Arduino libraries moved to MRRWA

http://opendcc.sourceforge.netI decided to move the on-going development of both the EmbeddedLocoNet and OpenDcc Arduino Libraries to the SourceForge MRRWA project associated with this website, so any new work on these libraries and new MRR based Arduino projects and articles are welcome.

Basically as things have become more Arduino centric and I got tired of maintaining these two libraries in separate source code repositories as they pretty much live side-by-side on my PC, so I merged them into this new project.

I’ve recently updated the EmbeddedLocoNet and OpenDCC project website to reflect this change.