Added Geoff's 5.1 changes

This commit is contained in:
Alex Shepherd
2016-06-11 15:31:34 +12:00
parent 515e56d918
commit 2c55e735b7
26 changed files with 3084 additions and 6190 deletions

View File

Before

Width:  |  Height:  |  Size: 780 KiB

After

Width:  |  Height:  |  Size: 780 KiB

View File

@@ -1,33 +1,26 @@
// Production 17 Function DCC Acessory Decoder Dual Address w/CV Access
// Version 4.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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
// ******** REMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
// ******** INFO TO THE SERIAL MONITOR
//#define DEBUG
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -84,105 +77,113 @@ CVPair FactoryDefaultCVs [] =
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{60, 2}, //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, 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=Double LED Blink
{65, 2}, //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=Double LED Blink
{70, 2}, //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=Double LED Blink
{75, 2}, //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=Double LED Blink
{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=Double LED Blink
{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
{89, 1}, // Current Position
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{94, 1}, // Current Position
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{99, 2}, // Current Position
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{104, 1}, // Current Position
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 1}, // Current Position
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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);
};
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);
@@ -218,8 +219,10 @@ void setup() //******************************************************
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
#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;
@@ -235,105 +238,29 @@ void setup() //******************************************************
}
break;
case 2: //servo
{ ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5)));
{
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -341,7 +268,24 @@ void setup() //******************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
break;
case 4: // NEXT FEATURE to pin
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;
@@ -353,17 +297,17 @@ void loop() //****************************************************************
{
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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);
@@ -373,18 +317,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -394,10 +350,21 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -409,49 +376,23 @@ extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t Output
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
break;
}
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
#ifdef DEBUG
Serial.print("Addr = ");
Serial.println(Addr);
Serial.print("BoardAddr = ");
Serial.println(BoardAddr);
Serial.print("Bit_State = ");
Serial.println(Bit_State);
#endif
exec_function(Addr-Current_Decoder_Addr, Bit_State );
}
}
void exec_function (int function, int pin, int FuncState) {
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
void exec_function (int function, int FuncState) {
byte pin;
int servo_temp;
pin = fpins[function];
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;
@@ -470,7 +411,10 @@ void exec_function (int function, int pin, int FuncState) {
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
@@ -491,51 +435,38 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,33 +1,26 @@
// Production 17 Function DCC Acessory Decoder Dual Address w/CV Access
// Version 4.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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
// ******** REMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
// ******** INFO TO THE SERIAL MONITOR
//#define DEBUG
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -84,67 +77,67 @@ CVPair FactoryDefaultCVs [] =
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{60, 2}, //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, 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=Double LED Blink
{65, 2}, //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=Double LED Blink
{70, 2}, //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=Double LED Blink
{75, 2}, //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, 2}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{80, 2}, //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, 2}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{85, 2}, //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, 2}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{90, 2}, //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
@@ -177,12 +170,20 @@ CVPair FactoryDefaultCVs [] =
{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);
};
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);
@@ -218,8 +219,10 @@ void setup() //******************************************************
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
#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;
@@ -234,106 +237,30 @@ void setup() //******************************************************
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)));
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -341,7 +268,24 @@ void setup() //******************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
break;
case 4: // NEXT FEATURE to pin
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;
@@ -353,17 +297,17 @@ void loop() //****************************************************************
{
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -373,18 +317,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -394,10 +350,21 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -409,49 +376,23 @@ extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t Output
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
break;
}
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
#ifdef DEBUG
Serial.print("Addr = ");
Serial.println(Addr);
Serial.print("BoardAddr = ");
Serial.println(BoardAddr);
Serial.print("Bit_State = ");
Serial.println(Bit_State);
#endif
exec_function(Addr-Current_Decoder_Addr, Bit_State );
}
}
void exec_function (int function, int pin, int FuncState) {
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
void exec_function (int function, int FuncState) {
byte pin;
int servo_temp;
pin = fpins[function];
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;
@@ -470,7 +411,10 @@ void exec_function (int function, int pin, int FuncState) {
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
@@ -491,51 +435,38 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,33 +1,26 @@
// Production 17 Function DCC Acessory Decoder Dual Address w/CV Access
// Version 4.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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
// ******** REMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
// ******** INFO TO THE SERIAL MONITOR
//#define DEBUG
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -84,105 +77,113 @@ CVPair FactoryDefaultCVs [] =
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{60, 2}, //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, 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=Double LED Blink
{65, 2}, //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=Double LED Blink
{70, 2}, //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=Double LED Blink
{75, 2}, //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, 2}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{80, 2}, //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, 2}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{85, 2}, //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, 2}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{90, 2}, //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, 2}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{95, 2}, //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, 28}, // Start Position Fx=0
{98, 140}, // End Position Fx=1
{99, 28}, // Current Position
{100, 2}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{100, 2}, //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, 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=Double LED Blink
{105, 1}, //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=Double LED Blink
{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=Double LED Blink
{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);
};
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);
@@ -218,8 +219,10 @@ void setup() //******************************************************
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
#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;
@@ -235,105 +238,29 @@ void setup() //******************************************************
}
break;
case 2: //servo
{ ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5)));
{
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -341,7 +268,18 @@ void setup() //******************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
break;
case 4: // NEXT FEATURE to pin
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;
@@ -353,17 +291,17 @@ void loop() //****************************************************************
{
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -373,18 +311,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -394,10 +344,27 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -409,49 +376,23 @@ extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t Output
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
break;
}
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
#ifdef DEBUG
Serial.print("Addr = ");
Serial.println(Addr);
Serial.print("BoardAddr = ");
Serial.println(BoardAddr);
Serial.print("Bit_State = ");
Serial.println(Bit_State);
#endif
exec_function(Addr-Current_Decoder_Addr, Bit_State );
}
}
void exec_function (int function, int pin, int FuncState) {
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
void exec_function (int function, int FuncState) {
byte pin;
int servo_temp;
pin = fpins[function];
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;
@@ -470,7 +411,10 @@ void exec_function (int function, int pin, int FuncState) {
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
@@ -491,51 +435,38 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,7 +1,6 @@
// Working 17 Function ACESSORY DCC Decoder No CV Programming DccAckPin not needed
// Version 3.0 Geoff Bunza 2014
// This uses Accessory addresses defined from This_Decoder_Address + 16
//
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// ******** 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
@@ -10,7 +9,8 @@
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 ledpins [] = {0,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;
const int FunctionPin2 = 5;
@@ -55,10 +55,8 @@ void notifyCVResetFactoryDefault()
// to flag to the loop() function that a reset to Factory Defaults needs to be done
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
};
void setup()
{
//Serial.begin(115200);
// initialize the digital pins as an outputs
for (int i=0; i< numleds; i++) {
pinMode(ledpins[i], OUTPUT);
@@ -97,7 +95,7 @@ void loop()
}
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
uint8_t Bit_State = OutputAddr & 0x01;
if ( Addr >= This_Decoder_Address || Addr < This_Decoder_Address+17) //Controls This_Decoder_Address+16
if ( Addr >= This_Decoder_Address && Addr < This_Decoder_Address+17) //Controls This_Decoder_Address+16
digitalWrite( ledpins[Addr-This_Decoder_Address], Bit_State );
}

View File

@@ -1,33 +1,26 @@
// Production 17 Function DCC Acessory Decoder Dual Address w/CV Access
// Version 4.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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
// ******** REMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
// ******** INFO TO THE SERIAL MONITOR
//#define DEBUG
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -84,105 +77,113 @@ CVPair FactoryDefaultCVs [] =
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{33, 140}, //F0 End Position F0=1
{34, 28}, //F0 Current Position
{35, 0}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 0}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 0}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 0}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 0}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 0}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 0}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 0}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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, 28}, // Start Position Fx=0
{63, 140}, // End Position Fx=1
{64, 28}, // Current Position
{65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 1}, // Start Position Fx=0
{68,35}, // End Position Fx=1
{69, 1}, // Current Position
{70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 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=Double LED Blink
{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, 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=Double LED Blink
{80, 5}, //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=Double LED Blink
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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
{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=Double LED Blink
{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, 20}, // End Position Fx=1
{94, 1}, // Current Position
{95, 0}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 35}, // End Position Fx=1
{99, 2}, // Current Position
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{104, 1}, // Current Position
{105, 0}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 60}, // End Position Fx=1
{109, 20}, // Current Position
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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);
};
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);
@@ -218,8 +219,10 @@ void setup() //******************************************************
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
#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;
@@ -235,105 +238,29 @@ void setup() //******************************************************
}
break;
case 2: //servo
{ ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5)));
{
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -341,7 +268,24 @@ void setup() //******************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
break;
case 4: // NEXT FEATURE to pin
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;
@@ -353,17 +297,17 @@ void loop() //****************************************************************
{
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -373,18 +317,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -394,10 +350,21 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -409,49 +376,23 @@ extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t Output
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
break;
}
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
#ifdef DEBUG
Serial.print("Addr = ");
Serial.println(Addr);
Serial.print("BoardAddr = ");
Serial.println(BoardAddr);
Serial.print("Bit_State = ");
Serial.println(Bit_State);
#endif
exec_function(Addr-Current_Decoder_Addr, Bit_State );
}
}
void exec_function (int function, int pin, int FuncState) {
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
void exec_function (int function, int FuncState) {
byte pin;
int servo_temp;
pin = fpins[function];
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;
@@ -470,7 +411,10 @@ void exec_function (int function, int pin, int FuncState) {
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
@@ -491,51 +435,38 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -0,0 +1,468 @@
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// 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
// ******** REMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
// ******** INFO TO THE SERIAL MONITOR
//#define DEBUG
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
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
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 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;
};
CVPair FactoryDefaultCVs [] =
{
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 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
{32, 28}, //F0 Start Position
{33, 140}, //F0 End Position
{34, 28}, //F0 Current Position
{35, 2}, //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, 28}, // Start Position
{38, 140}, // End Position
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position
{43, 140}, // End Position
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 2}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position
{48, 140}, // End Position
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 2}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position
{53, 140}, // End Position
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{56, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{57, 28}, // Start Position
{58, 140}, // End Position
{59, 28}, // Current Position
{60, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{61, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{62, 28}, // Start Position
{63, 140}, // End Position
{64, 28}, // Current Position
{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
{68, 140}, // End Position
{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, 1}, // Start Position
{73, 100}, // End Position
{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, 1}, // Start Position
{78, 10}, // End Position
{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
{83, 5}, // End Position
{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, 1}, // Start Position
{88, 5}, // End Position
{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
{93, 20}, // End Position
{94, 1}, // Current Position
{95, 1}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=PWM
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{97, 1}, // Start Position
{98, 20}, // End Position
{99, 1}, // Current Position
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=PWM
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{102, 1}, // Start Position
{103, 4}, // End Position
{104, 1}, // Current Position
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=PWM
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{107, 1}, // Start Position
{108, 60}, // End Position
{109, 20}, // Current Position
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=PWM
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{112, 1}, // Start Position
{113, 4}, // End Position
{114, 1}, // Current Position
//FUTURE USE
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=PWM
{116, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{117, 28}, // Start Position
{118, 50}, // End Position
{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);
};
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);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800);
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
{
for (int j=0; j < sizeof(FactoryDefaultCVs)/sizeof(CVPair); j++ )
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
for ( i=0; i < numfpins; 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; 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: // All Servo service timing is now local to the Turn on transition
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;
}
}
}
}
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
uint16_t Current_Decoder_Addr;
uint8_t Bit_State;
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
#ifdef DEBUG
Serial.print("Addr = ");
Serial.println(Addr);
Serial.print("BoardAddr = ");
Serial.println(BoardAddr);
Serial.print("Bit_State = ");
Serial.println(Bit_State);
#endif
exec_function(Addr-Current_Decoder_Addr, Bit_State );
}
}
void exec_function (int function, int FuncState) {
byte pin;
int servo_temp;
pin = fpins[function];
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) && (FuncState==1)) { // We have an OFF->ON transition
servo[function].attach(pin);
ftn_queue[function].increment = char ( Dcc.getCV( 31+(function*5)));
ftn_queue[function].start_value = Dcc.getCV( 32+(function*5));
ftn_queue[function].stop_value = Dcc.getCV( 33+(function*5));
for (servo_temp=ftn_queue[function].start_value; servo_temp<ftn_queue[function].stop_value; servo_temp=servo_temp+ftn_queue[function].increment) {
servo[function].write(servo_temp);
SoftwareServo::refresh();
delay(4);
}
for (servo_temp=ftn_queue[function].stop_value; servo_temp>ftn_queue[function].start_value; servo_temp=servo_temp-ftn_queue[function].increment) {
servo[function].write(servo_temp);
SoftwareServo::refresh();
delay(4);
}
ftn_queue[function].inuse = 1;
}
if (FuncState==0) {
ftn_queue[function].inuse = 0;
servo[function].detach();
}
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}

View File

@@ -1,33 +1,26 @@
// Production 17 Function DCC Acessory Decoder Dual Address w/CV Access
// Version 4.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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
// ******** REMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
// ******** INFO TO THE SERIAL MONITOR
//#define DEBUG
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -84,67 +77,67 @@ CVPair FactoryDefaultCVs [] =
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{60, 2}, //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, 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=Double LED Blink
{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, 2}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 28}, // Start Position Fx=0
{88, 140}, // End Position Fx=1
{89, 28}, // Current Position
{90, 2}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 28}, // Start Position Fx=0
{93, 140}, // End Position Fx=1
@@ -177,12 +170,20 @@ CVPair FactoryDefaultCVs [] =
{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);
};
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);
@@ -218,8 +219,10 @@ void setup() //******************************************************
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
#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;
@@ -235,105 +238,29 @@ void setup() //******************************************************
}
break;
case 2: //servo
{ ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5)));
{
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -341,7 +268,24 @@ void setup() //******************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
break;
case 4: // NEXT FEATURE to pin
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;
@@ -353,17 +297,17 @@ void loop() //****************************************************************
{
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -373,18 +317,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -394,10 +350,21 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -409,49 +376,23 @@ extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t Output
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
break;
}
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
#ifdef DEBUG
Serial.print("Addr = ");
Serial.println(Addr);
Serial.print("BoardAddr = ");
Serial.println(BoardAddr);
Serial.print("Bit_State = ");
Serial.println(Bit_State);
#endif
exec_function(Addr-Current_Decoder_Addr, Bit_State );
}
}
void exec_function (int function, int pin, int FuncState) {
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
void exec_function (int function, int FuncState) {
byte pin;
int servo_temp;
pin = fpins[function];
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;
@@ -470,7 +411,10 @@ void exec_function (int function, int pin, int FuncState) {
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
@@ -491,51 +435,38 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,641 +0,0 @@
// Production 17 Function DCC Acessory Decoder Dual Address w/CV Access
// Version 4.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
#define servo_start_delay 50
#define servo_init_delay 7
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
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
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 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;
};
CVPair FactoryDefaultCVs [] =
{
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{36, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{37, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{61, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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, 2}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{97, 28}, // Start Position Fx=0
{98, 140}, // End Position Fx=1
{99, 28}, // Current Position
{100, 2}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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 setup() //******************************************************
{
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);
digitalWrite(fpins[i], 0);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800);
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
{
for (int j=0; j < sizeof(FactoryDefaultCVs)/sizeof(CVPair); j++ )
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
}
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: // NEXT FEATURE to pin
break;
default:
break;
}
}
}
void loop() //**********************************************************************
{
boolean servo_on = true;
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
servo_on = true;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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:
{
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;
servo_on = false;
detach_servo (i);
}
}
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;
servo_on = false;
detach_servo (i);
}
}
if (servo_on) {
set_servo(i, ftn_queue[i].current_position);
}
}
break;
case 3:
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: //FUTURE FUNCTION
break;
default:
break;
}
}
}
}
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
uint16_t Current_Decoder_Addr;
uint8_t Bit_State;
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
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=Double LED Blink
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
ftn_queue[function].inuse = 1;
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: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0:
if (servo0.attached()==0) servo0.attach(FunctionPin0);
servo0.write(servo_pos);
break;
case 1:
if (servo1.attached()==0) servo1.attach(FunctionPin1);
servo1.write(servo_pos);
break;
case 2:
if (servo2.attached()==0) servo2.attach(FunctionPin2);
servo2.write(servo_pos);
break;
case 3:
if (servo3.attached()==0) servo3.attach(FunctionPin3);
servo3.write(servo_pos);
break;
case 4:
if (servo4.attached()==0) servo4.attach(FunctionPin4);
servo4.write(servo_pos);
break;
case 5:
if (servo5.attached()==0) servo5.attach(FunctionPin5);
servo5.write(servo_pos);
break;
case 6:
if (servo6.attached()==0) servo6.attach(FunctionPin6);
servo6.write(servo_pos);
break;
case 7:
if (servo7.attached()==0) servo7.attach(FunctionPin7);
servo7.write(servo_pos);
break;
case 8:
if (servo8.attached()==0) servo8.attach(FunctionPin8);
servo8.write(servo_pos);
break;
case 9:
if (servo9.attached()==0) servo9.attach(FunctionPin9);
servo9.write(servo_pos);
break;
case 10:
if (servo10.attached()==0) servo10.attach(FunctionPin10);
servo10.write(servo_pos);
break;
case 11:
if (servo11.attached()==0) servo11.attach(FunctionPin11);
servo11.write(servo_pos);
break;
case 12:
if (servo12.attached()==0) servo12.attach(FunctionPin12);
servo12.write(servo_pos);
case 13:
if (servo13.attached()==0) servo13.attach(FunctionPin13);
servo13.write(servo_pos);
break;
case 14:
if (servo14.attached()==0) servo12.attach(FunctionPin14);
servo14.write(servo_pos);
break;
case 15:
if (servo15.attached()==0) servo15.attach(FunctionPin15);
servo15.write(servo_pos);
break;
case 16:
if (servo16.attached()==0) servo16.attach(FunctionPin16);
servo16.write(servo_pos);
break;
default:
break;
}
}
void detach_servo (int servo_num) {
switch (servo_num) {
case 0:
if (servo0.attached()!=0) servo0.detach();
break;
case 1:
if (servo1.attached()!=0) servo1.detach();
break;
case 2:
if (servo2.attached()!=0) servo2.detach();
break;
case 3:
if (servo3.attached()!=0) servo3.detach();
break;
case 4:
if (servo4.attached()!=0) servo4.detach();
break;
case 5:
if (servo5.attached()!=0) servo5.detach();
break;
case 6:
if (servo6.attached()!=0) servo6.detach();
break;
case 7:
if (servo7.attached()!=0) servo7.detach();
break;
case 8:
if (servo8.attached()!=0) servo8.detach();
break;
case 9:
if (servo9.attached()!=0) servo9.detach();
break;
case 10:
if (servo10.attached()!=0) servo10.detach();
break;
case 11:
if (servo11.attached()!=0) servo11.detach();
break;
case 12:
if (servo12.attached()!=0) servo12.detach();
break;
case 13:
if (servo13.attached()!=0) servo13.detach();
break;
case 14:
if (servo14.attached()!=0) servo12.detach();
break;
case 15:
if (servo15.attached()!=0) servo15.detach();
break;
case 16:
if (servo16.attached()!=0) servo16.detach();
break;
default:
break;
}
}

View File

@@ -1,564 +0,0 @@
// Production 17 Function DCC Acessory Decoder Dual Address w/CV Access
// Version 4.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// This configuration supports 5 Modes per pin:
// 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
// It is recommended that you NOT MIX pulsed and servo control
// simultaneously as the servo timing will be off
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
#define servo_start_delay 50
#define servo_init_delay 7
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
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
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 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;
};
CVPair FactoryDefaultCVs [] =
{
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 4}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{31, 10}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{32, 28}, //F0 Start Position F0=0
{33, 140}, //F0 End Position F0=1
{34, 0}, //F0 Current Position
{35, 4}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{36, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{37, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 0}, // Current Position
{40, 4}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{41, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 0}, // Current Position
{45, 4}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{46, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 0}, // Current Position
{50, 4}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{51, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 0}, // Current Position
{55, 4}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{56, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{57, 28}, // Start Position Fx=0
{58, 140}, // End Position Fx=1
{59, 0}, // Current Position
{60, 4}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{61, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{62, 28}, // Start Position Fx=0
{63, 140}, // End Position Fx=1
{64, 0}, // Current Position
{65, 4}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{66, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{67, 1}, // Start Position Fx=0
{68,35}, // End Position Fx=1
{69, 0}, // Current Position
{70, 4}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{71, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{72, 1}, // Start Position Fx=0
{73, 100}, // End Position Fx=1
{74, 0}, // Current Position
{75, 4}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{76, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{77, 1}, // Start Position Fx=0
{78, 10}, // End Position Fx=1
{79, 0}, // Current Position
{80, 4}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{81, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{82, 1}, // Start Position Fx=0
{83, 5}, // End Position Fx=1
{84, 0}, // Current Position
{85, 4}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{86, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{87, 1}, // Start Position Fx=0
{88, 5}, // End Position Fx=1
{89, 0}, // Current Position
{90, 4}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{91, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{92, 1}, // Start Position Fx=0
{93, 20}, // End Position Fx=1
{94, 0}, // Current Position
{95, 4}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{96, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{97, 1}, // Start Position Fx=0
{98, 35}, // End Position Fx=1
{99, 0}, // Current Position
{100, 4}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{101, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{102, 1}, // Start Position Fx=0
{103, 4}, // End Position Fx=1
{104, 0}, // Current Position
{105, 4}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{106, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{107, 1}, // Start Position Fx=0
{108, 60}, // End Position Fx=1
{109, 0}, // Current Position
{110, 4}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{111, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{112, 1}, // Start Position Fx=0
{113, 4}, // End Position Fx=1
{114, 0}, // Current Position
//FUTURE USE
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{116, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{117, 28}, // Start Position Fx=0
{118, 50}, // End Position Fx=1
{119, 28}, // Current Position
};
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
void setup() //******************************************************
{
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);
digitalWrite(fpins[i], 0);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800);
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
{
for (int j=0; j < sizeof(FactoryDefaultCVs)/sizeof(CVPair); j++ )
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
}
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: //FUTURE FUNCTION
break;
default:
break;
}
}
}
void loop() //**********************************************************************
{
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
break;
case 3:
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
break;
case 5: //FUTURE FUNCTION
break;
default:
break;
}
}
}
}
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
uint16_t Current_Decoder_Addr;
uint8_t Bit_State;
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
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=Double LED Blink
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
ftn_queue[function].inuse = 1;
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: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,548 +0,0 @@
// Production 7 Servo Back and Forth DCC Acessory Decoder Dual Address w/CV Access
// Version 1.2 Geoff Bunza 2014
// Uses modified software servo Lib
// 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
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
#define servo_start_delay 50
#define servo_init_delay 7
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
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
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
int servo_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;
};
CVPair FactoryDefaultCVs [] =
{
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{CV_To_Store_SET_CV_Address, SET_CV_Address},
{CV_To_Store_SET_CV_Address+1, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{31, 3}, //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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{36, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{37, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{41, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{46, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{51, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{56, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{57, 28}, // Start Position Fx=0
{58, 140}, // End Position Fx=1
{59, 28}, // Current Position
{60, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{61, 3}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{62, 28}, // Start Position Fx=0
{63, 140}, // End Position Fx=1
{64, 28}, // Current Position
{65, 1}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{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=Double LED Blink
{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, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{92, 1}, // Start Position Fx=0
{93, 20}, // End Position Fx=1
{94, 1}, // Current Position
{95, 1}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=PWM
{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
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{102, 1}, // Start Position Fx=0
{103, 4}, // End Position Fx=1
{104, 1}, // Current Position
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=PWM
{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
{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
{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 setup() //******************************************************
{
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);
digitalWrite(fpins[i], 0);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
delay(800);
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
{
for (int j=0; j < sizeof(FactoryDefaultCVs)/sizeof(CVPair); j++ )
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 0;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
}
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: // 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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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: // All Servo service timing is now local to the Turn on transition
break;
case 3:
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: //FUTURE FUNCTION
break;
default:
break;
}
}
}
}
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
uint16_t Current_Decoder_Addr;
uint8_t Bit_State;
Current_Decoder_Addr = Dcc.getAddr();
Bit_State = OutputAddr & 0x01;
if ( Addr >= Current_Decoder_Addr || Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
switch (Addr-Current_Decoder_Addr) {
case 0: exec_function( 0, FunctionPin0, Bit_State );
break;
case 1: exec_function( 1, FunctionPin1, Bit_State );
break;
case 2: exec_function( 2, FunctionPin2, Bit_State );
break;
case 3: exec_function( 3, FunctionPin3, Bit_State );
break;
case 4: exec_function( 4, FunctionPin4, Bit_State );
break;
case 5: exec_function( 5, FunctionPin5, Bit_State );
break;
case 6: exec_function( 6, FunctionPin6, Bit_State );
break;
case 7: exec_function( 7, FunctionPin7, Bit_State );
break;
case 8: exec_function( 8, FunctionPin8, Bit_State );
break;
case 9: exec_function( 9, FunctionPin9, Bit_State );
break;
case 10: exec_function( 10, FunctionPin10, Bit_State );
break;
case 11: exec_function( 11, FunctionPin11, Bit_State );
break;
case 12: exec_function( 12, FunctionPin12, Bit_State );
break;
case 13: exec_function( 13, FunctionPin13, Bit_State );
break;
case 14: exec_function( 14, FunctionPin14, Bit_State );
break;
case 15: exec_function( 15, FunctionPin15, Bit_State );
break;
case 16: exec_function( 16, FunctionPin16, Bit_State );
break;
default:
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=Double LED Blink
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) && (FuncState==1)) { // We have an OFF->ON transition
ftn_queue[function].increment = char ( Dcc.getCV( 31+(function*5)));
ftn_queue[function].start_value = Dcc.getCV( 32+(function*5));
ftn_queue[function].stop_value = Dcc.getCV( 33+(function*5));
for (servo_temp=ftn_queue[function].start_value; servo_temp<ftn_queue[function].stop_value; servo_temp=servo_temp+ftn_queue[function].increment) {
set_servo(function,servo_temp);
SoftwareServo::refresh();
delay(4);
}
for (servo_temp=ftn_queue[function].stop_value; servo_temp>ftn_queue[function].start_value; servo_temp=servo_temp-ftn_queue[function].increment) {
set_servo(function,servo_temp);
SoftwareServo::refresh();
delay(4);
}
ftn_queue[function].inuse = 1;
}
if (FuncState==0) ftn_queue[function].inuse = 0;
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: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,34 +1,26 @@
// Production 17 Function DCC Decoder
// Version 3.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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 <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -80,93 +72,93 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{60, 2}, //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, 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=Double LED Blink
{65, 2}, //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=Double LED Blink
{70, 2}, //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=Double LED Blink
{75, 2}, //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=Double LED Blink
{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=Double LED Blink
{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
{89, 1}, // Current Position
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{94, 1}, // Current Position
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{99, 2}, // Current Position
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{104, 1}, // Current Position
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 1}, // Current Position
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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
@@ -183,9 +175,11 @@ void notifyCVResetFactoryDefault()
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);
@@ -208,9 +202,9 @@ void setup() //******************************************************
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800);
#if defined(DECODER_LOADED)
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
#endif
{
for (int j=0; j < FactoryDefaultCVIndex; j++ )
@@ -218,11 +212,13 @@ void setup() //******************************************************
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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;
@@ -230,143 +226,84 @@ void setup() //******************************************************
case 1: // LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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)));
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].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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 0;
ftn_queue[i].current_position = 0;
ftn_queue[i].start_value = 0;
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
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: // NEXT FEATURE to pin
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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -376,18 +313,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -397,10 +346,21 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -443,7 +403,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=Double LED Blink
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;
@@ -452,31 +412,24 @@ void exec_function (int function, int pin, int FuncState) {
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
ftn_queue[function].inuse = 1;
ftn_queue[function].start_value = 0;
digitalWrite(fpins[function], 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(fpins[function], 0);
digitalWrite(pin, 0);
}
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
/*
Serial.print("servo inc: ") ;
Serial.print(ftn_queue[function].increment,DEC) ;
Serial.print("servo inuse: ") ;
Serial.print(ftn_queue[function].inuse,DEC) ;
Serial.print("servo num: ") ;
Serial.print(function,DEC) ;
Serial.print(" stop: ");
Serial.println(ftn_queue[function].stop_value,DEC) ;
*/
break;
case 3: // Blinking LED PAIR
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
@@ -493,7 +446,34 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
@@ -501,43 +481,3 @@ void exec_function (int function, int pin, int FuncState) {
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,34 +1,26 @@
// Production 17 Function DCC Decoder
// Version 3.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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 <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -80,93 +72,93 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{60, 2}, //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, 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=Double LED Blink
{65, 2}, //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=Double LED Blink
{70, 2}, //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=Double LED Blink
{75, 2}, //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, 2}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{80, 2}, //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, 2}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{85, 2}, //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, 2}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{90, 2}, //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
{95, 1}, //F13 CConfig 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
{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
{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
{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
@@ -183,9 +175,11 @@ void notifyCVResetFactoryDefault()
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);
@@ -208,9 +202,9 @@ void setup() //******************************************************
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800);
#if defined(DECODER_LOADED)
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
#endif
{
for (int j=0; j < FactoryDefaultCVIndex; j++ )
@@ -218,11 +212,13 @@ void setup() //******************************************************
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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;
@@ -230,143 +226,84 @@ void setup() //******************************************************
case 1: // LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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)));
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].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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 0;
ftn_queue[i].current_position = 0;
ftn_queue[i].start_value = 0;
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
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: // NEXT FEATURE to pin
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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -376,18 +313,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -397,10 +346,21 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -443,9 +403,8 @@ 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=Double LED Blink
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
//Serial.println("****************cv:0 ") ;
digitalWrite (pin, FuncState);
ftn_queue[function].inuse = 0;
break;
@@ -453,31 +412,24 @@ void exec_function (int function, int pin, int FuncState) {
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
ftn_queue[function].inuse = 1;
ftn_queue[function].start_value = 0;
digitalWrite(fpins[function], 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(fpins[function], 0);
digitalWrite(pin, 0);
}
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
/*
Serial.print("servo inc: ") ;
Serial.print(ftn_queue[function].increment,DEC) ;
Serial.print("servo inuse: ") ;
Serial.print(ftn_queue[function].inuse,DEC) ;
Serial.print("servo num: ") ;
Serial.print(function,DEC) ;
Serial.print(" stop: ");
Serial.println(ftn_queue[function].stop_value,DEC) ;
*/
break;
case 3: // Blinking LED PAIR
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
@@ -494,7 +446,34 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
@@ -502,43 +481,3 @@ void exec_function (int function, int pin, int FuncState) {
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,34 +1,26 @@
// Production 17 Function DCC Decoder
// Version 3.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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 <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -80,93 +72,93 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{60, 2}, //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, 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=Double LED Blink
{65, 2}, //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=Double LED Blink
{70, 2}, //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=Double LED Blink
{75, 2}, //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, 2}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{80, 2}, //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, 2}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{85, 2}, //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, 2}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{90, 2}, //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, 2}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{95, 2}, //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, 28}, // Start Position Fx=0
{98, 140}, // End Position Fx=1
{99, 28}, // Current Position
{100, 2}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{100, 2}, //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, 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=Double LED Blink
{105, 1}, //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=Double LED Blink
{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=Double LED Blink
{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
@@ -183,9 +175,11 @@ void notifyCVResetFactoryDefault()
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);
@@ -208,9 +202,9 @@ void setup() //******************************************************
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800);
#if defined(DECODER_LOADED)
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
#endif
{
for (int j=0; j < FactoryDefaultCVIndex; j++ )
@@ -218,11 +212,13 @@ void setup() //******************************************************
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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;
@@ -230,113 +226,37 @@ void setup() //******************************************************
case 1: // LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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)));
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].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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(10);}
break;
default:
break;
}
}
break;
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -344,29 +264,46 @@ void setup() //******************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
break;
case 4: // NEXT FEATURE to pin
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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -376,18 +313,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
break;
case 3:
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);
@@ -396,11 +345,22 @@ void loop() //****************************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
break;
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;
}
}
}
@@ -443,7 +403,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=Double LED Blink
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;
@@ -452,31 +412,24 @@ void exec_function (int function, int pin, int FuncState) {
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
ftn_queue[function].inuse = 1;
ftn_queue[function].start_value = 0;
digitalWrite(fpins[function], 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(fpins[function], 0);
digitalWrite(pin, 0);
}
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
/*
Serial.print("servo inc: ") ;
Serial.print(ftn_queue[function].increment,DEC) ;
Serial.print("servo inuse: ") ;
Serial.print(ftn_queue[function].inuse,DEC) ;
Serial.print("servo num: ") ;
Serial.print(function,DEC) ;
Serial.print(" stop: ");
Serial.println(ftn_queue[function].stop_value,DEC) ;
*/
break;
case 3: // Blinking LED PAIR
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
@@ -493,7 +446,34 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
@@ -501,43 +481,3 @@ void exec_function (int function, int pin, int FuncState) {
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,7 +1,10 @@
// Working 14 Function DCC Decoder DccAckPin not needed
// Version 3.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
int tim_delay = 500;
@@ -31,7 +34,7 @@ const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
#define This_Decoder_Address 17
#define This_Decoder_Address 24
struct CVPair
{
@@ -46,7 +49,7 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
};
uint8_t FactoryDefaultCVIndex = 0;
uint8_t FactoryDefaultCVIndex = 4;
void notifyCVResetFactoryDefault()
{
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
@@ -75,8 +78,18 @@ void setup()
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);
#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(13, 1); //Blink the on board LED
delay (1000);
digitalWrite(13, 0);
}
}
void loop()
{
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
@@ -93,32 +106,32 @@ void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uin
switch(FuncGrp)
{
case FN_0_4:
digitalWrite( FunctionPin0, (FuncState & FN_BIT_00) );
digitalWrite( FunctionPin0, (FuncState & FN_BIT_00)>>4 );
digitalWrite( FunctionPin1, (FuncState & FN_BIT_01) );
digitalWrite( FunctionPin2, (FuncState & FN_BIT_02) );
digitalWrite( FunctionPin3, (FuncState & FN_BIT_03) );
digitalWrite( FunctionPin4, (FuncState & FN_BIT_04) );
digitalWrite( FunctionPin2, (FuncState & FN_BIT_02)>>1 );
digitalWrite( FunctionPin3, (FuncState & FN_BIT_03)>>2 );
digitalWrite( FunctionPin4, (FuncState & FN_BIT_03)>>3 );
break;
case FN_5_8:
digitalWrite( FunctionPin5, (FuncState & FN_BIT_05) );
digitalWrite( FunctionPin6, (FuncState & FN_BIT_06) );
digitalWrite( FunctionPin7, (FuncState & FN_BIT_07) );
digitalWrite( FunctionPin8, (FuncState & FN_BIT_08) );
digitalWrite( FunctionPin6, (FuncState & FN_BIT_06)>>1 );
digitalWrite( FunctionPin7, (FuncState & FN_BIT_07)>>2 );
digitalWrite( FunctionPin8, (FuncState & FN_BIT_08)>>3 );
break;
case FN_9_12:
digitalWrite( FunctionPin9, (FuncState & FN_BIT_09) );
digitalWrite( FunctionPin10, (FuncState & FN_BIT_10) );
digitalWrite( FunctionPin11, (FuncState & FN_BIT_11) );
digitalWrite( FunctionPin12, (FuncState & FN_BIT_12) );
digitalWrite( FunctionPin10, (FuncState & FN_BIT_10)>>1 );
digitalWrite( FunctionPin11, (FuncState & FN_BIT_11)>>2 );
digitalWrite( FunctionPin12, (FuncState & FN_BIT_12)>>3 );
break;
case FN_13_20:
digitalWrite( FunctionPin13, (FuncState & FN_BIT_13) );
digitalWrite( FunctionPin14, (FuncState & FN_BIT_14) );
digitalWrite( FunctionPin15, (FuncState & FN_BIT_15) );
digitalWrite( FunctionPin16, (FuncState & FN_BIT_16) );
digitalWrite( FunctionPin14, (FuncState & FN_BIT_14)>>1 );
digitalWrite( FunctionPin15, (FuncState & FN_BIT_15)>>2 );
digitalWrite( FunctionPin16, (FuncState & FN_BIT_16)>>3 );
break;
case FN_21_28:

View File

@@ -0,0 +1,483 @@
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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 <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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 & LOAD ACK
const int FunctionPin15 = 18; //A4
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
uint8_t CV_DECODER_MASTER_RESET = 120;
int t; // temp
#define This_Decoder_Address 24
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;
};
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_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
{33, 8}, //F0 End Position F0=1
{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
{38, 8}, // End Position Fx=1
{39, 1}, // Current Position
{40, 4}, //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, 4}, //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, 4}, //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, 28}, // Start Position Fx=0
{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
{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, 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
{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, 10}, // 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, 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, 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
{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 = 95;
void notifyCVResetFactoryDefault()
{
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
// to flag to the loop() function that a reset to Factory Defaults needs to be done
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
};
void setup() //******************************************************
{
#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);
digitalWrite(fpins[i], 0);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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 );
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 < numfpins; 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; 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:
{
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: // NEXT FEATURE to pin
break;
default:
break;
}
}
}
}
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
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
exec_function( 13, FunctionPin13, (FuncState & FN_BIT_13));
exec_function( 14, FunctionPin14, (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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}

View File

@@ -0,0 +1,573 @@
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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 <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo[12];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //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 = 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
int Function13_value = 0;
int Function14_value = 0;
NmraDcc Dcc ;
DCC_MSG Packet ;
uint8_t CV_DECODER_MASTER_RESET = 120;
int t; // temp
#define This_Decoder_Address 24
struct QUEUE
{
int inuse;
int current_position;
int increment;
int stop_value;
int start_value;
};
QUEUE *ftn_queue = new QUEUE[16];
extern uint8_t Decoder_Address = This_Decoder_Address;
struct CVPair
{
uint16_t CV;
uint8_t Value;
};
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_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
{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, 28}, // Start Position Fx=0
{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
{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, 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
{89, 1}, // Current Position
{90, 2}, //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, 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
{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 = 95;
void notifyCVResetFactoryDefault()
{
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
// to flag to the loop() function that a reset to Factory Defaults needs to be done
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
};
void setup() //******************************************************
{
#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);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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 );
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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
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();
SoftwareServo::refresh();
delay(2);
if (Motor1Speed != 0) {
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, int((Motor1Speed&0x7f)*21));
else gobwd1 (bwdtime, int((Motor1Speed&0x7f)*21));
}
if (Motor2Speed != 0) {
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, int((Motor2Speed&0x7f)*21));
else gobwd2 (bwdtime, int((Motor2Speed&0x7f)*21));
}
//
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:
{
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: // 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) {
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}

View File

@@ -1,34 +1,26 @@
// Production 17 Function DCC Decoder
// Version 3.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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 <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
SoftwareServo servo[16];
#define servo_start_delay 50
#define servo_init_delay 7
#define servo_slowdown 3 //servo loop counter limit
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
int tim_delay = 500;
int numfpins = 17;
@@ -80,93 +72,93 @@ CVPair FactoryDefaultCVs [] =
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
{CV_DECODER_MASTER_RESET, 0},
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 0}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{35, 2}, //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, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 0}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 0}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 0}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 0}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{55, 2}, //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=Double LED Blink
{60, 2}, //F6 Config 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, 28}, // Start Position Fx=0
{63, 140}, // End Position Fx=1
{64, 28}, // Current Position
{65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 1}, // Start Position Fx=0
{68,35}, // End Position Fx=1
{69, 1}, // Current Position
{70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 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=Double LED Blink
{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, 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=Double LED Blink
{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=Double LED Blink
{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
{89, 1}, // Current Position
{90, 0}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{94, 1}, // Current Position
{95, 0}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{99, 2}, // Current Position
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{104, 1}, // Current Position
{105, 0}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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
@@ -183,9 +175,11 @@ void notifyCVResetFactoryDefault()
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);
@@ -208,9 +202,9 @@ void setup() //******************************************************
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
delay(800);
#if defined(DECODER_LOADED)
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
#endif
{
for (int j=0; j < FactoryDefaultCVIndex; j++ )
@@ -218,11 +212,13 @@ void setup() //******************************************************
digitalWrite(fpins[14], 1);
delay (1000);
digitalWrite(fpins[14], 0);
}
}
for ( i=0; i < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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;
@@ -230,7 +226,7 @@ void setup() //******************************************************
case 1: // LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -238,105 +234,29 @@ void setup() //******************************************************
}
break;
case 2: //servo
{ ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5)));
{
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
// 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<servo_start_delay; t++)
{SoftwareServo::refresh();delay(servo_init_delay);}
ftn_queue[i].inuse = 0;
servo[i].detach();
}
break;
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
ftn_queue[i].inuse = 0;
ftn_queue[i].current_position = 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);
@@ -344,29 +264,46 @@ void setup() //******************************************************
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
}
break;
case 4: // NEXT FEATURE to pin
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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
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);
@@ -376,18 +313,30 @@ void loop() //****************************************************************
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
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);
@@ -397,10 +346,21 @@ void loop() //****************************************************************
}
i++;
break;
case 4: //FUTURE FUNCTION
break;
default:
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;
}
}
}
@@ -443,9 +403,8 @@ 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=Double LED Blink
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
//Serial.println("****************cv:0 ") ;
digitalWrite (pin, FuncState);
ftn_queue[function].inuse = 0;
break;
@@ -463,21 +422,14 @@ void exec_function (int function, int pin, int FuncState) {
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
/*
Serial.print("servo inc: ") ;
Serial.print(ftn_queue[function].increment,DEC) ;
Serial.print("servo inuse: ") ;
Serial.print(ftn_queue[function].inuse,DEC) ;
Serial.print("servo num: ") ;
Serial.print(function,DEC) ;
Serial.print(" stop: ");
Serial.println(ftn_queue[function].stop_value,DEC) ;
*/
break;
case 3: // Blinking LED PAIR
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
@@ -494,7 +446,34 @@ void exec_function (int function, int pin, int FuncState) {
}
}
break;
case 4: // Future Function
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<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 6: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
@@ -502,43 +481,3 @@ void exec_function (int function, int pin, int FuncState) {
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,10 +1,12 @@
#include <NmraDcc.h>
// Working 17 Function DCC Decoder DccAckPin not needed
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// LED control is dependent on direction of travel
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
int tim_delay = 500;
#define numleds 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
@@ -17,7 +19,7 @@ byte led_direction [] = {0,1,2,0,1,1,1,1,2,2,2,2,0,0,0,0,0}; //0=On/Off,
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
uint8_t Decoder_direction = 0;
uint8_t Decoder_direction = DCC_DIR_FWD;
uint8_t Last_Decoder_direction = 0;
int fade_time = 170;
const int FunctionPin0 = 3;
@@ -101,7 +103,6 @@ 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) {
@@ -146,8 +147,7 @@ void exec_function (int f_index, int FuncState) {
Set_LED (f_index,false);
}
}
void notifyDccSpeed( uint16_t Addr, uint8_t Speed, uint8_t ForwardDir, uint8_t MaxSpeed ) {
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
Last_Decoder_direction = Decoder_direction;
Decoder_direction = ForwardDir;
if ( Decoder_direction==Last_Decoder_direction) return;

View File

@@ -1,12 +1,19 @@
#include <NmraDcc.h>
// Working 12 Function DCC Decoder DccAckPin not needed
// 5 pin Arbitrary Group Lighting Functions Set in 4-Function Groups
// With Fade On and Fade Off
// Rev 4 Geoff Bunza September 2015
// Production 17 Function DCC Decoder
// Version 5.1 Geoff Bunza 2014,2015,2016
// NO LONGER REQUIRES modified software servo Lib
// Software restructuring mods added from Alex Shepherd and Franz-Peter
// With sincere thanks
// ******** 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 <NmraDcc.h>
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};
@@ -85,7 +92,9 @@ void notifyCVResetFactoryDefault()
void setup()
{
//Serial.begin(115200);
#ifdef DEBUG
Serial.begin(115200);
#endif
// initialize the digital pins as an outputs
for (int i=0; i< numleds; i++) {
pinMode(ledpins[i], OUTPUT);
@@ -102,9 +111,9 @@ void setup()
}
delay( tim_delay);
#if defined(DECODER_LOADED)
#if defined(DECODER_LOADED)
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
#endif
#endif
{
for (int j=0; j < FactoryDefaultCVIndex; j++ )
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
@@ -116,6 +125,7 @@ void setup()
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()
{
@@ -172,5 +182,3 @@ void exec_function (int f_index, int FuncState) {
Last_Function_State[f_index] = false;
}
}

View File

@@ -1,565 +0,0 @@
// Production 17 Function DCC Decoder
// Uses modified software servo Lib
//
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
#define servo_start_delay 50
#define servo_init_delay 7
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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 & LOAD ACK
const int FunctionPin15 = 18; //A4
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
uint8_t CV_DECODER_MASTER_RESET = 120;
int t; // temp
#define This_Decoder_Address 24
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;
};
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_DECODER_MASTER_RESET, 0},
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 4}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 0}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 0}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 0}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{61, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{62, 28}, // Start Position Fx=0
{63, 140}, // End Position Fx=1
{64, 28}, // Current Position
{65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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 = 95;
void notifyCVResetFactoryDefault()
{
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
// to flag to the loop() function that a reset to Factory Defaults needs to be done
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
};
void setup() //******************************************************
{
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);
digitalWrite(fpins[i], 0);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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 );
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 < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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].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 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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
}
break;
case 3: // DOUBLE ALTERNATING LED Blink
{
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);
digitalWrite(fpins[i+1], 0);
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.;
}
break;
case 4: // 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 5: // 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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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))) *10.;
}
break;
case 2:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
break;
case 3:
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))) *10.;
}
i++;
break;
case 4: // Fade On
break;
case 5: //FUTURE FUNCTION
break;
default:
break;
}
}
}
}
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
if (FuncNum==1) { //Function Group 1 F0 F4 F3 F2 F1
exec_function( 0, FunctionPin0, (FuncState&0x10)>>4 );
exec_function( 1, FunctionPin1, (FuncState&0x01 ));
exec_function( 2, FunctionPin2, (FuncState&0x02)>>1 );
exec_function( 3, FunctionPin3, (FuncState&0x04)>>2 );
exec_function( 4, FunctionPin4, (FuncState&0x08)>>3 );
}
else if (FuncNum==2) { //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8
if ((FuncState & 0x10)==0x10) {
exec_function( 5, FunctionPin5, (FuncState&0x01 ));
exec_function( 6, FunctionPin6, (FuncState&0x02)>>1 );
exec_function( 7, FunctionPin7, (FuncState&0x04)>>2 );
exec_function( 8, FunctionPin8, (FuncState&0x08)>>3 );
}
else {
exec_function( 9, FunctionPin9, (FuncState&0x01 ));
exec_function( 10, FunctionPin10, (FuncState&0x02)>>1 );
exec_function( 11, FunctionPin11, (FuncState&0x04)>>2 );
exec_function( 12, FunctionPin12, (FuncState&0x08)>>3 );
}
}
else if (FuncNum==3) { //Function Group 2 FuncState == F20-F13 Function Control
exec_function( 13, FunctionPin13, (FuncState&0x01 ));
exec_function( 14, FunctionPin14, (FuncState&0x02)>>1 );
exec_function( 15, FunctionPin15, (FuncState&0x04)>>2 );
exec_function( 16, FunctionPin16, (FuncState&0x08)>>3 );
}
}
void exec_function (int function, int pin, int FuncState) {
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
case 0: // On - Off LED
//Serial.println("****************cv:0 ") ;
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(fpins[function], 0);
ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5))) *10.;
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 2: // Servo
ftn_queue[function].inuse = 1;
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));
/*
Serial.print("servo inc: ") ;
Serial.print(ftn_queue[function].increment,DEC) ;
Serial.print("servo inuse: ") ;
Serial.print(ftn_queue[function].inuse,DEC) ;
Serial.print("servo num: ") ;
Serial.print(function,DEC) ;
Serial.print(" stop: ");
Serial.println(ftn_queue[function].stop_value,DEC) ;
*/
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))) *10.;
} else {
if (FuncState==0) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
digitalWrite(fpins[function+1], 0);
}
}
break;
case 4: // Fade On
#define fadedelay 24
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
ftn_queue[function].inuse = 1;
for (t=0; t<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
digitalWrite( fpins[function], 1);
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
digitalWrite( fpins[function], 0);
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
}
digitalWrite( fpins[function], 1 );
} else {
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
ftn_queue[function].inuse = 0;
digitalWrite(fpins[function], 0);
}
}
break;
case 5: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,566 +0,0 @@
// Production 17 Function DCC Decoder
// Version 3.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// This configuration supports 5 Modes per pin:
// 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
// It is recommended that you NOT MIX pulsed and servo control
// simultaneously as the servo timing will be off
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
#define servo_start_delay 50
#define servo_init_delay 7
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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 & LOAD ACK
const int FunctionPin15 = 18; //A4
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
uint8_t CV_DECODER_MASTER_RESET = 120;
int t; // temp
#define This_Decoder_Address 24
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;
};
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_DECODER_MASTER_RESET, 0},
{30, 4}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{31, 10}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{32, 28}, //F0 Start Position F0=0
{33, 140}, //F0 End Position F0=1
{34, 0}, //F0 Current Position
{35, 4}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{36, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{37, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 0}, // Current Position
{40, 4}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{41, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 0}, // Current Position
{45, 4}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{46, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 0}, // Current Position
{50, 4}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{51, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 0}, // Current Position
{55, 4}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{56, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{57, 28}, // Start Position Fx=0
{58, 140}, // End Position Fx=1
{59, 0}, // Current Position
{60, 4}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{61, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{62, 28}, // Start Position Fx=0
{63, 140}, // End Position Fx=1
{64, 0}, // Current Position
{65, 4}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{66, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{67, 1}, // Start Position Fx=0
{68,35}, // End Position Fx=1
{69, 0}, // Current Position
{70, 4}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{71, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{72, 1}, // Start Position Fx=0
{73, 100}, // End Position Fx=1
{74, 0}, // Current Position
{75, 4}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{76, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{77, 1}, // Start Position Fx=0
{78, 10}, // End Position Fx=1
{79, 0}, // Current Position
{80, 4}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{81, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{82, 1}, // Start Position Fx=0
{83, 5}, // End Position Fx=1
{84, 0}, // Current Position
{85, 4}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{86, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{87, 1}, // Start Position Fx=0
{88, 5}, // End Position Fx=1
{89, 0}, // Current Position
{90, 4}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{91, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{92, 1}, // Start Position Fx=0
{93, 20}, // End Position Fx=1
{94, 0}, // Current Position
{95, 4}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{96, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{97, 1}, // Start Position Fx=0
{98, 35}, // End Position Fx=1
{99, 0}, // Current Position
{100, 4}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{101, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{102, 1}, // Start Position Fx=0
{103, 4}, // End Position Fx=1
{104, 0}, // Current Position
{105, 4}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{106, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{107, 1}, // Start Position Fx=0
{108, 60}, // End Position Fx=1
{109, 0}, // Current Position
{110, 4}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{111, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{112, 1}, // Start Position Fx=0
{113, 4}, // End Position Fx=1
{114, 0}, // Current Position
//FUTURE USE
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink,4=Pulsed
{116, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Pulsed=Milliseconds/10
{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);
};
void setup() //******************************************************
{
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);
digitalWrite(fpins[i], 0);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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 );
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 < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
}
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: //FUTURE FUNCTION
break;
default:
break;
}
}
}
void loop() //**********************************************************************
{
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
break;
case 3:
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
break;
case 5: //FUTURE FUNCTION
break;
default:
break;
}
}
}
}
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
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
exec_function( 13, FunctionPin13, (FuncState & FN_BIT_13));
exec_function( 14, FunctionPin14, (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=Double LED Blink
case 0: // On - Off LED
//Serial.println("****************cv:0 ") ;
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
ftn_queue[function].inuse = 1;
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));
/*
Serial.print("servo inc: ") ;
Serial.print(ftn_queue[function].increment,DEC) ;
Serial.print("servo inuse: ") ;
Serial.print(ftn_queue[function].inuse,DEC) ;
Serial.print("servo num: ") ;
Serial.print(function,DEC) ;
Serial.print(" stop: ");
Serial.println(ftn_queue[function].stop_value,DEC) ;
*/
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: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -1,672 +0,0 @@
// Production Motor Drive 13 Pin Function DCC Decoder with Motor Drive
// F13 and F14 enable speed control of MOTOR1 and MOTOR2 respectively
// Version 5.0 Geoff Bunza 2015
// Uses modified software servo Lib
//
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
#define servo_start_delay 50
#define servo_init_delay 7
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 = 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
int Function13_value = 0;
int Function14_value = 0;
NmraDcc Dcc ;
DCC_MSG Packet ;
uint8_t CV_DECODER_MASTER_RESET = 120;
int t; // temp
#define This_Decoder_Address 24
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;
};
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_DECODER_MASTER_RESET, 0},
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
{32, 1}, //F0 Start Position F0=0
{33, 1}, //F0 End Position F0=1
{34, 10}, //F0 Current Position
{35, 0}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{36, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{37, 1}, // Start Position Fx=0
{38, 1}, // End Position Fx=1
{39, 10}, // Current Position
{40, 0}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 1}, // Start Position Fx=0
{43, 10}, // End Position Fx=1
{44, 10}, // Current Position
{45, 0}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 1}, // Start Position Fx=0
{48, 1}, // End Position Fx=1
{49, 10}, // Current Position
{50, 0}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 1}, // Start Position Fx=0
{53, 1}, // End Position Fx=1
{54, 10}, // Current Position
{55, 0}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{56, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{57, 1}, // Start Position Fx=0
{58, 1}, // End Position Fx=1
{59, 10}, // Current Position
{60, 0}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{61, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{62, 1}, // Start Position Fx=0
{63, 1}, // End Position Fx=1
{64, 10}, // Current Position
{65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{67, 1}, // Start Position Fx=0
{68, 1}, // End Position Fx=1
{69, 1}, // Current Position
{70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{72, 1}, // Start Position Fx=0
{73, 10}, // End Position Fx=1
{74, 1}, // Current Position
{75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{77, 1}, // Start Position Fx=0
{78, 10}, // End Position Fx=1
{79, 1}, // Current Position
{80, 2}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{92, 1}, // Start Position Fx=0
{93, 1}, // End Position Fx=1
{94, 28}, // Current Position
{95, 0}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{97, 1}, // Start Position Fx=0
{98, 28}, // End Position Fx=1
{99, 2}, // Current Position
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{102, 1}, // Start Position Fx=0
{103, 4}, // End Position Fx=1
{104, 1}, // Current Position
{105, 0}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{107, 1}, // Start Position Fx=0
{108, 1}, // End Position Fx=1
{109, 20}, // Current Position
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{112, 1}, // Start Position Fx=0
{113, 1}, // End Position Fx=1
{114, 1}, // Current Position
//FUTURE USE
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{116, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{117, 28}, // Start Position Fx=0
{118, 140}, // 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);
};
void setup() //******************************************************
{
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);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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 );
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)) ;
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
}
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: // NEXT FEATURE to pin
break;
default:
break;
}
}
}
void loop() //**********************************************************************
{
boolean servo_on = true;
//MUST call the NmraDcc.process() method frequently
// from the Arduino loop() function for correct library operation
Dcc.process();
SoftwareServo::refresh();
delay(2);
if (Motor1Speed != 0) {
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, int((Motor1Speed&0x7f)*21));
else gobwd1 (bwdtime, int((Motor1Speed&0x7f)*21));
}
if (Motor2Speed != 0) {
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, int((Motor2Speed&0x7f)*21));
else gobwd2 (bwdtime, int((Motor2Speed&0x7f)*21));
}
//
for (int i=0; i < num_active_fpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
servo_on = true;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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:
{
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;
servo_on = false;
detach_servo (i);
}
}
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;
servo_on = false;
detach_servo (i);
}
}
if (servo_on) {
set_servo(i, ftn_queue[i].current_position);
}
}
break;
case 3:
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: //FUTURE FUNCTION
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, uint8_t Speed, uint8_t ForwardDir, uint8_t MaxSpeed ) {
if (Function13_value==1) {
Motor1Speed = Speed;
Motor1ForwardDir = ForwardDir;
Motor1MaxSpeed = MaxSpeed;
}
if (Function14_value==1) {
Motor2Speed = Speed;
Motor2ForwardDir = ForwardDir;
Motor2MaxSpeed = MaxSpeed;
}
}
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
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=Double LED Blink
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
ftn_queue[function].inuse = 1;
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: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0:
if (servo0.attached()==0) servo0.attach(FunctionPin0);
servo0.write(servo_pos);
break;
case 1:
if (servo1.attached()==0) servo1.attach(FunctionPin1);
servo1.write(servo_pos);
break;
case 2:
if (servo2.attached()==0) servo2.attach(FunctionPin2);
servo2.write(servo_pos);
break;
case 3:
if (servo3.attached()==0) servo3.attach(FunctionPin3);
servo3.write(servo_pos);
break;
case 4:
if (servo4.attached()==0) servo4.attach(FunctionPin4);
servo4.write(servo_pos);
break;
case 5:
if (servo5.attached()==0) servo5.attach(FunctionPin5);
servo5.write(servo_pos);
break;
case 6:
if (servo6.attached()==0) servo6.attach(FunctionPin6);
servo6.write(servo_pos);
break;
case 7:
if (servo7.attached()==0) servo7.attach(FunctionPin7);
servo7.write(servo_pos);
break;
case 8:
if (servo8.attached()==0) servo8.attach(FunctionPin8);
servo8.write(servo_pos);
break;
case 9:
if (servo9.attached()==0) servo9.attach(FunctionPin9);
servo9.write(servo_pos);
break;
case 10:
if (servo10.attached()==0) servo10.attach(FunctionPin10);
servo10.write(servo_pos);
break;
case 11:
if (servo11.attached()==0) servo11.attach(FunctionPin11);
servo11.write(servo_pos);
break;
case 12:
if (servo12.attached()==0) servo12.attach(FunctionPin12);
servo12.write(servo_pos);
break;
default:
break;
}
}
void detach_servo (int servo_num) {
switch (servo_num) {
case 0:
if (servo0.attached()!=0) servo0.detach();
break;
case 1:
if (servo1.attached()!=0) servo1.detach();
break;
case 2:
if (servo2.attached()!=0) servo2.detach();
break;
case 3:
if (servo3.attached()!=0) servo3.detach();
break;
case 4:
if (servo4.attached()!=0) servo4.detach();
break;
case 5:
if (servo5.attached()!=0) servo5.detach();
break;
case 6:
if (servo6.attached()!=0) servo6.detach();
break;
case 7:
if (servo7.attached()!=0) servo7.detach();
break;
case 8:
if (servo8.attached()!=0) servo8.detach();
break;
case 9:
if (servo9.attached()!=0) servo9.detach();
break;
case 10:
if (servo10.attached()!=0) servo10.detach();
break;
case 11:
if (servo11.attached()!=0) servo11.detach();
break;
case 12:
if (servo12.attached()!=0) servo12.detach();
default:
break;
}
}

View File

@@ -1,544 +0,0 @@
// Production 17 Function DCC Decoder
// Version 3.0 Geoff Bunza 2014
// Uses modified software servo Lib
//
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
//#define DECODER_LOADED
#include <NmraDcc.h>
#include <SoftwareServo.h>
SoftwareServo servo0;
SoftwareServo servo1;
SoftwareServo servo2;
SoftwareServo servo3;
SoftwareServo servo4;
SoftwareServo servo5;
SoftwareServo servo6;
SoftwareServo servo7;
SoftwareServo servo8;
SoftwareServo servo9;
SoftwareServo servo10;
SoftwareServo servo11;
SoftwareServo servo12;
SoftwareServo servo13;
SoftwareServo servo14;
SoftwareServo servo15;
SoftwareServo servo16;
#define servo_start_delay 50
#define servo_init_delay 7
int tim_delay = 500;
int numfpins = 17;
byte fpins [] = {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;
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 & LOAD ACK
const int FunctionPin15 = 18; //A4
const int FunctionPin16 = 19; //A5
NmraDcc Dcc ;
DCC_MSG Packet ;
uint8_t CV_DECODER_MASTER_RESET = 120;
int t; // temp
#define This_Decoder_Address 24
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;
};
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_DECODER_MASTER_RESET, 0},
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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
{35, 2}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{36, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{37, 28}, // Start Position Fx=0
{38, 140}, // End Position Fx=1
{39, 28}, // Current Position
{40, 2}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{41, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{42, 28}, // Start Position Fx=0
{43, 140}, // End Position Fx=1
{44, 28}, // Current Position
{45, 2}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{46, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{47, 28}, // Start Position Fx=0
{48, 140}, // End Position Fx=1
{49, 28}, // Current Position
{50, 2}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{51, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{52, 28}, // Start Position Fx=0
{53, 140}, // End Position Fx=1
{54, 28}, // Current Position
{55, 2}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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, 2}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{61, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{62, 28}, // Start Position Fx=0
{63, 140}, // End Position Fx=1
{64, 28}, // Current Position
{65, 1}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{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=Double LED Blink
{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=Double LED Blink
{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, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{92, 1}, // Start Position Fx=0
{93, 20}, // End Position Fx=1
{94, 1}, // Current Position
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{97, 1}, // Start Position Fx=0
{98, 35}, // End Position Fx=1
{99, 2}, // Current Position
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
{102, 1}, // Start Position Fx=0
{103, 4}, // End Position Fx=1
{104, 1}, // Current Position
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink
{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=Double LED Blink
{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=Double LED Blink
{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);
};
void setup() //******************************************************
{
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);
digitalWrite(fpins[i], 0);
}
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 1);
delay (tim_delay/10);
}
delay( tim_delay);
for (int i=0; i < numfpins; i++) {
digitalWrite(fpins[i], 0);
delay (tim_delay/10);
}
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 );
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 < numfpins; i++) {
cv_value = Dcc.getCV( 30+(i*5)) ;
//Serial.print(" cv_value: ");
//Serial.println(cv_value, DEC) ;
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))));
switch ( i ) {
case 0: servo0.attach(FunctionPin0); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo0.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 1: servo1.attach(FunctionPin1); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo1.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 2: servo2.attach(FunctionPin2); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo2.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 3: servo3.attach(FunctionPin3); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo3.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 4: servo4.attach(FunctionPin4); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo4.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 5: servo5.attach(FunctionPin5); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo5.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 6: servo6.attach(FunctionPin6); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo6.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 7: servo7.attach(FunctionPin7); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo7.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 8: servo8.attach(FunctionPin8); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo8.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 9: servo9.attach(FunctionPin9); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo9.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 10: servo10.attach(FunctionPin10); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo10.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 11: servo11.attach(FunctionPin11); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo11.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 12: servo12.attach(FunctionPin12); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo12.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 13: servo13.attach(FunctionPin13); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo13.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 14: servo14.attach(FunctionPin14); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo14.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 15: servo15.attach(FunctionPin15); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo15.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
case 16: servo16.attach(FunctionPin16); // attaches servo on pin to the servo object
ftn_queue[i].inuse = 1;
servo16.write(ftn_queue[i].start_value);
for (t=0; t<servo_start_delay; t++) {SoftwareServo::refresh();delay(servo_init_delay);}
break;
default:
break;
}
}
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: // 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();
SoftwareServo::refresh();
delay(8);
for (int i=0; i < numfpins; i++) {
if (ftn_queue[i].inuse==1) {
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
switch (Dcc.getCV( 30+(i*5))) {
case 0:
break;
case 1:
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:
{
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;
}
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;
}
set_servo(i, ftn_queue[i].current_position);
}
break;
case 3:
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: //FUTURE FUNCTION
break;
default:
break;
}
}
}
}
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
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
exec_function( 13, FunctionPin13, (FuncState & FN_BIT_13));
exec_function( 14, FunctionPin14, (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=Double LED Blink
case 0: // On - Off LED
//Serial.println("****************cv:0 ") ;
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
ftn_queue[function].inuse = 1;
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));
/*
Serial.print("servo inc: ") ;
Serial.print(ftn_queue[function].increment,DEC) ;
Serial.print("servo inuse: ") ;
Serial.print(ftn_queue[function].inuse,DEC) ;
Serial.print("servo num: ") ;
Serial.print(function,DEC) ;
Serial.print(" stop: ");
Serial.println(ftn_queue[function].stop_value,DEC) ;
*/
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: // Future Function
ftn_queue[function].inuse = 0;
break;
default:
ftn_queue[function].inuse = 0;
break;
}
}
void set_servo (int servo_num, int servo_pos) {
switch (servo_num) {
case 0: servo0.write(servo_pos);
break;
case 1: servo1.write(servo_pos);
break;
case 2: servo2.write(servo_pos);
break;
case 3: servo3.write(servo_pos);
break;
case 4: servo4.write(servo_pos);
break;
case 5: servo5.write(servo_pos);
break;
case 6: servo6.write(servo_pos);
break;
case 7: servo7.write(servo_pos);
break;
case 8: servo8.write(servo_pos);
break;
case 9: servo9.write(servo_pos);
break;
case 10: servo10.write(servo_pos);
break;
case 11: servo11.write(servo_pos);
break;
case 12: servo12.write(servo_pos);
break;
case 13: servo13.write(servo_pos);
break;
case 14: servo14.write(servo_pos);
break;
case 15: servo15.write(servo_pos);
break;
case 16: servo16.write(servo_pos);
break;
default:
break;
}
}

View File

@@ -33,87 +33,87 @@ Correspondingly by way of example, for the 7 Servo 10 LED decoder configuration,
\par
\ul\b\{CV number, Value\} Description\par
\ulnone\b0 \{1, 24\} Decoder Initial Address\par
\{30, 2\}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{30, 2\}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{31, 1\}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{32, 28\}, //F0 Start Position F0=0\par
\{33, 140\}, //F0 End Position F0=1\par
\{34, 28\}, //F0 Current Position\par
\{35, 2\}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{35, 2\}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{36, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{37, 28\}, // Start Position Fx=0\par
\{38, 140\}, // End Position Fx=1\par
\{39, 28\}, // Current Position\par
\{40, 2\}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{40, 2\}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{41, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{42, 28\}, // Start Position Fx=0\par
\{43, 140\}, // End Position Fx=1\par
\{44, 28\}, // Current Position\par
\{45, 2\}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{45, 2\}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{46, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{47, 28\}, // Start Position Fx=0\par
\{48, 140\}, // End Position Fx=1\par
\{49, 28\}, // Current Position\par
\{50, 2\}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{50, 2\}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{51, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{52, 28\}, // Start Position Fx=0\par
\{53, 140\}, // End Position Fx=1\par
\{54, 28\}, // Current Position\par
\{55, 2\}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{55, 2\}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{56, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{57, 28\}, // Start Position Fx=0\par
\{58, 140\}, // End Position Fx=1\par
\{59, 28\}, // Current Position\par
\{60, 2\}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{60, 2\}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{61, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{62, 28\}, // Start Position Fx=0\par
\{63, 140\}, // End Position Fx=1\par
\{64, 28\}, // Current Position\par
\{65, 1\}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{65, 1\}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{66, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{67, 1\}, // Start Position Fx=0\par
\{68,35\}, // End Position Fx=1\par
\{69, 1\}, // Current Position\par
\{70, 1\}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{70, 1\}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{71, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{72, 1\}, // Start Position Fx=0\par
\{73, 100\}, // End Position Fx=1\par
\{74, 1\}, // Current Position\par
\{75, 0\}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{75, 0\}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{76, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{77, 1\}, // Start Position Fx=0\par
\{78, 10\}, // End Position Fx=1\par
\{79, 1\}, // Current Position\par
\{80, 0\}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{80, 0\}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{81, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{82, 1\}, // Start Position Fx=0\par
\{83, 5\}, // End Position Fx=1\par
\{84, 1\}, // Current Position\par
\{85, 1\}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{85, 1\}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{86, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{87, 1\}, // Start Position Fx=0\par
\{88, 5\}, // End Position Fx=1\par
\{89, 1\}, // Current Position\par
\{90, 1\}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{90, 1\}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{91, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{92, 1\}, // Start Position Fx=0\par
\{93, 20\}, // End Position Fx=1\par
\{94, 1\}, // Current Position\par
\{95, 3\}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{95, 3\}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{96, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{97, 1\}, // Start Position Fx=0\par
\{98, 35\}, // End Position Fx=1\par
\{99, 2\}, // Current Position\par
\{100, 0\}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{100, 0\}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{101, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{102, 1\}, // Start Position Fx=0\par
\{103, 4\}, // End Position Fx=1\par
\{104, 1\}, // Current Position\par
\{105, 3\}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{105, 3\}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{106, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{107, 1\}, // Start Position Fx=0\par
\{108, 60\}, // End Position Fx=1\par
\{109, 20\}, // Current Position\par
\{110, 0\}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=Double LED Blink\par
\{110, 0\}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade\par
\{111, 1\}, // Rate Blink=Eate,PWM=Rate,Servo=Rate\par
\{112, 1\}, // Start Position Fx=0\par
\{113, 4\}, // End Position Fx=1\par

View File

@@ -0,0 +1,38 @@
Release Notes for the 5.1 SMA Decoder Examples
1. Automatic servo attachment and detachment has been implemented for all
servo control functions. When a servo has stopped at the end of its traverse,
it will be "detached" by the software. This has been demonstrated
to reduce power consumption greatly and reduce servo "chatter."
2. Several bug fixes including all reported bugs as of May 2016
3. In the fully conficurable verions. all 17 pins now can be configured for any of 6 functions
Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=variable Pulse ,5=fade on
4. Servo timing has a timing modifier added for extra slow servo traverse
#define servo_slowdown 3 //servo loop counter limit
Can be set from 0 to 255 -- the higher the number the slower the traverse
5. Software has been restructured to support new NmraDcc library releases
including the NmraDcc-MicroBahner library version.
6. 18 Predefined decoder skectekes are included:
Mobile Decoders:
Dec_2MotDrive_12LED_1Srv_6Ftn Dual motor drive, 12 LED 6 Function
Dec_7Serv_10LED_6Ftn 7 Servo 10 LED 6 Function
Dec_10Serv_7LED_6Ftn 10 Servo 7 LED 6 Function
Dec_13Serv_4LED_6Ftn 13 Servo 4 LED 6 Function
Dec_15Serv_2LED_6Ftn 15 Servo 2 LED 6 Function
Dec_17LED_1Ftn 17 LED ON/OFF Control
Dec_17LED_6Ftn 17 LED 6 Function
Dec_Dir_and_Fade 17 LED with Dual Direction Control and FADE
Dec_SMA12_LED_Groups LED Group Control for Euro Signaling
Accessory Decoders:
AccDec_7ServoBackandForth6Ftn 7 Servo 10 LED 6 Function
AccDec_7Servos_10LED_6Ftn 7 Servo 10 LED 6 Function
AccDec_10Servos_7LED_6Ftn 10 Servo 7 LED 6 Function
AccDec_13Servos_4LED_6Ftn 13 Servo 4 LED 6 Function
AccDec_15Servos_2LED_6Ftn 15 Servo 2 LED 6 Function
AccDec_17LED_1Ftn 17 LED ON/OFF Control
AccDec_17LED_6Ftn 17 LED 6 Function