diff --git a/NmraDcc.cpp b/NmraDcc.cpp index 29ab28d..39c80c8 100644 --- a/NmraDcc.cpp +++ b/NmraDcc.cpp @@ -583,7 +583,7 @@ uint8_t writeCV( unsigned int CV, uint8_t Value) { case CV_29_CONFIG: // copy addressmode Bit to Flags - DccProcState.Flags = ( DccProcState.Flags & ~FLAGS_OUTPUT_ADDRESS_MODE) | (Value & FLAGS_OUTPUT_ADDRESS_MODE); + DccProcState.Flags = ( DccProcState.Flags & ~FLAGS_CV29_BITS) | (Value & FLAGS_CV29_BITS); // no break, because myDccAdress must also be reset case CV_ACCESSORY_DECODER_ADDRESS_LSB: // Also same CV for CV_MULTIFUNCTION_PRIMARY_ADDRESS case CV_ACCESSORY_DECODER_ADDRESS_MSB: @@ -601,11 +601,11 @@ uint8_t writeCV( unsigned int CV, uint8_t Value) if( notifyCVChange ) notifyCVChange( CV, Value) ; + if( notifyDccCVChange && !(DccProcState.Flags & FLAGS_SETCV_CALLED) ) notifyDccCVChange( CV, Value ); - - DccProcState.Flags &= ~FLAGS_SETCV_CALLED; } + return readEEPROM( CV ) ; } @@ -934,7 +934,8 @@ void processServiceModeOperation( DCC_MSG * pDccMsg ) } else if( pDccMsg->Size == 4) // 4 Byte Packets are for Direct Byte & Bit Mode - { DB_PRINT("BB-Mode"); + { + DB_PRINT("BB-Mode"); CVAddr = ( ( ( pDccMsg->Data[0] & 0x03 ) << 8 ) | pDccMsg->Data[1] ) + 1 ; Value = pDccMsg->Data[2] ; @@ -1056,7 +1057,7 @@ void execDccProcessor( DCC_MSG * pDccMsg ) { int16_t BoardAddress ; int16_t OutputAddress ; - uint8_t TurnoutPairIndex ; + uint8_t TurnoutPairIndex ; #ifdef DEBUG_PRINT SerialPrintPacketHex(F( "eDP: AccCmd: "), pDccMsg); @@ -1137,7 +1138,9 @@ void execDccProcessor( DCC_MSG * pDccMsg ) if((pDccMsg->Size == 4) && ((pDccMsg->Data[1] & 0b10001001) == 1)) // Extended Accessory Decoder Control Packet Format { - uint8_t state = pDccMsg->Data[2] ;// & 0b00011111; + // According to the NMRA Dcc Spec the Signal State should only use the lower 5 Bits, + // however some manufacturers seem to allow/use all 8 bits, so we'll relax that constraint for now + uint8_t state = pDccMsg->Data[2] ; DB_PRINT("eDP: OAddr:%d Extended State:%0X", OutputAddress, state); if( notifyDccSigOutputState ) notifyDccSigOutputState(OutputAddress, state); @@ -1231,9 +1234,9 @@ void execDccProcessor( DCC_MSG * pDccMsg ) uint8_t currentValue = readCV(cvAddress); uint8_t newValueMask = 1 << (cvValue & 0b00000111); if(cvValue & 0b00001000) - writeCV(cvAddress, cvValue | newValueMask); + writeCV(cvAddress, currentValue | newValueMask); else - writeCV(cvAddress, cvValue & ~newValueMask); + writeCV(cvAddress, currentValue & ~newValueMask); } break; } @@ -1262,6 +1265,13 @@ NmraDcc::NmraDcc() { } +#ifdef digitalPinToInterrupt +void NmraDcc::pin( uint8_t ExtIntPinNum, uint8_t EnablePullup) +{ + pin(digitalPinToInterrupt(ExtIntPinNum), ExtIntPinNum, EnablePullup); +} +#endif + void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup) { #if defined ( __STM32F1__ ) @@ -1308,8 +1318,8 @@ void NmraDcc::init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, ui // Set the Bits that control Multifunction or Accessory behaviour // and if the Accessory decoder optionally handles Output Addressing - uint8_t cv29Mask = CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE ; // peal off the top two bits - writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~cv29Mask ) | (Flags & cv29Mask) ) ; + // we need to peal off the top two bits + writeCV( CV_29_CONFIG, ( readCV( CV_29_CONFIG ) & ~FLAGS_CV29_BITS ) | (Flags & FLAGS_CV29_BITS) ) ; uint8_t doAutoFactoryDefault = 0; if((Flags & FLAGS_AUTO_FACTORY_DEFAULT) && (readCV(CV_VERSION_ID) == 255) && (readCV(CV_MANUFACTURER_ID) == 255)) @@ -1334,7 +1344,12 @@ uint8_t NmraDcc::getCV( uint16_t CV ) uint8_t NmraDcc::setCV( uint16_t CV, uint8_t Value) { DccProcState.Flags |= FLAGS_SETCV_CALLED; - return writeCV(CV,Value); + + uint8_t returnValue = writeCV(CV,Value); + + DccProcState.Flags &= ~FLAGS_SETCV_CALLED; + + return returnValue; } //////////////////////////////////////////////////////////////////////// diff --git a/NmraDcc.h b/NmraDcc.h index ed2191d..d5ae4b8 100644 --- a/NmraDcc.h +++ b/NmraDcc.h @@ -109,7 +109,7 @@ typedef struct typedef enum { CV29_LOCO_DIR = 0b00000001, /** bit 0: Locomotive Direction: "0" = normal, "1" = reversed */ CV29_F0_LOCATION = 0b00000010, /** bit 1: F0 location: "0" = bit 4 in Speed and Direction instructions, "1" = bit 4 in function group one instruction */ - CV29_APS = 0b00000100, /** bit 2: Alternate Power Source (APS) "0" = NMRA Digital only, "1" = Alternate power source set by CV12 */ + CV29_APS = 0b00000100, /** bit 2: Alternate Power Source (APS) "0" = NMRA Digital only, "1" = Alternate power source set by CV12 */ CV29_ADV_ACK = 0b00001000, /** bit 3: ACK, Advanced Acknowledge mode enabled if 1, disabled if 0 */ CV29_SPEED_TABLE_ENABLE = 0b00010000, /** bit 4: STE, Speed Table Enable, "0" = values in CVs 2, 4 and 6, "1" = Custom table selected by CV 25 */ CV29_EXT_ADDRESSING = 0b00100000, /** bit 5: "0" = one byte addressing, "1" = two byte addressing */ @@ -206,6 +206,10 @@ class NmraDcc #define FLAGS_OUTPUT_ADDRESS_MODE 0x40 // CV 29/541 bit 6 #define FLAGS_DCC_ACCESSORY_DECODER 0x80 // CV 29/541 bit 7 +// Flag Bits that are cloned from CV29 relating the DCC Accessory Decoder +#define FLAGS_CV29_BITS (FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER) + + /*+ * pin() is called from setup() and sets up the pin used to receive DCC packets. * @@ -219,6 +223,21 @@ class NmraDcc */ void pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup); + /*+ + * pin() is called from setup() and sets up the pin used to receive DCC packets. + * This relies on the internal function: digitalPinToInterrupt() to map the input pin number to the right interrupt + * + * Inputs: + * ExtIntPinNum - Input pin number. + * EnablePullup - Set true to enable the pins pullup resistor. + * + * Returns: + * None. + */ +#ifdef digitalPinToInterrupt +void pin( uint8_t ExtIntPinNum, uint8_t EnablePullup); +#endif + /*+ * init() is called from setup() after the pin() command is called. * It initializes the NmDcc object and makes it ready to process packets. diff --git a/examples/SMA/AccDec_10Servos_7LED_6Ftn/AccDec_10Servos_7LED_6Ftn.ino b/examples/SMA/AccDec_10Servos_7LED_6Ftn/AccDec_10Servos_7LED_6Ftn.ino index ac981a7..68798d4 100755 --- a/examples/SMA/AccDec_10Servos_7LED_6Ftn/AccDec_10Servos_7LED_6Ftn.ino +++ b/examples/SMA/AccDec_10Servos_7LED_6Ftn/AccDec_10Servos_7LED_6Ftn.ino @@ -1,5 +1,10 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Switch Acessory DCC Decoder AccDec_10Servos_7LED_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// 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-56 SWITCHES) +// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 +// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -19,7 +24,7 @@ SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,6 +54,7 @@ int t; // temp #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 @@ -61,7 +67,7 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; struct CVPair { @@ -70,15 +76,22 @@ struct CVPair }; CVPair FactoryDefaultCVs [] = { - {CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, - {CV_To_Store_SET_CV_Address, SET_CV_Address}, - {CV_To_Store_SET_CV_Address+1, 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 {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade - {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate {32, 28}, //F0 Start Position F0=0 {33, 140}, //F0 End Position F0=1 {34, 28}, //F0 Current Position @@ -112,21 +125,21 @@ CVPair FactoryDefaultCVs [] = {62, 28}, // Start Position Fx=0 {63, 140}, // End Position Fx=1 {64, 28}, // Current Position - {65, 2}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {65, 1}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate - {67, 28}, // Start Position Fx=0 - {68,140}, // End Position Fx=1 - {69, 28}, // Current Position - {70, 2}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {67, 1}, // Start Position Fx=0 + {68,35}, // End Position Fx=1 + {69, 1}, // Current Position + {70, 1}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate - {72, 28}, // Start Position Fx=0 - {73, 140}, // End Position Fx=1 - {74, 28}, // Current Position - {75, 2}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {72, 1}, // Start Position Fx=0 + {73, 100}, // End Position Fx=1 + {74, 1}, // Current Position + {75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate - {77, 28}, // Start Position Fx=0 - {78, 140}, // End Position Fx=1 - {79, 28}, // Current Position + {77, 1}, // Start Position Fx=0 + {78, 10}, // End Position Fx=1 + {79, 1}, // Current Position {80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {82, 1}, // Start Position Fx=0 @@ -135,22 +148,22 @@ CVPair FactoryDefaultCVs [] = {85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {87, 1}, // Start Position Fx=0 - {88, 5}, // End Position Fx=1 + {88, 50}, // End Position Fx=1 {89, 1}, // Current Position {90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {92, 1}, // Start Position Fx=0 - {93, 20}, // End Position Fx=1 + {93, 100}, // End Position Fx=1 {94, 1}, // Current Position {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 35}, // End Position Fx=1 + {98, 200}, // End Position Fx=1 {99, 2}, // Current Position {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 4}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate @@ -299,7 +312,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { diff --git a/examples/SMA/AccDec_13Servos_4LED_6Ftn/AccDec_13Servos_4LED_6Ftn.ino b/examples/SMA/AccDec_13Servos_4LED_6Ftn/AccDec_13Servos_4LED_6Ftn.ino index b887187..a6cf15b 100755 --- a/examples/SMA/AccDec_13Servos_4LED_6Ftn/AccDec_13Servos_4LED_6Ftn.ino +++ b/examples/SMA/AccDec_13Servos_4LED_6Ftn/AccDec_13Servos_4LED_6Ftn.ino @@ -1,5 +1,11 @@ // Production 17 Function DCC Decoder -// Version 5.1 Geoff Bunza 2014,2015,2016 +// Production 17 Switch Acessory DCC Decoder AccDec_13Servos_4LED_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// 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-56 SWITCHES) +// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 +// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -12,14 +18,13 @@ // ******** INFO TO THE SERIAL MONITOR //#define DEBUG - #include #include SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,6 +54,7 @@ int t; // temp #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 @@ -61,7 +67,7 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; struct CVPair { @@ -70,13 +76,21 @@ struct CVPair }; CVPair FactoryDefaultCVs [] = { - {CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, - {CV_To_Store_SET_CV_Address, SET_CV_Address}, - {CV_To_Store_SET_CV_Address+1, 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 {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate {32, 28}, //F0 Start Position F0=0 @@ -142,22 +156,22 @@ CVPair FactoryDefaultCVs [] = {92, 28}, // Start Position Fx=0 {93, 140}, // End Position Fx=1 {94, 28}, // Current Position - {95, 1}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 20}, // End Position Fx=1 - {99, 1}, // Current Position - {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {98, 200}, // End Position Fx=1 + {99, 2}, // Current Position + {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 4}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position - {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {107, 1}, // Start Position Fx=0 {108, 60}, // End Position Fx=1 - {109, 20}, // Current Position - {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {109, 1}, // Current Position + {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {112, 1}, // Start Position Fx=0 {113, 4}, // End Position Fx=1 @@ -203,7 +217,7 @@ void setup() //****************************************************** // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); + Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); delay(800); #if defined(DECODER_LOADED) @@ -299,7 +313,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { diff --git a/examples/SMA/AccDec_15Servos_2LED_6Ftn/AccDec_15Servos_2LED_6Ftn.ino b/examples/SMA/AccDec_15Servos_2LED_6Ftn/AccDec_15Servos_2LED_6Ftn.ino index 087fe6d..f6e407b 100755 --- a/examples/SMA/AccDec_15Servos_2LED_6Ftn/AccDec_15Servos_2LED_6Ftn.ino +++ b/examples/SMA/AccDec_15Servos_2LED_6Ftn/AccDec_15Servos_2LED_6Ftn.ino @@ -1,5 +1,10 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Switch Acessory DCC Decoder AccDec_15Servos_2LED_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// 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-56 SWITCHES) +// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 +// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -12,14 +17,13 @@ // ******** INFO TO THE SERIAL MONITOR //#define DEBUG - #include #include SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,6 +53,7 @@ int t; // temp #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 @@ -61,7 +66,7 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; struct CVPair { @@ -70,13 +75,21 @@ struct CVPair }; CVPair FactoryDefaultCVs [] = { - {CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, - {CV_To_Store_SET_CV_Address, SET_CV_Address}, - {CV_To_Store_SET_CV_Address+1, 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 {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate {32, 28}, //F0 Start Position F0=0 @@ -203,7 +216,7 @@ void setup() //****************************************************** // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); + Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); delay(800); #if defined(DECODER_LOADED) @@ -277,7 +290,13 @@ void setup() //****************************************************** } break; case 5: // Fade On - + { + ftn_queue[i].inuse = 0; + ftn_queue[i].start_value = 0; + ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.; + } break; case 6: // NEXT FEATURE to pin break; @@ -293,7 +312,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { @@ -353,13 +372,7 @@ void loop() //**************************************************************** } break; case 5: // Fade On - { - ftn_queue[i].inuse = 0; - ftn_queue[i].start_value = 0; - ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5)))); - digitalWrite(fpins[i], 0); - ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.; - } + break; case 6: // NEXT FEATURE to pin break; diff --git a/examples/SMA/AccDec_17LED_1Ftn/AccDec_17LED_1Ftn.ino b/examples/SMA/AccDec_17LED_1Ftn/AccDec_17LED_1Ftn.ino index 658bfe3..a8c8fbf 100755 --- a/examples/SMA/AccDec_17LED_1Ftn/AccDec_17LED_1Ftn.ino +++ b/examples/SMA/AccDec_17LED_1Ftn/AccDec_17LED_1Ftn.ino @@ -1,5 +1,9 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Switch Acessory DCC Decoder AccDec_17LED_1Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// 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-56 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!! @@ -9,7 +13,7 @@ int tim_delay = 500; #define numleds 17 -byte ledpins [] = {0,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; +byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; const int FunctionPin0 = 3; const int FunctionPin1 = 4; @@ -31,9 +35,14 @@ const int FunctionPin16 = 19; //A5 NmraDcc Dcc ; DCC_MSG Packet ; -#define This_Decoder_Address 40 //ACCESSORY DECODER ADDRESS - //Start of SWITCHES RANGE -uint8_t CV_DECODER_MASTER_RESET = 120; +#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; @@ -41,11 +50,21 @@ struct CVPair }; CVPair FactoryDefaultCVs [] = { - {CV_ACCESSORY_DECODER_ADDRESS_LSB, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {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; @@ -86,7 +105,7 @@ void setup() // 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, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, 0 ); + Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); } void loop() { @@ -94,7 +113,7 @@ void loop() Dcc.process(); } extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) { - if ( Addr >= This_Decoder_Address && Addr < This_Decoder_Address+17) //Controls This_Decoder_Address+16 - digitalWrite( ledpins[Addr-This_Decoder_Address], Direction ); + if ( Addr >= Accessory_Address && Addr < Accessory_Address+17) //Controls This_Decoder_Address+16 + digitalWrite( ledpins[Addr-Accessory_Address], Direction ); } - + diff --git a/examples/SMA/AccDec_17LED_6Ftn/AccDec_17LED_6Ftn.ino b/examples/SMA/AccDec_17LED_6Ftn/AccDec_17LED_6Ftn.ino index fea3c93..99b6c28 100755 --- a/examples/SMA/AccDec_17LED_6Ftn/AccDec_17LED_6Ftn.ino +++ b/examples/SMA/AccDec_17LED_6Ftn/AccDec_17LED_6Ftn.ino @@ -1,5 +1,10 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Switch Acessory DCC Decoder AccDec_17LED_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// 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-56 SWITCHES) +// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 +// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -12,14 +17,13 @@ // ******** INFO TO THE SERIAL MONITOR //#define DEBUG - #include #include SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,6 +53,7 @@ int t; // temp #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 @@ -61,7 +66,7 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; struct CVPair { @@ -70,13 +75,21 @@ struct CVPair }; CVPair FactoryDefaultCVs [] = { - {CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, - {CV_To_Store_SET_CV_Address, SET_CV_Address}, - {CV_To_Store_SET_CV_Address+1, 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 {30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate {32, 28}, //F0 Start Position F0=0 @@ -127,36 +140,36 @@ CVPair FactoryDefaultCVs [] = {77, 1}, // Start Position Fx=0 {78, 10}, // End Position Fx=1 {79, 1}, // Current Position - {80, 5}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {82, 1}, // Start Position Fx=0 {83, 5}, // End Position Fx=1 {84, 1}, // Current Position - {85, 4}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade - {86, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {87, 1}, // Start Position Fx=0 - {88, 5}, // End Position Fx=1 + {88, 50}, // End Position Fx=1 {89, 1}, // Current Position - {90, 0}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {92, 1}, // Start Position Fx=0 - {93, 20}, // End Position Fx=1 + {93, 100}, // End Position Fx=1 {94, 1}, // Current Position - {95, 0}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 35}, // End Position Fx=1 + {98, 200}, // End Position Fx=1 {99, 2}, // Current Position {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 4}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position - {105, 0}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {107, 1}, // Start Position Fx=0 {108, 60}, // End Position Fx=1 - {109, 20}, // Current Position + {109, 1}, // Current Position {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {112, 1}, // Start Position Fx=0 @@ -177,6 +190,9 @@ void notifyCVResetFactoryDefault() FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); }; +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + void setup() //****************************************************** { #ifdef DEBUG @@ -203,7 +219,7 @@ void setup() //****************************************************** // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); + Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); delay(800); #if defined(DECODER_LOADED) @@ -299,7 +315,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { diff --git a/examples/SMA/AccDec_7ServoBackandForth6Ftn/AccDec_7ServoBackandForth6Ftn.ino b/examples/SMA/AccDec_7ServoBackandForth6Ftn/AccDec_7ServoBackandForth6Ftn.ino index 73ddc2d..3923248 100755 --- a/examples/SMA/AccDec_7ServoBackandForth6Ftn/AccDec_7ServoBackandForth6Ftn.ino +++ b/examples/SMA/AccDec_7ServoBackandForth6Ftn/AccDec_7ServoBackandForth6Ftn.ino @@ -1,13 +1,19 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Switch Acessory DCC Decoder AccDec_7ServoBackandForth6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// 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-56 SWITCHES) +// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 +// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks + // This Decoder Version has been modified so that each Switch Closure Transition from Thrown to Closed // Swings the Servo Quickly from Start to Stop and Back to Start // This is ONLY done in the transition from Thrown to Closed Servo Speed can be slowed by changing the // RATE CV towards 1 -// + // ******** 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 @@ -22,7 +28,7 @@ SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -64,7 +70,7 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; struct CVPair { @@ -73,13 +79,21 @@ struct CVPair }; CVPair FactoryDefaultCVs [] = { - {CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, - {CV_To_Store_SET_CV_Address, SET_CV_Address}, - {CV_To_Store_SET_CV_Address+1, 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 {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate {32, 28}, //F0 Start Position @@ -180,6 +194,9 @@ void notifyCVResetFactoryDefault() FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); }; +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + void setup() //****************************************************** { #ifdef DEBUG @@ -206,7 +223,7 @@ void setup() //****************************************************** // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); + Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); delay(800); #if defined(DECODER_LOADED) @@ -302,7 +319,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { diff --git a/examples/SMA/AccDec_7Servos_10LED_6Ftn/AccDec_7Servos_10LED_6Ftn.ino b/examples/SMA/AccDec_7Servos_10LED_6Ftn/AccDec_7Servos_10LED_6Ftn.ino index ae92e0a..c888b63 100755 --- a/examples/SMA/AccDec_7Servos_10LED_6Ftn/AccDec_7Servos_10LED_6Ftn.ino +++ b/examples/SMA/AccDec_7Servos_10LED_6Ftn/AccDec_7Servos_10LED_6Ftn.ino @@ -1,5 +1,10 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Switch Acessory DCC Decoder AccDec_7Servos_10LED_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// 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-56 SWITCHES) +// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255 +// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -12,14 +17,13 @@ // ******** INFO TO THE SERIAL MONITOR //#define DEBUG - #include #include SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,6 +53,7 @@ int t; // temp #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 @@ -61,7 +66,7 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; struct CVPair { @@ -70,13 +75,21 @@ struct CVPair }; CVPair FactoryDefaultCVs [] = { - {CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, - {CV_To_Store_SET_CV_Address, SET_CV_Address}, - {CV_To_Store_SET_CV_Address+1, 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 {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate {32, 28}, //F0 Start Position F0=0 @@ -129,41 +142,41 @@ CVPair FactoryDefaultCVs [] = {79, 28}, // Current Position {80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate - {82, 28}, // Start Position Fx=0 - {83, 140}, // End Position Fx=1 - {84, 28}, // Current Position - {85, 0}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {82, 1}, // Start Position Fx=0 + {83, 5}, // End Position Fx=1 + {84, 1}, // Current Position + {85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate - {87, 28}, // Start Position Fx=0 - {88, 140}, // End Position Fx=1 - {89, 28}, // Current Position - {90, 0}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {87, 1}, // Start Position Fx=0 + {88, 50}, // End Position Fx=1 + {89, 1}, // Current Position + {90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate - {92, 28}, // Start Position Fx=0 - {93, 140}, // End Position Fx=1 - {94, 28}, // Current Position - {95, 1}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {92, 1}, // Start Position Fx=0 + {93, 100}, // End Position Fx=1 + {94, 1}, // Current Position + {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 20}, // End Position Fx=1 - {99, 1}, // Current Position - {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {98, 200}, // End Position Fx=1 + {99, 2}, // Current Position + {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 4}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position - {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {107, 1}, // Start Position Fx=0 {108, 60}, // End Position Fx=1 - {109, 20}, // Current Position - {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {109, 1}, // Current Position + {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {112, 1}, // Start Position Fx=0 {113, 4}, // End Position Fx=1 {114, 1}, // Current Position //FUTURE USE - {115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=PWM + {115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {116, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {117, 28}, // Start Position Fx=0 {118, 50}, // End Position Fx=1 @@ -177,6 +190,9 @@ void notifyCVResetFactoryDefault() FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); }; +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + void setup() //****************************************************** { #ifdef DEBUG @@ -203,7 +219,7 @@ void setup() //****************************************************** // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); + Dcc.init( MAN_ID_DIY, 600, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address); delay(800); #if defined(DECODER_LOADED) @@ -299,7 +315,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { @@ -370,6 +386,7 @@ void loop() //**************************************************************** } } +// This function is called whenever a normal DCC Turnout Packet is received and we're in Output Addressing Mode extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) { uint16_t Current_Decoder_Addr = Dcc.getAddr(); diff --git a/examples/SMA/Dec_10Serv_7LED_6Ftn/Dec_10Serv_7LED_6Ftn.ino b/examples/SMA/Dec_10Serv_7LED_6Ftn/Dec_10Serv_7LED_6Ftn.ino index 7471ee6..cc97362 100755 --- a/examples/SMA/Dec_10Serv_7LED_6Ftn/Dec_10Serv_7LED_6Ftn.ino +++ b/examples/SMA/Dec_10Serv_7LED_6Ftn/Dec_10Serv_7LED_6Ftn.ino @@ -1,5 +1,6 @@ // Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -19,7 +20,7 @@ SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,7 +50,6 @@ NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; int t; // temp -#define This_Decoder_Address 24 struct QUEUE { int inuse; @@ -58,19 +58,29 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; struct CVPair { uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { - {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate @@ -130,22 +140,22 @@ CVPair FactoryDefaultCVs [] = {85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {87, 1}, // Start Position Fx=0 - {88, 5}, // End Position Fx=1 + {88, 50}, // End Position Fx=1 {89, 1}, // Current Position {90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {92, 1}, // Start Position Fx=0 - {93, 20}, // End Position Fx=1 + {93, 100}, // End Position Fx=1 {94, 1}, // Current Position {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 35}, // End Position Fx=1 + {98, 200}, // End Position Fx=1 {99, 2}, // Current Position {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 4}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate @@ -173,6 +183,8 @@ void notifyCVResetFactoryDefault() FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); }; +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS void setup() //****************************************************** { #ifdef DEBUG @@ -199,7 +211,7 @@ void setup() //****************************************************** // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); delay(800); #if defined(DECODER_LOADED) @@ -295,7 +307,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { @@ -367,6 +379,17 @@ void loop() //**************************************************************** } void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { +#ifdef DEBUG + Serial.print(" addr: "); + Serial.print(Addr, DEC) ; + Serial.print(" at: "); + Serial.print(AddrType, DEC) ; + Serial.print(" fg : "); + Serial.print(FuncGrp, DEC) ; + Serial.print(" fs: "); + Serial.println(FuncState, DEC) ; +#endif + switch(FuncGrp) { case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1 @@ -480,4 +503,4 @@ void exec_function (int function, int pin, int FuncState) { ftn_queue[function].inuse = 0; break; } -} +} diff --git a/examples/SMA/Dec_13Serv_4LED_6Ftn/Dec_13Serv_4LED_6Ftn.ino b/examples/SMA/Dec_13Serv_4LED_6Ftn/Dec_13Serv_4LED_6Ftn.ino index 863c97a..b463aa4 100755 --- a/examples/SMA/Dec_13Serv_4LED_6Ftn/Dec_13Serv_4LED_6Ftn.ino +++ b/examples/SMA/Dec_13Serv_4LED_6Ftn/Dec_13Serv_4LED_6Ftn.ino @@ -1,4 +1,4 @@ -// Production 17 Function DCC Decoder +// Production 17 Function DCC Decoder Dec_13Serv_4LED_6Ftn.ino // Version 5.4 Geoff Bunza 2014,2015,2016 // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter @@ -19,7 +19,7 @@ SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,7 +49,6 @@ NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; int t; // temp -#define This_Decoder_Address 24 struct QUEUE { int inuse; @@ -65,12 +64,22 @@ struct CVPair uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { - {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate @@ -137,21 +146,21 @@ CVPair FactoryDefaultCVs [] = {92, 28}, // Start Position Fx=0 {93, 140}, // End Position Fx=1 {94, 28}, // Current Position - {95, 1}, //F13 CConfig 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 20}, // End Position Fx=1 - {99, 1}, // Current Position + {98, 200}, // End Position Fx=1 + {99, 2}, // Current Position {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 4}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {107, 1}, // Start Position Fx=0 {108, 60}, // End Position Fx=1 - {109, 20}, // Current Position + {109, 1}, // Current Position {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {112, 1}, // Start Position Fx=0 @@ -295,7 +304,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { diff --git a/examples/SMA/Dec_15Serv_2LED_6Ftn/Dec_15Serv_2LED_6Ftn.ino b/examples/SMA/Dec_15Serv_2LED_6Ftn/Dec_15Serv_2LED_6Ftn.ino index 653644f..2cfbfdb 100755 --- a/examples/SMA/Dec_15Serv_2LED_6Ftn/Dec_15Serv_2LED_6Ftn.ino +++ b/examples/SMA/Dec_15Serv_2LED_6Ftn/Dec_15Serv_2LED_6Ftn.ino @@ -1,4 +1,4 @@ -// Production 17 Function DCC Decoder +// Production 17 Function DCC Decoder Dec_15Serv_2LED_6Ftn.ino // Version 5.4 Geoff Bunza 2014,2015,2016 // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter @@ -12,14 +12,13 @@ // ******** INFO TO THE SERIAL MONITOR //#define DEBUG - #include #include SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,7 +48,6 @@ NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; int t; // temp -#define This_Decoder_Address 24 struct QUEUE { int inuse; @@ -65,6 +63,9 @@ struct CVPair uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, @@ -147,15 +148,15 @@ CVPair FactoryDefaultCVs [] = {102, 28}, // Start Position Fx=0 {103, 140}, // End Position Fx=1 {104, 28}, // Current Position - {105, 1}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {107, 1}, // Start Position Fx=0 - {108, 10}, // End Position Fx=1 + {108, 60}, // End Position Fx=1 {109, 1}, // Current Position {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {112, 1}, // Start Position Fx=0 - {113, 10}, // End Position Fx=1 + {113, 4}, // End Position Fx=1 {114, 1}, // Current Position //FUTURE USE {115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade @@ -295,7 +296,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { diff --git a/examples/SMA/Dec_17LED_1Ftn/Dec_17LED_1Ftn.ino b/examples/SMA/Dec_17LED_1Ftn/Dec_17LED_1Ftn.ino index 1fd6a8a..81a57f3 100755 --- a/examples/SMA/Dec_17LED_1Ftn/Dec_17LED_1Ftn.ino +++ b/examples/SMA/Dec_17LED_1Ftn/Dec_17LED_1Ftn.ino @@ -1,5 +1,6 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Function DCC Decoder Dec_17LED_1Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses // ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP // ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!! @@ -9,7 +10,7 @@ int tim_delay = 500; #define numleds 17 -byte ledpins [] = {0,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; +byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; const int FunctionPin0 = 3; const int FunctionPin1 = 4; @@ -26,7 +27,6 @@ const int FunctionPin9 = 12; const int FunctionPin10 = 13; const int FunctionPin11 = 14; //A0 const int FunctionPin12 = 15; //A1 - const int FunctionPin13 = 16; //A2 const int FunctionPin14 = 17; //A3 const int FunctionPin15 = 18; //A4 @@ -34,7 +34,6 @@ const int FunctionPin16 = 19; //A5 NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; -#define This_Decoder_Address 24 struct CVPair { @@ -42,15 +41,25 @@ struct CVPair uint8_t Value; }; CVPair FactoryDefaultCVs [] = + +#define This_Decoder_Address 24 + { - {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, }; -uint8_t FactoryDefaultCVIndex = 4; +uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); void notifyCVResetFactoryDefault() { // Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset @@ -78,7 +87,7 @@ void setup() // 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, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); delay(800); #if defined(DECODER_LOADED) if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET ) diff --git a/examples/SMA/Dec_17LED_6Ftn/Dec_17LED_6Ftn.ino b/examples/SMA/Dec_17LED_6Ftn/Dec_17LED_6Ftn.ino index f5d3009..e022030 100755 --- a/examples/SMA/Dec_17LED_6Ftn/Dec_17LED_6Ftn.ino +++ b/examples/SMA/Dec_17LED_6Ftn/Dec_17LED_6Ftn.ino @@ -1,5 +1,6 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Function DCC Decoder Dec_17LED_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -10,15 +11,14 @@ // ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING // ******** INFO TO THE SERIAL MONITOR -//#define DEBUG - +#define DEBUG #include #include SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -48,7 +48,7 @@ NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; int t; // temp -#define This_Decoder_Address 24 + struct QUEUE { int inuse; @@ -64,18 +64,27 @@ struct CVPair uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps {CV_DECODER_MASTER_RESET, 0}, {30, 5}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade - {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate - {32, 0}, //F0 Start Position F0=0 + {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate + {32, 0}, //F0 Start Position F0=0 {33, 8}, //F0 End Position F0=1 - {34, 1}, //F0 Current Position + {34, 1}, //F0 Current Position {35, 5}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {36, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {37, 0}, // Start Position Fx=0 @@ -121,40 +130,40 @@ CVPair FactoryDefaultCVs [] = {77, 28}, // Start Position Fx=0 {78, 140}, // End Position Fx=1 {79, 28}, // Current Position - {80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {82, 1}, // Start Position Fx=0 {83, 5}, // End Position Fx=1 {84, 1}, // Current Position - {85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {87, 1}, // Start Position Fx=0 - {88, 5}, // End Position Fx=1 + {88, 50}, // End Position Fx=1 {89, 1}, // Current Position - {90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {92, 1}, // Start Position Fx=0 - {93, 10}, // End Position Fx=1 + {93, 100}, // End Position Fx=1 {94, 1}, // Current Position - {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 6}, // End Position Fx=1 - {99, 1}, // Current Position - {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {98, 200}, // End Position Fx=1 + {99, 2}, // Current Position + {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 6}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position - {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {107, 1}, // Start Position Fx=0 - {108, 10}, // End Position Fx=1 + {108, 60}, // End Position Fx=1 {109, 1}, // Current Position - {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {112, 1}, // Start Position Fx=0 - {113, 10}, // End Position Fx=1 + {113, 4}, // End Position Fx=1 {114, 1}, // Current Position //FUTURE USE {115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade @@ -164,7 +173,7 @@ CVPair FactoryDefaultCVs [] = {119, 28}, // Current Position }; -uint8_t FactoryDefaultCVIndex = 95; +uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); void notifyCVResetFactoryDefault() { // Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset @@ -172,14 +181,17 @@ void notifyCVResetFactoryDefault() FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); }; +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + void setup() //****************************************************** + { #ifdef DEBUG Serial.begin(115200); #endif int i; uint8_t cv_value; - Serial.begin(115200); // initialize the digital pins as outputs for (int i=0; i < numfpins; i++) { pinMode(fpins[i], OUTPUT); @@ -199,12 +211,12 @@ void setup() //****************************************************** // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); delay(800); #if defined(DECODER_LOADED) if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET ) -#endif +#endif { for (int j=0; j < FactoryDefaultCVIndex; j++ ) @@ -213,8 +225,9 @@ void setup() //****************************************************** delay (1000); digitalWrite(fpins[14], 0); } + for ( i=0; i < numfpins; i++) { - cv_value = Dcc.getCV( 30+(i*5)) ; + cv_value = Dcc.getCV( 30+(i*5)) ; #ifdef DEBUG Serial.print(" cv_value: "); Serial.println(cv_value, DEC) ; @@ -295,7 +308,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { @@ -367,6 +380,12 @@ void loop() //**************************************************************** } void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { +#ifdef DEBUG + Serial.print("Addr= "); + Serial.println(Addr, DEC) ; + Serial.print("FuncState= "); + Serial.println(FuncState, DEC) ; +#endif switch(FuncGrp) { case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1 @@ -403,7 +422,7 @@ void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uin } } void exec_function (int function, int pin, int FuncState) { - switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade case 0: // On - Off LED digitalWrite (pin, FuncState); ftn_queue[function].inuse = 0; @@ -480,4 +499,4 @@ void exec_function (int function, int pin, int FuncState) { ftn_queue[function].inuse = 0; break; } -} +} diff --git a/examples/SMA/Dec_2MotDrive_12LED_1Srv_6Ftn/Dec_2MotDrive_12LED_1Srv_6Ftn.ino b/examples/SMA/Dec_2Mot_12LED_1Srv_6Ftn/Dec_2Mot_12LED_1Srv_6Ftn.ino old mode 100755 new mode 100644 similarity index 89% rename from examples/SMA/Dec_2MotDrive_12LED_1Srv_6Ftn/Dec_2MotDrive_12LED_1Srv_6Ftn.ino rename to examples/SMA/Dec_2Mot_12LED_1Srv_6Ftn/Dec_2Mot_12LED_1Srv_6Ftn.ino index 3374fb3..2f5658f --- a/examples/SMA/Dec_2MotDrive_12LED_1Srv_6Ftn/Dec_2MotDrive_12LED_1Srv_6Ftn.ino +++ b/examples/SMA/Dec_2Mot_12LED_1Srv_6Ftn/Dec_2Mot_12LED_1Srv_6Ftn.ino @@ -1,9 +1,23 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 2 Motor 13 Function DCC Decoder Dec_2MotDrive_12LED_1Srv_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks - +/* + * Motor selection is via motor select Function 13 (Motor1) and Function 14 (Motor2) + * Motor speed for each can only be changed if the corresponding Function is on + * (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function + * is off. Thus, each motor can be controlled independently and run at different speeds. + * F0-F12 control LEDs on Pro Mini Digital Pins 5,6,7,8,11,12,13,14,15,16,17,18,19 + * Simple speed control is made via throttle speed setting for two motors. Motor selection + * is via motor select Function 13 (Motor1) and Function 14 (Motor2). Motor speed for each + * can only be changed if the corresponding Function is on (F13 and/or F14). Motor speed is + * maintained if the corresponding motor select function is off. Thus, each motor can be + * controlled independently and run at different speeds. The other functions are configurable + * but are preset for LED on/off control. +*/ // ******** 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 @@ -18,7 +32,7 @@ SoftwareServo servo[13]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit uint8_t Motor1Speed = 0; @@ -42,7 +56,7 @@ int m0l = 10; //B H Bridge //Motor2 int speedup = 112; //Right track time differntial int deltime = 1500; -int tim_delay = 100; +int tim_delay = 80; int numfpins = 17; int num_active_fpins = 13; byte fpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; @@ -57,6 +71,7 @@ const int FunctionPin6 = 13; const int FunctionPin7 = 14; //A0 const int FunctionPin8 = 15; //A1 + const int FunctionPin9 = 16; //A2 const int FunctionPin10 = 17; //A3 const int FunctionPin11 = 18; //A4 @@ -69,7 +84,6 @@ NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; int t; // temp -#define This_Decoder_Address 24 struct QUEUE { int inuse; @@ -78,20 +92,29 @@ struct QUEUE int stop_value; int start_value; }; -QUEUE *ftn_queue = new QUEUE[16]; +QUEUE *ftn_queue = new QUEUE[17]; -extern uint8_t Decoder_Address = This_Decoder_Address; struct CVPair { uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { - {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, {30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate @@ -186,7 +209,7 @@ CVPair FactoryDefaultCVs [] = {119, 28}, // Current Position }; -uint8_t FactoryDefaultCVIndex = 95; +uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); void notifyCVResetFactoryDefault() { // Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset @@ -194,6 +217,9 @@ void notifyCVResetFactoryDefault() FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); }; +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + void setup() //****************************************************** { #ifdef DEBUG @@ -206,23 +232,21 @@ void setup() //****************************************************** pinMode(fpins[i], OUTPUT); digitalWrite(fpins[i], 0); } - for (int i=0; i < numfpins; i++) { + for (int i=8; i < numfpins; i++) { digitalWrite(fpins[i], 1); - delay (tim_delay/10); + delay (tim_delay); } delay( tim_delay); - for (int i=0; i < numfpins; i++) { + for (int i=8; i < numfpins; i++) { digitalWrite(fpins[i], 0); - delay (tim_delay/10); + delay (tim_delay); } - delay( tim_delay); - // Setup which External Interrupt, the Pin it's associated with that we're using Dcc.pin(0, 2, 0); // Call the main DCC Init function to enable the DCC Receiver - Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); delay(800); - + #if defined(DECODER_LOADED) if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET ) #endif @@ -309,7 +333,6 @@ void setup() //****************************************************** } } } - void loop() //********************************************************************** { //MUST call the NmraDcc.process() method frequently @@ -455,7 +478,6 @@ void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_D Motor2ForwardDir = ForwardDir; } } - void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { switch(FuncGrp) { @@ -570,4 +592,4 @@ void exec_function (int function, int pin, int FuncState) { ftn_queue[function].inuse = 0; break; } -} +} diff --git a/examples/SMA/Dec_2Mot_3LED_TrigAud/Dec_2Mot_3LED_TrigAud.ino b/examples/SMA/Dec_2Mot_3LED_TrigAud/Dec_2Mot_3LED_TrigAud.ino new file mode 100644 index 0000000..4b4b5f9 --- /dev/null +++ b/examples/SMA/Dec_2Mot_3LED_TrigAud/Dec_2Mot_3LED_TrigAud.ino @@ -0,0 +1,702 @@ +// Production 2 Motor w/Triggered Audio Multi Function DCC Decoder Dec_2Mot_3LED_TrigAudio.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses + +// This decoder will control 2 motors and play audio clips by function: +// F0=LED on pin 8, F1-F4 Controls playing specific audio tracks in the 3rd CV (start) at the volume in the 2nd CV (rate) +// F5 Controls playing audio track in CV57 at the volume in CV56 ONLY when F5 is ON and Pin17/A3 is held low, +// and plays continuously until F5 turns off or Pin17 trigger goes HIGH or open +// F6 plays one track selected randomly off the memory card +// F13 and F14 select each separate motor which will respond to speed and direction controls +// F7-F8 control LEDs by default PINS 18 and 19 + +// NO LONGER REQUIRES modified software servo Lib +// Software restructuring mods added from Alex Shepherd and Franz-Peter +// With sincere thanks + +// * MAX 9 Configurations per pin function: +// * 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio +/* + * Motor selection is via motor select Function 13 (Motor1) and Function 14 (Motor2) + * Motor speed for each can only be changed if the corresponding Function is on + * (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function + * is off. Thus, each motor can be controlled independently and run at different speeds. + * F0 LED Pin 8 + * F1-F6 6 Functions Configures As Audio Play + * F7-F8 2 Functions Configures As LEDs by default PINS 18 and 19 + * F13 Motor1 Control Enable + * F14 Motor2 Control Enable + * Pro Mini Transmit-7 (TX) connected to DFPlayer Receive (RX)Pin 2 via 470 Ohm Resistor + * Pro Mini Receive (RX) connected to DFPlayer Transmit (TX) Pin 3 + * Remember to connect +5V and GND to the DFPlayer too: DFPLAYER PINS 1 & 7,10 respectively + * This is a “mobile/function” decoder that adds audio play to dual motor control and + * LED functions. Audio tracks or clips are stored on a micro SD card for playing, + * in a folder labeled mp3, with tracks named 0001.mp3, 0002.mp3, etc. F0 is configured + * as an on/off LED function, F1-F5 play audio tracks 1-5 respectively. + * F6 plays a random selection in random order from tracks 1-6. + * F7-F9 control LEDs on Pro Mini Digital Pins 11-13. + * Simple speed control is made via throttle speed setting for two motors. Motor selection + * is via motor select Function 13 (Motor1) and Function 14 (Motor2). Motor speed for each + * can only be changed if the corresponding Function is on (F13 and/or F14). Motor speed is + * maintained if the corresponding motor select function is off. Thus, each motor can be + * controlled independently and run at different speeds. The other functions are configurable + * but are preset for LED on/off control. +*/ +// ******** 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 + +// ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING +// ******** INFO TO THE SERIAL MONITOR +//#define DEBUG + +#include +#include +#include +#include +SoftwareSerial mySerial(6,7); // PRO MINI RX, PRO MINI TX serial to DFPlayer + +int busy_pin = 5; // DFPlayer Busy status pin +#define num_clips 6 //number of sound tracks/clips on the Micro SD Memory Card +int del_tim = 4000; +int tctr, tctr2, i; +byte audio_on = 0; // Audio ON sets this to 1; otherwise 0 + +SoftwareServo servo[10]; +#define servo_start_delay 50 +#define servo_init_delay 7 +#define servo_slowdown 4 //servo loop counter limit +int servo_slow_counter = 0; //servo loop counter to slowdown servo transit + +uint8_t Motor1Speed = 0; +uint8_t Motor1ForwardDir = 1; +uint8_t Motor1MaxSpeed = 127; +uint8_t Motor2Speed = 0; +uint8_t Motor2ForwardDir = 1; +uint8_t Motor2MaxSpeed = 127; +int kickstarton = 1400; //kick start cycle on time +int kickstarttime = 5; //kick start duration on time +int fwdon = 0; +int fwdtime = 1; +int bwdon = 0; +int bwdtime = 1; +int bwdshift = 0; +int cyclewidth = 2047; +int m2h = 3; //R H Bridge //Motor1 +int m2l = 4; //B H Bridge //Motor1 +int m0h = 9; //R H Bridge //Motor2 +int m0l = 10; //B H Bridge //Motor2 + +int speedup = 112; //Right track time differntial +int deltime = 1500; +int tim_delay = 100; +int numfpins = 13; +int num_active_fpins = 9; +byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,18}; +const int FunctionPin0 = 8; +const int FunctionPin1 = 11; +const int FunctionPin2 = 12; +const int FunctionPin3 = 13; +const int FunctionPin4 = 14; //A0 + +const int FunctionPin5 = 15; //A1 +const int FunctionPin6 = 16; //A2 +const int FunctionPin7 = 18; //A5 +const int FunctionPin8 = 19; //A4 + +const int AudioTriggerPin = 17; //A3 NOW USED AS Audio Trigger Pin INPUT_PULLUP + +const int FunctionPin9 = 20; // Place holders ONLY +const int FunctionPin10 = 20; // Place holders ONLY +const int FunctionPin11 = 20; +const int FunctionPin12 = 20; +const int FunctionPin13 = 20; +const int FunctionPin14 = 20; +const int FunctionPin15 = 20; +const int FunctionPin16 = 20; + +int Function13_value = 0; +int Function14_value = 0; + +NmraDcc Dcc ; +DCC_MSG Packet ; +uint8_t CV_DECODER_MASTER_RESET = 120; +int t; // temp + +struct QUEUE +{ + int inuse; + int current_position; + int increment; + int stop_value; + int start_value; +}; +QUEUE *ftn_queue = new QUEUE[17]; + +struct CVPair +{ + uint16_t CV; + uint8_t Value; +}; + +#define This_Decoder_Address 24 + +CVPair FactoryDefaultCVs [] = +{ + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + + {CV_DECODER_MASTER_RESET, 0}, + {30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {31, 10}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {32, 0}, //F0 Start Position F0=0,Audio=Audio Track/Clip# + {33, 8}, //F0 End Position F0=1 + {34, 1}, //F0 Current Position + {35, 6}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {36, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {37, 1}, // Start Position Fx=0,Audio=Audio Track/Clip# + {38, 8}, // End Position Fx=1 + {39, 1}, // Current Position + {40, 6}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {41, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {42, 2}, // Start Position Fx=0,Audio=Audio Track/Clip# + {43, 140}, // End Position Fx=1 + {44, 0}, // Current Position + {45, 6}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {46, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {47, 3}, // Start Position Fx=0,Audio=Audio Track/Clip# + {48, 140}, // End Position Fx=1 + {49, 0}, // Current Position + {50, 6}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {51, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {52, 4}, // Start Position Fx=0,Audio=Audio Track/Clip# + {53, 140}, // End Position Fx=1 + {54, 0}, // Current Position + {55, 8}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {56, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {57, 6}, // Start Position Fx=0,Audio=Audio Track/Clip# + {58, 140}, // End Position Fx=1 + {59, 0}, // Current Position + {60, 7}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {61, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {62, 6}, // Start Position Fx=0,Audio=Audio Track/Clip# + {63, 140}, // End Position Fx=1 + {64, 28}, // Current Position + {65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {67, 28}, // Start Position Fx=0,Audio=Audio Track/Clip# + {68,140}, // End Position Fx=1 + {69, 28}, // Current Position + {70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {72, 28}, // Start Position Fx=0,Audio=Audio Track/Clip# + {73, 140}, // End Position Fx=1 + {74, 28}, // Current Position + {75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio + {76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {77, 28}, // Start Position Fx=0,Audio=Audio Track/Clip# + {78, 140}, // End Position Fx=1 + {79, 28}, // Current Position +}; + +uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); +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); +}; + +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + +void setup() //****************************************************** +{ +#ifdef DEBUG + Serial.begin(115200); +#endif + pinMode (busy_pin, INPUT); // MUST NOT Pull Up == 3.3V device output pin + pinMode (AudioTriggerPin, INPUT_PULLUP); + + mySerial.begin (9600); + mp3_set_serial (mySerial); //set softwareSerial for DFPlayer-mini mp3 module + mp3_reset (); + delay(100); + mp3_set_volume (18); + delay(50); + audio_on = 0; + uint8_t cv_value; + // initialize the digital pins as outputs + for (int i=0; i < numfpins; i++) { + pinMode(fpins[i], OUTPUT); + digitalWrite(fpins[i], 0); + } + // Setup which External Interrupt, the Pin it's associated with that we're using + Dcc.pin(0, 2, 0); + // Call the main DCC Init function to enable the DCC Receiver + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); + delay(800); + +#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); + digitalWrite(fpins[14], 1); + delay (1000); + digitalWrite(fpins[14], 0); + } + for ( i=0; i < num_active_fpins; i++) { + cv_value = Dcc.getCV( 30+(i*5)) ; +#ifdef DEBUG + Serial.print(" cv_value: "); + Serial.println(cv_value, DEC) ; +#endif + switch ( cv_value ) { + case 0: // LED on/off + ftn_queue[i].inuse = 0; + break; + case 1: // LED Blink + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].start_value = 0; + ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) ; + } + break; + case 2: //servo + { + ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5))); + ftn_queue[i].stop_value = int (Dcc.getCV( 33+(i*5))); + ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5))); + ftn_queue[i].increment = -int (char (Dcc.getCV( 31+(i*5)))); + // attaches servo on pin to the servo object + servo[i].attach(fpins[i]); + +#ifdef DEBUG + Serial.print("InitServo ID= "); + Serial.println(i, DEC) ; +#endif + servo[i].write(ftn_queue[i].start_value); + for (t=0; t ftn_queue[i].stop_value) { + ftn_queue[i].start_value = ~ftn_queue[i].start_value; + digitalWrite(fpins[i], ftn_queue[i].start_value); + ftn_queue[i].current_position = 0; + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))); + } + break; + case 2: + { + if (servo_slow_counter++ > servo_slowdown) + { + ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment; + if (ftn_queue[i].increment > 0) { + if (ftn_queue[i].current_position > ftn_queue[i].stop_value) { + ftn_queue[i].current_position = ftn_queue[i].stop_value; + ftn_queue[i].inuse = 0; + servo[i].detach(); + } + } + if (ftn_queue[i].increment < 0) { + if (ftn_queue[i].current_position < ftn_queue[i].start_value) { + ftn_queue[i].current_position = ftn_queue[i].start_value; + ftn_queue[i].inuse = 0; + servo[i].detach(); + } + } + servo[i].write(ftn_queue[i].current_position); + servo_slow_counter = 0; + } + } + break; + case 3: + ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment; + if (ftn_queue[i].current_position > ftn_queue[i].stop_value) { + ftn_queue[i].start_value = ~ftn_queue[i].start_value; + digitalWrite(fpins[i], ftn_queue[i].start_value); + digitalWrite(fpins[i]+1, ~ftn_queue[i].start_value); + ftn_queue[i].current_position = 0; + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))); + } + i++; + break; + case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + } + break; + case 5: // Fade On + + break; + case 6: // Audio Track Play + if (digitalRead(busy_pin)== HIGH) { + ftn_queue[i].inuse = 0; + } + break; + case 7: // Audio Random Track/Clip Play + if (digitalRead(busy_pin)== HIGH) { + ftn_queue[i].inuse = 0; +/* Insert the following code if you want continuous random play as long as F6 is selected + if (ftn_queue[i].inuse ==1) { // Audio Off continue playing clips + mp3_play (random(1,num_clips)); // play random clip + delay(5); + } +*/ + } + break; + case 8: // Triggered Audio Track Play + if (ftn_queue[i].inuse ==1) { // Function is set ON + if ((digitalRead(AudioTriggerPin)== LOW)&&(digitalRead(busy_pin)== HIGH)) { // Trigger ON Audio Off + mp3_set_volume (ftn_queue[i].increment); + delay(8); + mp3_play (ftn_queue[i].start_value); // play clip function + delay(5); + } + } + break; + case 9: // NEXT FEATURE for the Future + break; + default: + break; + } + } + } +} +void gofwd1(int fcnt,int fcycle) { + int icnt; + int totcycle; + icnt = 0; + while (icnt < fcnt) + { + digitalWrite(m2h, HIGH); //Motor1 + delayMicroseconds(fcycle); + digitalWrite(m2h, LOW); //Motor1 + delayMicroseconds(cyclewidth - fcycle); + icnt++; + } +} +void gobwd1(int bcnt,int bcycle) { + int icnt; + icnt=0; + while (icnt < bcnt) + { + digitalWrite(m2l, HIGH); //Motor1 + delayMicroseconds(bcycle); + digitalWrite(m2l, LOW); //Motor1 + delayMicroseconds(cyclewidth - bcycle); + icnt++; + } +} +void gofwd2(int fcnt,int fcycle) { + int icnt; + int totcycle; + icnt = 0; + while (icnt < fcnt) + { + digitalWrite(m0h, HIGH); //Motor2 + delayMicroseconds(fcycle); + digitalWrite(m0h, LOW); //Motor2 + delayMicroseconds(cyclewidth - fcycle); + icnt++; + } +} +void gobwd2(int bcnt,int bcycle) { + int icnt; + icnt=0; + while (icnt < bcnt) + { + digitalWrite(m0l, HIGH); //Motor2 + delayMicroseconds(bcycle); + digitalWrite(m0l, LOW); //Motor2 + delayMicroseconds(cyclewidth - bcycle); + icnt++; + } +} +void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) { + if (Function13_value==1) { + Motor1Speed = Speed; + Motor1ForwardDir = ForwardDir; + } + if (Function14_value==1) { + Motor2Speed = Speed; + Motor2ForwardDir = ForwardDir; + } +} + +void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { +#ifdef DEBUG + Serial.print("Addr= "); + Serial.println(Addr, DEC) ; + Serial.print("FuncState= "); + Serial.println(FuncState, DEC) ; +#endif + switch(FuncGrp) + { + case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1 + exec_function( 0, FunctionPin0, (FuncState & FN_BIT_00)>>4 ); + exec_function( 1, FunctionPin1, (FuncState & FN_BIT_01)); + exec_function( 2, FunctionPin2, (FuncState & FN_BIT_02)>>1); + exec_function( 3, FunctionPin3, (FuncState & FN_BIT_03)>>2 ); + exec_function( 4, FunctionPin4, (FuncState & FN_BIT_04)>>3 ); + break; + + case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8 + exec_function( 5, FunctionPin5, (FuncState & FN_BIT_05)); + exec_function( 6, FunctionPin6, (FuncState & FN_BIT_06)>>1 ); + exec_function( 7, FunctionPin7, (FuncState & FN_BIT_07)>>2 ); + exec_function( 8, FunctionPin8, (FuncState & FN_BIT_08)>>3 ); + break; + + case FN_9_12: + exec_function( 9, FunctionPin9, (FuncState & FN_BIT_09)); +// exec_function( 10, FunctionPin10, (FuncState & FN_BIT_10)>>1 ); +// exec_function( 11, FunctionPin11, (FuncState & FN_BIT_11)>>2 ); +// exec_function( 12, FunctionPin12, (FuncState & FN_BIT_12)>>3 ); + break; + + case FN_13_20: //Function Group 2 FuncState == F20-F13 Function Control + Function13_value = (FuncState & FN_BIT_13); + Function14_value = (FuncState & FN_BIT_14)>>1; +// exec_function( 15, FunctionPin15, (FuncState & FN_BIT_15)>>2 ); +// exec_function( 16, FunctionPin16, (FuncState & FN_BIT_16)>>3 ); + break; + + case FN_21_28: + break; + } +} +void exec_function (int function, int pin, int FuncState) { + switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + case 0: // On - Off LED + digitalWrite (pin, FuncState); + ftn_queue[function].inuse = 0; + break; + case 1: // Blinking LED + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + ftn_queue[function].start_value = 0; + digitalWrite(pin, 0); + ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5))); + } else { + if ((ftn_queue[function].inuse==1) && (FuncState==0)) { + ftn_queue[function].inuse = 0; + digitalWrite(pin, 0); + } + } + break; + case 2: // Servo + if (ftn_queue[function].inuse == 0) { + ftn_queue[function].inuse = 1; + servo[function].attach(pin); + } + if (FuncState==1) ftn_queue[function].increment = char ( Dcc.getCV( 31+(function*5))); + else ftn_queue[function].increment = - char(Dcc.getCV( 31+(function*5))); + if (FuncState==1) ftn_queue[function].stop_value = Dcc.getCV( 33+(function*5)); + else ftn_queue[function].stop_value = Dcc.getCV( 32+(function*5)); + break; + case 3: // Blinking LED PAIR + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + ftn_queue[function].start_value = 0; + digitalWrite(fpins[function], 0); + digitalWrite(fpins[function+1], 1); + ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5))); + } else { + if (FuncState==0) { + ftn_queue[function].inuse = 0; + digitalWrite(fpins[function], 0); + digitalWrite(fpins[function+1], 0); + } + } + break; + case 4: // Pulse Output based on Rate*10 Milliseconds + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { //First Turn On Detected + digitalWrite(fpins[function], 1); + delay (10*ftn_queue[function].increment); + digitalWrite(fpins[function], 0); + ftn_queue[function].inuse = 1; //inuse set to 1 says we already pulsed + } else + if (FuncState==0) ftn_queue[function].inuse = 0; + break; + case 5: // Fade On +#define fadedelay 24 + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + for (t=0; t +#include +#include +#include +SoftwareSerial mySerial(6,7); // PRO MINI RX, PRO MINI TX serial to DFPlayer + +int busy_pin = 5; // DFPlayer Busy status pin +#define num_clips 6 //number of sound tracks/clips on the Micro SD Memory Card +int del_tim = 4000; +int tctr, tctr2, i; +byte audio_on = 0; // Audio ON sets this to 1; otherwise 0 + +SoftwareServo servo[10]; +#define servo_start_delay 50 +#define servo_init_delay 7 +#define servo_slowdown 4 //servo loop counter limit +int servo_slow_counter = 0; //servo loop counter to slowdown servo transit + +uint8_t Motor1Speed = 0; +uint8_t Motor1ForwardDir = 1; +uint8_t Motor1MaxSpeed = 127; +uint8_t Motor2Speed = 0; +uint8_t Motor2ForwardDir = 1; +uint8_t Motor2MaxSpeed = 127; +int kickstarton = 1400; //kick start cycle on time +int kickstarttime = 5; //kick start duration on time +int fwdon = 0; +int fwdtime = 1; +int bwdon = 0; +int bwdtime = 1; +int bwdshift = 0; +int cyclewidth = 2047; +int m2h = 3; //R H Bridge //Motor1 +int m2l = 4; //B H Bridge //Motor1 +int m0h = 9; //R H Bridge //Motor2 +int m0l = 10; //B H Bridge //Motor2 + +int speedup = 112; //Right track time differntial +int deltime = 1500; +int tim_delay = 100; +int numfpins = 14; +int num_active_fpins = 10; +byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,17,18,19}; +const int FunctionPin0 = 8; +const int FunctionPin1 = 11; +const int FunctionPin2 = 12; +const int FunctionPin3 = 13; +const int FunctionPin4 = 14; //A0 + +const int FunctionPin5 = 15; //A1 +const int FunctionPin6 = 16; //A2 +const int FunctionPin7 = 17; //A3 +const int FunctionPin8 = 18; //A4 +const int FunctionPin9 = 19; //A5 + +const int FunctionPin10 = 20; // Place holders ONLY +const int FunctionPin11 = 20; +const int FunctionPin12 = 20; +const int FunctionPin13 = 20; +const int FunctionPin14 = 20; +const int FunctionPin15 = 20; +const int FunctionPin16 = 20; + +int Function13_value = 0; +int Function14_value = 0; + +NmraDcc Dcc ; +DCC_MSG Packet ; +uint8_t CV_DECODER_MASTER_RESET = 120; +int t; // temp + +struct QUEUE +{ + int inuse; + int current_position; + int increment; + int stop_value; + int start_value; +}; +QUEUE *ftn_queue = new QUEUE[17]; + +struct CVPair +{ + uint16_t CV; + uint8_t Value; +}; + +#define This_Decoder_Address 24 + +CVPair FactoryDefaultCVs [] = +{ + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + + {CV_DECODER_MASTER_RESET, 0}, + {30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {31, 10}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {32, 0}, //F0 Start Position F0=0,Audio=Audio Track/Clip# + {33, 8}, //F0 End Position F0=1 + {34, 1}, //F0 Current Position + {35, 6}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {36, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {37, 1}, // Start Position Fx=0,Audio=Audio Track/Clip# + {38, 8}, // End Position Fx=1 + {39, 1}, // Current Position + {40, 6}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {41, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {42, 2}, // Start Position Fx=0,Audio=Audio Track/Clip# + {43, 140}, // End Position Fx=1 + {44, 0}, // Current Position + {45, 6}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {46, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {47, 3}, // Start Position Fx=0,Audio=Audio Track/Clip# + {48, 140}, // End Position Fx=1 + {49, 0}, // Current Position + {50, 6}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {51, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {52, 4}, // Start Position Fx=0,Audio=Audio Track/Clip# + {53, 140}, // End Position Fx=1 + {54, 0}, // Current Position + {55, 6}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {56, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {57, 5}, // Start Position Fx=0,Audio=Audio Track/Clip# + {58, 140}, // End Position Fx=1 + {59, 28}, // Current Position + {60, 7}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {61, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {62, 6}, // Start Position Fx=0,Audio=Audio Track/Clip# + {63, 140}, // End Position Fx=1 + {64, 28}, // Current Position + {65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {67, 28}, // Start Position Fx=0,Audio=Audio Track/Clip# + {68,140}, // End Position Fx=1 + {69, 28}, // Current Position + {70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {72, 28}, // Start Position Fx=0,Audio=Audio Track/Clip# + {73, 140}, // End Position Fx=1 + {74, 28}, // Current Position + {75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio + {76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30) + {77, 28}, // Start Position Fx=0,Audio=Audio Track/Clip# + {78, 140}, // End Position Fx=1 + {79, 28}, // Current Position +}; + +uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); +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); +}; + +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + +void setup() //****************************************************** +{ +#ifdef DEBUG + Serial.begin(115200); +#endif + pinMode (busy_pin, INPUT); + mySerial.begin (9600); + mp3_set_serial (mySerial); //set softwareSerial for DFPlayer-mini mp3 module + mp3_reset (); + delay(100); + mp3_set_volume (18); + delay(50); + audio_on = 0; + uint8_t cv_value; + // initialize the digital pins as outputs + for (int i=0; i < numfpins; i++) { + pinMode(fpins[i], OUTPUT); + digitalWrite(fpins[i], 0); + } + // Setup which External Interrupt, the Pin it's associated with that we're using + Dcc.pin(0, 2, 0); + // Call the main DCC Init function to enable the DCC Receiver + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); + delay(800); + +#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); + digitalWrite(fpins[14], 1); + delay (1000); + digitalWrite(fpins[14], 0); + } + for ( i=0; i < num_active_fpins; i++) { + cv_value = Dcc.getCV( 30+(i*5)) ; +#ifdef DEBUG + Serial.print(" cv_value: "); + Serial.println(cv_value, DEC) ; +#endif + switch ( cv_value ) { + case 0: // LED on/off + ftn_queue[i].inuse = 0; + break; + case 1: // LED Blink + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].start_value = 0; + ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) ; + } + break; + case 2: //servo + { + ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5))); + ftn_queue[i].stop_value = int (Dcc.getCV( 33+(i*5))); + ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5))); + ftn_queue[i].increment = -int (char (Dcc.getCV( 31+(i*5)))); + // attaches servo on pin to the servo object + servo[i].attach(fpins[i]); + +#ifdef DEBUG + Serial.print("InitServo ID= "); + Serial.println(i, DEC) ; +#endif + servo[i].write(ftn_queue[i].start_value); + for (t=0; t ftn_queue[i].stop_value) { + ftn_queue[i].start_value = ~ftn_queue[i].start_value; + digitalWrite(fpins[i], ftn_queue[i].start_value); + ftn_queue[i].current_position = 0; + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))); + } + break; + case 2: + { + if (servo_slow_counter++ > servo_slowdown) + { + ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment; + if (ftn_queue[i].increment > 0) { + if (ftn_queue[i].current_position > ftn_queue[i].stop_value) { + ftn_queue[i].current_position = ftn_queue[i].stop_value; + ftn_queue[i].inuse = 0; + servo[i].detach(); + } + } + if (ftn_queue[i].increment < 0) { + if (ftn_queue[i].current_position < ftn_queue[i].start_value) { + ftn_queue[i].current_position = ftn_queue[i].start_value; + ftn_queue[i].inuse = 0; + servo[i].detach(); + } + } + servo[i].write(ftn_queue[i].current_position); + servo_slow_counter = 0; + } + } + break; + case 3: + ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment; + if (ftn_queue[i].current_position > ftn_queue[i].stop_value) { + ftn_queue[i].start_value = ~ftn_queue[i].start_value; + digitalWrite(fpins[i], ftn_queue[i].start_value); + digitalWrite(fpins[i]+1, ~ftn_queue[i].start_value); + ftn_queue[i].current_position = 0; + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))); + } + i++; + break; + case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + } + break; + case 5: // Fade On + + break; + case 6: // Audio Track Play + if (digitalRead(busy_pin)== HIGH) { + ftn_queue[i].inuse = 0; + } + break; + case 7: // Audio Random Track/Clip Play + if (digitalRead(busy_pin)== HIGH) { + ftn_queue[i].inuse = 0; +/* Insert the following code if you want continuous random play as long as F6 is selected + if (ftn_queue[i].inuse ==1) { // Audio Off continue playing clips + mp3_play (random(1,num_clips)); // play random clip + delay(5); + } +*/ + } + break; + case 8: // NEXT FEATURE to pin + break; + default: + break; + } + } + } +} +void gofwd1(int fcnt,int fcycle) { + int icnt; + int totcycle; + icnt = 0; + while (icnt < fcnt) + { + digitalWrite(m2h, HIGH); //Motor1 + delayMicroseconds(fcycle); + digitalWrite(m2h, LOW); //Motor1 + delayMicroseconds(cyclewidth - fcycle); + icnt++; + } +} +void gobwd1(int bcnt,int bcycle) { + int icnt; + icnt=0; + while (icnt < bcnt) + { + digitalWrite(m2l, HIGH); //Motor1 + delayMicroseconds(bcycle); + digitalWrite(m2l, LOW); //Motor1 + delayMicroseconds(cyclewidth - bcycle); + icnt++; + } +} +void gofwd2(int fcnt,int fcycle) { + int icnt; + int totcycle; + icnt = 0; + while (icnt < fcnt) + { + digitalWrite(m0h, HIGH); //Motor2 + delayMicroseconds(fcycle); + digitalWrite(m0h, LOW); //Motor2 + delayMicroseconds(cyclewidth - fcycle); + icnt++; + } +} +void gobwd2(int bcnt,int bcycle) { + int icnt; + icnt=0; + while (icnt < bcnt) + { + digitalWrite(m0l, HIGH); //Motor2 + delayMicroseconds(bcycle); + digitalWrite(m0l, LOW); //Motor2 + delayMicroseconds(cyclewidth - bcycle); + icnt++; + } +} +void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) { + if (Function13_value==1) { + Motor1Speed = Speed; + Motor1ForwardDir = ForwardDir; + } + if (Function14_value==1) { + Motor2Speed = Speed; + Motor2ForwardDir = ForwardDir; + } +} + +void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { +#ifdef DEBUG + Serial.print("Addr= "); + Serial.println(Addr, DEC) ; + Serial.print("FuncState= "); + Serial.println(FuncState, DEC) ; +#endif + switch(FuncGrp) + { + case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1 + exec_function( 0, FunctionPin0, (FuncState & FN_BIT_00)>>4 ); + exec_function( 1, FunctionPin1, (FuncState & FN_BIT_01)); + exec_function( 2, FunctionPin2, (FuncState & FN_BIT_02)>>1); + exec_function( 3, FunctionPin3, (FuncState & FN_BIT_03)>>2 ); + exec_function( 4, FunctionPin4, (FuncState & FN_BIT_04)>>3 ); + break; + + case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8 + exec_function( 5, FunctionPin5, (FuncState & FN_BIT_05)); + exec_function( 6, FunctionPin6, (FuncState & FN_BIT_06)>>1 ); + exec_function( 7, FunctionPin7, (FuncState & FN_BIT_07)>>2 ); + exec_function( 8, FunctionPin8, (FuncState & FN_BIT_08)>>3 ); + break; + + case FN_9_12: + exec_function( 9, FunctionPin9, (FuncState & FN_BIT_09)); +// exec_function( 10, FunctionPin10, (FuncState & FN_BIT_10)>>1 ); +// exec_function( 11, FunctionPin11, (FuncState & FN_BIT_11)>>2 ); +// exec_function( 12, FunctionPin12, (FuncState & FN_BIT_12)>>3 ); + break; + + case FN_13_20: //Function Group 2 FuncState == F20-F13 Function Control + Function13_value = (FuncState & FN_BIT_13); + Function14_value = (FuncState & FN_BIT_14)>>1; +// exec_function( 15, FunctionPin15, (FuncState & FN_BIT_15)>>2 ); +// exec_function( 16, FunctionPin16, (FuncState & FN_BIT_16)>>3 ); + break; + + case FN_21_28: + break; + } +} +void exec_function (int function, int pin, int FuncState) { + switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + case 0: // On - Off LED + digitalWrite (pin, FuncState); + ftn_queue[function].inuse = 0; + break; + case 1: // Blinking LED + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + ftn_queue[function].start_value = 0; + digitalWrite(pin, 0); + ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5))); + } else { + if ((ftn_queue[function].inuse==1) && (FuncState==0)) { + ftn_queue[function].inuse = 0; + digitalWrite(pin, 0); + } + } + break; + case 2: // Servo + if (ftn_queue[function].inuse == 0) { + ftn_queue[function].inuse = 1; + servo[function].attach(pin); + } + if (FuncState==1) ftn_queue[function].increment = char ( Dcc.getCV( 31+(function*5))); + else ftn_queue[function].increment = - char(Dcc.getCV( 31+(function*5))); + if (FuncState==1) ftn_queue[function].stop_value = Dcc.getCV( 33+(function*5)); + else ftn_queue[function].stop_value = Dcc.getCV( 32+(function*5)); + break; + case 3: // Blinking LED PAIR + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + ftn_queue[function].start_value = 0; + digitalWrite(fpins[function], 0); + digitalWrite(fpins[function+1], 1); + ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5))); + } else { + if (FuncState==0) { + ftn_queue[function].inuse = 0; + digitalWrite(fpins[function], 0); + digitalWrite(fpins[function+1], 0); + } + } + break; + case 4: // Pulse Output based on Rate*10 Milliseconds + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { //First Turn On Detected + digitalWrite(fpins[function], 1); + delay (10*ftn_queue[function].increment); + digitalWrite(fpins[function], 0); + ftn_queue[function].inuse = 1; //inuse set to 1 says we already pulsed + } else + if (FuncState==0) ftn_queue[function].inuse = 0; + break; + case 5: // Fade On +#define fadedelay 24 + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + for (t=0; t #include @@ -19,7 +18,7 @@ SoftwareServo servo[17]; #define servo_start_delay 50 #define servo_init_delay 7 -#define servo_slowdown 3 //servo loop counter limit +#define servo_slowdown 12 //servo loop counter limit int servo_slow_counter = 0; //servo loop counter to slowdown servo transit int tim_delay = 500; @@ -49,7 +48,6 @@ NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; int t; // temp -#define This_Decoder_Address 24 struct QUEUE { int inuse; @@ -65,12 +63,22 @@ struct CVPair uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { - {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, {30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate @@ -130,28 +138,28 @@ CVPair FactoryDefaultCVs [] = {85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {87, 1}, // Start Position Fx=0 - {88, 5}, // End Position Fx=1 + {88, 50}, // End Position Fx=1 {89, 1}, // Current Position {90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {92, 1}, // Start Position Fx=0 - {93, 20}, // End Position Fx=1 + {93, 100}, // End Position Fx=1 {94, 1}, // Current Position {95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {97, 1}, // Start Position Fx=0 - {98, 35}, // End Position Fx=1 + {98, 200}, // End Position Fx=1 {99, 2}, // Current Position {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {102, 1}, // Start Position Fx=0 - {103, 4}, // End Position Fx=1 + {103, 200}, // End Position Fx=1 {104, 1}, // Current Position {105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {107, 1}, // Start Position Fx=0 {108, 60}, // End Position Fx=1 - {109, 20}, // Current Position + {109, 1}, // Current Position {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate {112, 1}, // Start Position Fx=0 @@ -295,7 +303,7 @@ void loop() //**************************************************************** // from the Arduino loop() function for correct library operation Dcc.process(); SoftwareServo::refresh(); - delay(4); + delay(3); for (int i=0; i < numfpins; i++) { if (ftn_queue[i].inuse==1) { @@ -480,4 +488,4 @@ void exec_function (int function, int pin, int FuncState) { ftn_queue[function].inuse = 0; break; } -} +} diff --git a/examples/SMA/Dec_Dir_and_Fade/Dec_Dir_and_Fade.ino b/examples/SMA/Dec_Dir_and_Fade/Dec_Dir_and_Fade.ino index 8651c1f..2df4109 100755 --- a/examples/SMA/Dec_Dir_and_Fade/Dec_Dir_and_Fade.ino +++ b/examples/SMA/Dec_Dir_and_Fade/Dec_Dir_and_Fade.ino @@ -1,6 +1,8 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 -// LED control is dependent on direction of travel +// Production 17 Function DCC Decoder Dec_Dir_and_Fade.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses +// LED control is dependent on direction of travel and Fade can be added + // ******** 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 @@ -11,11 +13,12 @@ int tim_delay = 500; #define numleds 17 byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; //Defines all possible LED pins +// IMPORTANT: // The following list defines how each of the 17 function pins operate: // a 0 allows for normal On/Off control with fade on and fade off // a 1 allows for normal control when the decoder sees a forward speed setting, reverse turns the LED off // a 2 allows for normal control when the decoder sees a reverse speed setting, forward turns the LED off -byte led_direction [] = {0,1,2,0,1,1,1,1,2,2,2,2,0,0,0,0,0}; //0=On/Off, 1=On Forward, 2=On Reverse +byte led_direction [] = {0,1,2,0,1,1,1,1,2,2,2,1,1,1,2,0,0}; //0=On/Off, 1=On Forward, 2=On Reverse boolean led_last_state [] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false}; //last state of led boolean Last_Function_State[] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false}; //These hold the last Fx assignments @@ -46,18 +49,27 @@ NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; -#define This_Decoder_Address 24 struct CVPair { uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { - {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, }; uint8_t FactoryDefaultCVIndex = 0; @@ -98,7 +110,7 @@ void setup() // 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, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); } void loop() { @@ -201,4 +213,4 @@ void Switch_LED (int Function) { } led_last_state[Function] = end_state; } - + diff --git a/examples/SMA/Dec_SMA12_LED_Groups/Dec_SMA12_LED_Groups.ino b/examples/SMA/Dec_SMA12_LED_Groups/Dec_SMA12_LED_Groups.ino index 7af8a0b..413678a 100755 --- a/examples/SMA/Dec_SMA12_LED_Groups/Dec_SMA12_LED_Groups.ino +++ b/examples/SMA/Dec_SMA12_LED_Groups/Dec_SMA12_LED_Groups.ino @@ -1,5 +1,7 @@ -// Production 17 Function DCC Decoder -// Version 5.4 Geoff Bunza 2014,2015,2016 +// Production 17 Function DCC Decoder Dec_SMA12_LED_Groups.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses + // NO LONGER REQUIRES modified software servo Lib // Software restructuring mods added from Alex Shepherd and Franz-Peter // With sincere thanks @@ -13,8 +15,8 @@ //#define DEBUG #include - int tim_delay = 500; + #define numleds 17 byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; byte FPins_Assigned [12][5] = { // This array defines the pins controlled by each function @@ -52,14 +54,17 @@ const int FunctionPin1 = 4; const int FunctionPin2 = 5; const int FunctionPin3 = 6; const int FunctionPin4 = 7; + const int FunctionPin5 = 8; const int FunctionPin6 = 9; const int FunctionPin7 = 10; const int FunctionPin8 = 11; + const int FunctionPin9 = 12; const int FunctionPin10 = 13; const int FunctionPin11 = 14; //A0 const int FunctionPin12 = 15; //A1 + const int FunctionPin13 = 16; //A2 const int FunctionPin14 = 17; //A3 const int FunctionPin15 = 18; //A4 @@ -67,24 +72,31 @@ const int FunctionPin16 = 19; //A5 NmraDcc Dcc ; DCC_MSG Packet ; uint8_t CV_DECODER_MASTER_RESET = 120; - -#define This_Decoder_Address 24 - struct CVPair { uint16_t CV; uint8_t Value; }; + +#define This_Decoder_Address 24 + CVPair FactoryDefaultCVs [] = { - {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address}, - {CV_ACCESSORY_DECODER_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, - {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0}, + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + {CV_DECODER_MASTER_RESET, 0}, }; -uint8_t FactoryDefaultCVIndex = 0; +uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); void notifyCVResetFactoryDefault() { // Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset @@ -112,7 +124,11 @@ void setup() delay (tim_delay/10); } delay( tim_delay); - + // 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, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); + delay(800); #if defined(DECODER_LOADED) if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET ) #endif @@ -123,18 +139,12 @@ void setup() delay (1000); digitalWrite(ledpins[14], 0); } - // 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, 100, FLAGS_MY_ADDRESS_ONLY, 0 ); - delay(800); } void loop() { // You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation Dcc.process(); } - void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { int f_index; switch (FuncGrp) { @@ -145,20 +155,17 @@ switch (FuncGrp) { exec_function( 3, (FuncState & FN_BIT_03)>>2 ); exec_function( 4, (FuncState & FN_BIT_04)>>3 ); break; - case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8 exec_function( 5, (FuncState & FN_BIT_05)); exec_function( 6, (FuncState & FN_BIT_06)>>1 ); exec_function( 7, (FuncState & FN_BIT_07)>>2 ); exec_function( 8, (FuncState & FN_BIT_08)>>3 ); - break; - + break; case FN_9_12: exec_function( 9, (FuncState & FN_BIT_09)); exec_function( 10,(FuncState & FN_BIT_10)>>1 ); exec_function( 11,(FuncState & FN_BIT_11)>>2 ); break; - } } void exec_function (int f_index, int FuncState) { diff --git a/examples/SMA/Dec_Stepper_6Ftn/Dec_Stepper_6Ftn.ino b/examples/SMA/Dec_Stepper_6Ftn/Dec_Stepper_6Ftn.ino new file mode 100644 index 0000000..9bde9b7 --- /dev/null +++ b/examples/SMA/Dec_Stepper_6Ftn/Dec_Stepper_6Ftn.ino @@ -0,0 +1,508 @@ +// Production Stepper Drive DCC Decoder Dec_Stepper_6Ftn.ino +// Version 6.0 Geoff Bunza 2014,2015,2016,2017,2018 +// Now works with both short and long DCC Addesses + +// NO LONGER REQUIRES modified software servo Lib +// Software restructuring mods added from Alex Shepherd and Franz-Peter +// With sincere thanks +/* + * Stepper Motor Drive (4 Pins Bi dirrectional) uses the 2 Motor controls MOT1 and MOT2 + * F0 LED Pin 5 + * This is a “mobile/function” decoder that controls a single four wire stepper motor + * (5/12 Volt) via throttle speed setting and a multiplier which can be set in CV121. + * Stepper speed is pre-set in the sketch but can be changed. The library also supports + * setting acceleration/deceleration for the stepper. The other functions are configurable + * but are preset for LED on/off control. No servo motor control is available. + * Steppers whose coils need less than 500 ma can be accommodated. Each coil of the + * stepper attaches to MOT1 and MOT2. You may have to reverse the connections of one + * or the other until you get the connections right. The number of steps moved is set + * by the speed setting multiplied by the contents of CV 121. + * Every Off to On activation of F2 will move the stepper the specified number of steps, + * in the direction set by the DCC speed direction. +*/ +// ******** 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 + +// ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING +// ******** INFO TO THE SERIAL MONITOR +//#define DEBUG + +#include +#include +AccelStepper stepper(AccelStepper::FULL4WIRE, 3, 4, 9, 10); + +int servo_slow_counter = 0; //servo loop counter to slowdown servo transit +long Motor1Speed = 0; +uint8_t Motor1ForwardDir = 1; +uint8_t Motor1MaxSpeed = 127; +long Motor2Speed = 0; +uint8_t Motor2ForwardDir = 1; +uint8_t Motor2MaxSpeed = 127; +int kickstarton = 1400; //kick start cycle on time +int kickstarttime = 5; //kick start duration on time +int fwdon = 0; +int fwdtime = 1; +int bwdon = 0; +int bwdtime = 1; +int bwdshift = 0; +int cyclewidth = 2047; +int m2h = 3; //R H Bridge //Motor1 +int m2l = 4; //B H Bridge //Motor1 +int m0h = 9; //R H Bridge //Motor2 +int m0l = 10; //B H Bridge //Motor2 + +int speedup = 112; //Right track time differntial +int deltime = 1500; +int tim_delay = 100; +int numfpins = 17; +int num_active_fpins = 13; +byte fpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; +const int FunctionPin0 = 5; +const int FunctionPin1 = 6; +const int FunctionPin2 = 7; +const int FunctionPin3 = 8; +const int FunctionPin4 = 11; + +const int FunctionPin5 = 12; +const int FunctionPin6 = 13; +const int FunctionPin7 = 14; //A0 +const int FunctionPin8 = 15; //A1 + +const int FunctionPin9 = 16; //A2 +const int FunctionPin10 = 17; //A3 +const int FunctionPin11 = 18; //A4 +const int FunctionPin12 = 19; //A5 + +byte Function2_value = 0; +int Function13_value = 0; +int Function14_value = 0; + +NmraDcc Dcc ; +DCC_MSG Packet ; +uint8_t CV_DECODER_MASTER_RESET = 120; +uint8_t Motor_Multiplier = 121; +int t; // temp + +struct QUEUE +{ + int inuse; + int current_position; + int increment; + int stop_value; + int start_value; +}; +QUEUE *ftn_queue = new QUEUE[16]; +struct CVPair +{ + uint16_t CV; + uint8_t Value; +}; + +#define This_Decoder_Address 24 + +CVPair FactoryDefaultCVs [] = +{ + {CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F }, + + // These two CVs define the Long DCC Address + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 }, + {CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF }, + + // 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 | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps + + {CV_DECODER_MASTER_RESET, 0}, // CV 120 + {Motor_Multiplier, 10}, // CV 121 + {30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate + {32, 0}, //F0 Start Position F0=0 + {33, 8}, //F0 End Position F0=1 + {34, 1}, //F0 Current Position + {35, 0}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {36, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {37, 0}, // Start Position Fx=0 + {38, 8}, // End Position Fx=1 + {39, 1}, // Current Position + {40, 0}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {41, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {42, 28}, // Start Position Fx=0 + {43, 140}, // End Position Fx=1 + {44, 0}, // Current Position + {45, 0}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {46, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {47, 28}, // Start Position Fx=0 + {48, 140}, // End Position Fx=1 + {49, 0}, // Current Position + {50, 0}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {51, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {52, 28}, // Start Position Fx=0 + {53, 140}, // End Position Fx=1 + {54, 0}, // Current Position + {55, 0}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {56, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {57, 28}, // Start Position Fx=0 + {58, 140}, // End Position Fx=1 + {59, 28}, // Current Position + {60, 0}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {61, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {62, 1}, // Start Position Fx=0 + {63, 255}, // End Position Fx=1 + {64, 28}, // Current Position + {65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {67, 28}, // Start Position Fx=0 + {68,140}, // End Position Fx=1 + {69, 28}, // Current Position + {70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {72, 28}, // Start Position Fx=0 + {73, 140}, // End Position Fx=1 + {74, 28}, // Current Position + {75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {77, 28}, // Start Position Fx=0 + {78, 140}, // End Position Fx=1 + {79, 28}, // Current Position + {80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {82, 1}, // Start Position Fx=0 + {83, 5}, // End Position Fx=1 + {84, 1}, // Current Position + {85, 0}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {87, 1}, // Start Position Fx=0 + {88, 5}, // End Position Fx=1 + {89, 1}, // Current Position + {90, 0}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {92, 1}, // Start Position Fx=0 + {93, 10}, // End Position Fx=1 + {94, 1}, // Current Position + {95, 0}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {97, 1}, // Start Position Fx=0 + {98, 6}, // End Position Fx=1 + {99, 1}, // Current Position + {100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {102, 1}, // Start Position Fx=0 + {103, 6}, // End Position Fx=1 + {104, 1}, // Current Position + {105, 0}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {107, 1}, // Start Position Fx=0 + {108, 10}, // End Position Fx=1 + {109, 1}, // Current Position + {110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {112, 1}, // Start Position Fx=0 + {113, 10}, // End Position Fx=1 + {114, 1}, // Current Position +//FUTURE USE + {115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + {116, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate + {117, 28}, // Start Position Fx=0 + {118, 50}, // End Position Fx=1 + {119, 28}, // Current Position +}; + +uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair); +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); +}; + +// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE +// OUTPUT PINS FOR FUNCTIONS + +void setup() //****************************************************** +{ +#ifdef DEBUG + Serial.begin(115200); +#endif + int i; + uint8_t cv_value; + // initialize the digital pins as outputs + for (int i=0; i < numfpins; i++) { + pinMode(fpins[i], OUTPUT); + digitalWrite(fpins[i], 0); + } + + // Setup which External Interrupt, the Pin it's associated with that we're using + Dcc.pin(0, 2, 0); + // Call the main DCC Init function to enable the DCC Receiver + Dcc.init( MAN_ID_DIY, 600, FLAGS_MY_ADDRESS_ONLY, 0 ); + delay(800); + +#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); + digitalWrite(fpins[14], 1); + delay (1000); + digitalWrite(fpins[14], 0); + } + for ( i=0; i < num_active_fpins; i++) { + cv_value = Dcc.getCV( 30+(i*5)) ; +#ifdef DEBUG + Serial.print(" cv_value: "); + Serial.println(cv_value, DEC) ; +#endif + stepper.setMaxSpeed(100.0); + stepper.setAcceleration(50.0); + stepper.moveTo(1); + switch ( cv_value ) { + case 0: // LED on/off + ftn_queue[i].inuse = 0; + break; + case 1: // LED Blink + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].start_value = 0; + ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) ; + } + break; + case 2: //servo NOT AVAILABLE WITH THIS DECODER - STEPPER ONLY + break; + case 3: // DOUBLE ALTERNATING LED Blink + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].start_value = 0; + ftn_queue[i].increment = Dcc.getCV( 31+(i*5)); + digitalWrite(fpins[i], 0); + digitalWrite(fpins[i+1], 0); + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))); + } + break; + case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + } + break; + case 5: // Fade On + { + ftn_queue[i].inuse = 0; + ftn_queue[i].start_value = 0; + ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.; + } + break; + case 6: // NEXT FEATURE to pin + break; + default: + break; + } + } +} +void loop() //********************************************************************** +{ + //MUST call the NmraDcc.process() method frequently + // from the Arduino loop() function for correct library operation + Dcc.process(); + delay(2); + stepper.run(); + //*************************Normal Function Processing follows + for (int i=0; i < num_active_fpins; i++) { + if (ftn_queue[i].inuse==1) { + switch (Dcc.getCV( 30+(i*5))) { + case 0: + break; + case 1: + ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment; + if (ftn_queue[i].current_position > ftn_queue[i].stop_value) { + ftn_queue[i].start_value = ~ftn_queue[i].start_value; + digitalWrite(fpins[i], ftn_queue[i].start_value); + ftn_queue[i].current_position = 0; + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))); + } + break; + case 2: + break; + case 3: + ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment; + if (ftn_queue[i].current_position > ftn_queue[i].stop_value) { + ftn_queue[i].start_value = ~ftn_queue[i].start_value; + digitalWrite(fpins[i], ftn_queue[i].start_value); + digitalWrite(fpins[i]+1, ~ftn_queue[i].start_value); + ftn_queue[i].current_position = 0; + ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))); + } + i++; + break; + case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds + { + ftn_queue[i].inuse = 0; + ftn_queue[i].current_position = 0; + ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5)))); + digitalWrite(fpins[i], 0); + } + break; + case 5: // Fade On + + break; + case 6: // NEXT FEATURE to pin + break; + default: + break; + } + } + } +} +void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) { + //if (Function13_value==1) { + Motor1Speed = Speed * Dcc.getCV( Motor_Multiplier); + //Motor1ForwardDir = ForwardDir & 1; + if (ForwardDir == DCC_DIR_REV) Motor1Speed = -Motor1Speed;; + //} +} +void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) { + if (FuncGrp==FN_0_4 && ((FuncState & FN_BIT_02)>>1) == 1) { + if (Function2_value == 0) { + Function2_value=1; + stepper.move(Motor1Speed); + return; + } + } else if (FuncGrp==FN_0_4 && ((FuncState & FN_BIT_02)>>1) == 0) { + Function2_value = 0; + return; + } + switch(FuncGrp) + { + case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1 + exec_function( 0, FunctionPin0, (FuncState & FN_BIT_00)>>4 ); + exec_function( 1, FunctionPin1, (FuncState & FN_BIT_01)); + //exec_function( 2, FunctionPin2, (FuncState & FN_BIT_02)>>1); + exec_function( 3, FunctionPin3, (FuncState & FN_BIT_03)>>2 ); + exec_function( 4, FunctionPin4, (FuncState & FN_BIT_04)>>3 ); + break; + + case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8 + exec_function( 5, FunctionPin5, (FuncState & FN_BIT_05)); + exec_function( 6, FunctionPin6, (FuncState & FN_BIT_06)>>1 ); + exec_function( 7, FunctionPin7, (FuncState & FN_BIT_07)>>2 ); + exec_function( 8, FunctionPin8, (FuncState & FN_BIT_08)>>3 ); + break; + + case FN_9_12: + exec_function( 9, FunctionPin9, (FuncState & FN_BIT_09)); + exec_function( 10, FunctionPin10, (FuncState & FN_BIT_10)>>1 ); + exec_function( 11, FunctionPin11, (FuncState & FN_BIT_11)>>2 ); + exec_function( 12, FunctionPin12, (FuncState & FN_BIT_12)>>3 ); + break; + + case FN_13_20: //Function Group 2 FuncState == F20-F13 Function Control +// Function13_value = (FuncState & FN_BIT_13); +// Function14_value = (FuncState & FN_BIT_14)>>1; +// exec_function( 15, FunctionPin15, (FuncState & FN_BIT_15)>>2 ); +// exec_function( 16, FunctionPin16, (FuncState & FN_BIT_16)>>3 ); + break; + + case FN_21_28: + break; + } +} +void exec_function (int function, int pin, int FuncState) { +#ifdef DEBUG + Serial.print(" function: "); + Serial.println(function, DEC) ; + Serial.print(" pin: "); + Serial.println(pin, DEC) ; + Serial.print(" FuncState: "); + Serial.println(FuncState, DEC) ; + Serial.print(" Dcc.getCV( 30+(function*5)): "); + Serial.println(Dcc.getCV( 30+(function*5)), DEC) ; +#endif + if (function!=2) + switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade + case 0: // On - Off LED + digitalWrite (pin, FuncState); +#ifdef DEBUG + Serial.print(" Dcc.getCV( 30+(function*5)): "); + Serial.println(Dcc.getCV( 30+(function*5)), DEC) ; + Serial.print(" pin: "); + Serial.println(pin, DEC) ; + Serial.print(" FuncState: "); + Serial.println(FuncState, DEC) ; +#endif + ftn_queue[function].inuse = 0; + break; + case 1: // Blinking LED + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + ftn_queue[function].start_value = 0; + digitalWrite(pin, 0); + ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5))); + } else { + if ((ftn_queue[function].inuse==1) && (FuncState==0)) { + ftn_queue[function].inuse = 0; + digitalWrite(pin, 0); + } + } + break; + case 2: // Servo + break; + case 3: // Blinking LED PAIR + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + ftn_queue[function].start_value = 0; + digitalWrite(fpins[function], 0); + digitalWrite(fpins[function+1], 1); + ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5))); + } else { + if (FuncState==0) { + ftn_queue[function].inuse = 0; + digitalWrite(fpins[function], 0); + digitalWrite(fpins[function+1], 0); + } + } + break; + case 4: // Pulse Output based on Rate*10 Milliseconds + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { //First Turn On Detected + digitalWrite(fpins[function], 1); + delay (10*ftn_queue[function].increment); + digitalWrite(fpins[function], 0); + ftn_queue[function].inuse = 1; //inuse set to 1 says we already pulsed + } else + if (FuncState==0) ftn_queue[function].inuse = 0; + break; + case 5: // Fade On +#define fadedelay 24 + if ((ftn_queue[function].inuse==0) && (FuncState==1)) { + ftn_queue[function].inuse = 1; + for (t=0; t sentence=Enables NMRA DCC Communication -paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library currently supports the AVR ATTiny84/85 & ATMega88/168/328/32u4 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms. WARNING as of version 1.4.4 support for the call-back functions notifyDccAccState() and notifyDccSigState() has been removed, please check and update your sketches, as they will silently fail. +paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library has been tested on AVR ATTiny84/85 & ATMega88/168/328/32u4, ESP8266 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms. category=Communication url=https://github.com/mrrwa/NmraDcc -architectures=avr,esp8266,STM32F1 +architectures=*