@martin re:The Arduino Mega2560: 67 Function Accessory Decoder
Hi Martin,
Yes, both the SMA decoder code (for the most part) and the NmraDcc library can be run on the Arduino Mega2560. The pin assignments would need to be changed and you would need to add a small DCC bus interface to the Mega.
Here is what the interface would look like:
The DCC OUT would connect to pin 2 of the Mega.
Here is the Eagle .brd file for Printed Circuit Board fabrication: mrhpub.com/files/users/geoffbfiles/DCC_FE2.zip
Here is a example of the pin re-assignment for the AccDec_17LED_1Ftn.ino deoder in the SMA20 library rebuilt for the Mega2560 with 67 switches (possible LEDs):
// Production 67 Switch Acessory DCC Decoder MAccDec_67LED_1Ftn.ino
// Version 7.01 Geoff Bunza 2014,2015,2016,2017,2018,2019,2020
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-106 SWITCHES)
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include < NmraDcc.h>
int tim_delay = 500;
#define numleds 67
byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,
23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,
43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,
63,64,65,66,67,68,69}; // 67 Pins Available
NmraDcc Dcc ;
DCC_MSG Packet ;
#define SET_CV_Address 24 // THIS ADDRESS IS FOR SETTING CV'S Like a Loco
#define Accessory_Address 40 // THIS ADDRESS IS THE START OF THE SWITCHES RANGE
// WHICH WILL EXTEND FOR 16 MORE SWITCH ADDRESSES
// THIS CAN START ABOVE ADDRESS 256
uint8_t CV_DECODER_MASTER_RESET = 120; // THIS IS THE CV ADDRESS OF THE FULL RESET
#define CV_To_Store_SET_CV_Address 121
#define CV_Accessory_Address CV_ACCESSORY_DECODER_ADDRESS_LSB
struct CVPair
{
uint16_t CV;
uint8_t Value;
};
CVPair FactoryDefaultCVs [] =
{
// These two CVs define the Long Accessory Address
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address 8)&0x07},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
// Speed Steps don't matter for this decoder
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
// {CV_29_CONFIG, CV29_EXT_ADDRESSING
{CV_29_CONFIG,CV29_ACCESSORY_DECODER
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address 8)&0x3F }, //MSB Set CV Address
};
uint8_t FactoryDefaultCVIndex = 0;
void notifyCVResetFactoryDefault()
{
// 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);
};
void setup()
{
// initialize the digital pins as an outputs
for (int i=0; i< numleds; i++) {
pinMode(ledpins, OUTPUT);
digitalWrite(ledpins, LOW);
}
for (int i=0; i< numleds; i++) {
digitalWrite(ledpins, HIGH);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i< numleds; i++) {
digitalWrite(ledpins, LOW);
delay (tim_delay/10);
}
delay( tim_delay);
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
{
for (int j=0; j < FactoryDefaultCVIndex; j++ )
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
}
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(0, 2, 0);
// Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 61, FLAGS_OUTPUT_ADDRESS_MODE
}
void loop()
{
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
Dcc.process();
}
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
if ( Addr> = Accessory_Address && Addr < Accessory_Address+67) //Controls This_Decoder_Address+66
digitalWrite( ledpins[Addr-Accessory_Address], Direction );
}
This does provide 67 outputs. There are still a few issues. The Mega cannot power that many LEDs at full power. It is limited to 40ma total. If you found ultra bright, ultra efficient LEDs that you could power at 0.5ma each (which do exist) you will have a chance. Next, the NmraDcc library will support 29 functions for the Mobile decoder but you will need to implement the Accessory decoder to get you the broader direct addressing range.
Sometime soon I will release a library specifically for the Mega and the details for the DCC generic front end too. Larger issues currently have priority.
Have fun!
Best regards,
Geoff Bunza