/* Library: DCC_Decoder File: DCC_Decoder-Switch1_16 Descr: switch for 16 DCC accessories By: Ed den Ouden 2022 DCC-Edd (public domain) Remark: In order to function properly this library needs an active DCC locomotive to be on the track | Green | Red ----------+-----------+--------- Arduino | Pin x | Pin x+1 DCC | Disable | Enable Rocrail | Off | On DCC addresses decoder: 17 to 32 (16 channels), adjustable Available extra pins: A5 on Uno, A5-A7 on Nano, many more on Mega Rocrail settings: Protocol: default, Parameter: 0, Value: 0, Options-turnout: ON, Accessory: ON Address-port: 5-1, 5-2, 5-3, 5-4, 6-1, etc */ #include // library to use for this sketch #define NUMACCESSORIES 16 // enter the number of accessories here #define SERIALMON // serial monitor, comment/uncomment to switch off/onn //#define DEBUGGER // uncomment to show debuglines in serial monitor const byte startPinArduino = 3; // first output pin on Arduino const int dccStartAddress = 17; // first DCC address to respond to const boolean outputIdle = LOW; // output state when idle const boolean outputActive = HIGH; // output state when activated typedef struct DCCAccessoryData { // internal datafields for the DCC-decoder 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 in a loop to set / reset accessories void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data) { address -= 1; address *= 4; address += 1; address += (data & 0x06) >> 1; // converts bits to a decimal DCC-address //address = address - 4; // uncomment this line for Roco Maus or z21 #ifdef SERIALMON Serial.print("DCC-address, activate, data: "); Serial.print(address); Serial.print (", "); Serial.print (activate); Serial.print (", "); Serial.println(data); #endif 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; } } #ifdef DEBUGGER Serial.print(address); Serial.print(" - "); Serial.print(enable); if (enable == 1) Serial.println(" green/on"); if (enable == 0) Serial.println(" red/off"); #endif } void setup() { #ifdef SERIALMON Serial.begin(115200); Serial.println("DCC decoder switch v1 for accessories (on-off), Ed den Ouden 2022 (lib: DCC_Decoder)"); Serial.println(""); Serial.print("First DCC-address: "); Serial.println(dccStartAddress); Serial.print("Nr of accessories: "); Serial.println(NUMACCESSORIES); Serial.print("Outputs when idle: "); Serial.println(outputIdle); Serial.print("Outputs when activated: "); Serial.println(outputActive); Serial.println(""); Serial.println("Ready/idle, waiting for DCC-packets..."); Serial.println(""); #endif /* set DCC-addresses, outputpins and behaviour: 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[x] init can also be done in a for loop DCC signal pin: 2 16 pins Uno/Nano: 3-18 (8 turnouts or 16 accessories) 32 pins Mega: 22-53 (16 turnouts or 32 accessories) */ accessory[0].address = dccStartAddress; // DCC address accessory[0].outputpin = startPinArduino; // Arduino pin accessory[1].address = dccStartAddress + 1; accessory[1].outputpin = startPinArduino + 1; accessory[2].address = dccStartAddress + 2; accessory[2].outputpin = startPinArduino + 2; accessory[3].address = dccStartAddress + 3; accessory[3].outputpin = startPinArduino + 3; accessory[4].address = dccStartAddress + 4; accessory[4].outputpin = startPinArduino + 4; accessory[5].address = dccStartAddress + 5; accessory[5].outputpin = startPinArduino + 5; accessory[6].address = dccStartAddress + 6; accessory[6].outputpin = startPinArduino + 6; accessory[7].address = dccStartAddress + 7; accessory[7].outputpin = startPinArduino + 7; accessory[8].address = dccStartAddress + 8; accessory[8].outputpin = startPinArduino + 8; accessory[9].address = dccStartAddress + 9; accessory[9].outputpin = startPinArduino + 9; accessory[10].address = dccStartAddress + 10; accessory[10].outputpin = startPinArduino + 10; accessory[11].address = dccStartAddress + 11; accessory[11].outputpin = startPinArduino + 11; accessory[12].address = dccStartAddress + 12; accessory[12].outputpin = startPinArduino + 12; accessory[13].address = dccStartAddress + 13; accessory[13].outputpin = startPinArduino + 13; accessory[14].address = dccStartAddress + 14; accessory[14].outputpin = startPinArduino + 14; accessory[15].address = dccStartAddress + 15; accessory[15].outputpin = startPinArduino + 15; DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true); // start the decoder DCC.SetupDecoder( 0x00, 0x00, 0 ); // setup output pins for (byte i = 0; i < NUMACCESSORIES; i++) { pinMode (accessory[i].outputpin, OUTPUT);// define pins as outputpin digitalWrite(accessory[i].outputpin, outputIdle); // set to default on startup } } void loop() { static int n = 0; DCC.loop(); if ( ++n >= NUMACCESSORIES ) n = 0; // next address to test if (accessory[n].dccstate) digitalWrite(accessory[n].outputpin, outputActive); // switch to green = on else digitalWrite(accessory[n].outputpin, outputIdle); // switch to red = off }