Hallo liebe Stummiforum Gemeinde
Ich habe ein Problem mit unten Abgebildeten Sketch der wie ich glaube recht bekannt sein dürfte.
Ich nutze Eigenbau DCC Decoder auf Arduino Basis mit Adafruit PCA 9685 PWM Shirlds.
Als DCC Zentrale nutze ich das hier im Forum bekannte 10€ Analog/DCC Regler/zentrale ohne PC mit Funk System, welches Fabelhaft funktioniert.
Meine Decoder sind alle mit einem PC 817 Optokoppler ausgerüstet was auch gut funktioniert.
Ich würde die alle gerne mit einem 6N137 Optokoppler versehen.
Grund ist das bei Automatikbetrieb mit Windigipet in den Fahrstraßen nicht immer alle Weichen zuverlässig schalten was wie ich glaube an den zu langsamen
PC 817 Optos liegt.
Tests mit eingelöteten 6N137 Optos zeigten dann keine Funktion mehr.
Ist es möglich im Sketch die Library DCC_Decoder.h durch die Library NmraDCC zu ersetzen?
Muss ich im Sketch noch irgentwelche Änderungen vornehmen?
Das Programmieren mit Arduino IDE ist nicht so ganz mein Steckenpferd.
Über Hilfe würde ich riesig freuen..
Vielen Dank schonmal im vorraus.
Anhang mein verwendeter Sketch.
Gruss Andi
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Arduino DCC Servo and Function Decoder.
// Author: Author: Ruud Boer - January 2015
// This sketch turns an Arduino into a DCC decoder with max 12 servo motor outputs combined with function outputs.
// The DCC signal is optically separated and fed to pin 2 (=Interrupt 0). Schematics:
// Many thanks to for publishing their DCC monitor and -decoder code, which is used in this sketch.
//
// Important Change:
// This sketch from Ruud Boer was changed by lordbrummi in April 2016
// Now you can connect a PWM Arduino Servo Shield with 16 possible servos and adress them with DCC adresses
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT: change some lines marked as IMPORTANT !!!!!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#include <DCC_Decoder.h>
#include <Servo.h>
#define kDCC_INTERRUPT 0
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fill in these values ...
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const byte maxservos = 16; //The number of servos (not the physical number, but the number of servo adresses defined. IMPORTANT!!!!!
const byte servotimer = 0; //Global Servotimer fo all servos, higher value is slower (0 is recommended)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set the Servomin and the Servomax of your servo between the gear range possibility IMPORTANT!!!!!
const int SERVOMIN = 150; // this is the 'minimum' pulse length count (out of 4096)
const int SERVOMAX = 600; // this is the 'maximum' pulse length count (out of 4096)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int lastaddr; // last switched adress, internal use only
unsigned long timetoupdatesetpoint = millis() + servotimer;
struct DCCAccessoryAddress {
int address; // DCC address to respond to
byte output; // State of accessory: 1=on, 0=off (for internal use only)
int outputPin; // Arduino output pin
int change; // State of accessory change: 1=change, 0=no change (for internal use only)
};
DCCAccessoryAddress accessory[maxservos];
struct servoItem {
int angle;
int setpoint;
int offangle;
int onangle;
byte inverted;
int servo;
byte functionnumber;
unsigned long stimer;
unsigned long suptimer;
};
servoItem servos[maxservos];
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fill in the address and pin for every accessory / function. Servos are 'coupled' to accessory[n] in line 72 and further. IMPORTANT!!!!!
// COPY - PASTE as many times as you have functions. The amount must be same as in line 22 above!
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ConfigureDecoderFunctions()
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// You have to declare as much accessorys as servomax is defined above.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
accessory[0].address = 25; // DCC address for this accessory IMPORTANT!!!!!
accessory[0].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[1].address = 26; // DCC address for this accessory
accessory[1].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[2].address = 27; // DCC address for this accessory
accessory[2].outputPin = 12; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[3].address = 28; // DCC address for this accessory
accessory[3].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[4].address = 51; // DCC address for this accessory
accessory[4].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[5].address = 30; // DCC address for this accessory
accessory[5].outputPin = 12; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[6].address = 48; // DCC address for this accessory
accessory[6].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[7].address = 32; // DCC address for this accessory
accessory[7].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[8].address = 41; // DCC address for this accessory
accessory[8].outputPin = 12; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[9].address = 34; // DCC address for this accessory
accessory[9].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[10].address = 61; // DCC address for this accessory
accessory[10].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[11].address = 36; // DCC address for this accessory
accessory[11].outputPin = 12; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[12].address = 37; // DCC address for this accessory
accessory[12].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[13].address = 38; // DCC address for this accessory
accessory[13].outputPin = 12; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[14].address = 39; // DCC address for this accessory
accessory[14].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
accessory[15].address = 40; // DCC address for this accessory
accessory[15].outputPin = 13; // Arduino pin where accessory is connected to and which will be switched on/off
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup output pins for accessories
for(int i=0; i<maxservos; i++)
{
if( accessory[i].outputPin )
{
pinMode (accessory[i].outputPin, OUTPUT );
digitalWrite (accessory[i].outputPin, LOW);
}
}
} // END ConfigureDecoderFunctions
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fill in the attributes for every servo
// COPY - PASTE as many times as you have servo's. The amount must be same as maxservos in line 22 above!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ConfigureDecoderServos()
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// You have to declare as much servos as servomax is defined above.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
servos[0].angle=140; // initial angle of servo (at startup) IMPORTANT!!!!!
servos[0].offangle=140; // minimum angle. Do not use value too close to 0, servo may stutter at the extremes.
servos[0].onangle=115; // maximum angle. Do not use value too close to 180, servo may stutter at the extremes.
servos[0].servo=0; // PWM Pin where the servo is connected to
servos[0].functionnumber=0; // CONNECTION BETWEEN FUNCTION AND SERVO ()accessory[functionnumber] - see above) - in the accessory function is the DCC adress defined !!!!!!
servos[0].stimer=5; // Servotimer for this servo, higher value is slower, 0 is very fast, means the setpoint will be set immediatly
servos[1].angle=140;
servos[1].offangle=140;
servos[1].onangle=123;
servos[1].servo=1; // This is the same PWM Pin as the servo above, but this are the to other angles
servos[1].functionnumber=1;
servos[1].stimer=5;
servos[2].angle=139;
servos[2].offangle=139;
servos[2].onangle=123;
servos[2].servo=2; // this servo is on PWM Pin1
servos[2].functionnumber=2;
servos[2].stimer=5;
servos[3].angle=145;
servos[3].offangle=145;
servos[3].onangle=123;
servos[3].servo=3; // This is the same PWM Pin as the servo above, but this are the to other angles
servos[3].functionnumber=3;
servos[3].stimer=5;
servos[4].angle=146;
servos[4].offangle=146;
servos[4].onangle=115;
servos[4].servo=4; // this servo is on PWM Pin1
servos[4].functionnumber=4;
servos[4].stimer=5;
servos[5].angle=143;
servos[5].offangle=143;
servos[5].onangle=123;
servos[5].servo=5; // This is the same PWM Pin as the servo above, but this are the to other angles
servos[5].functionnumber=5;
servos[5].stimer=5;
servos[6].angle=146;
servos[6].offangle=146;
servos[6].onangle=114;
servos[6].servo=6; // this servo is on PWM Pin1
servos[6].functionnumber=6;
servos[6].stimer=5;
servos[7].angle=123;
servos[7].offangle=145;
servos[7].onangle=123;
servos[7].servo=7; // This is the same PWM Pin as the servo above, but this are the to other angles
servos[7].functionnumber=7;
servos[7].stimer=5;
servos[8].angle=144;
servos[8].offangle=144;
servos[8].onangle=123;
servos[8].servo=8; // this servo is on PWM Pin1
servos[8].functionnumber=8;
servos[8].stimer=5;
servos[9].angle=144;
servos[9].offangle=144;
servos[9].onangle=123;
servos[9].servo=9; // This is the same PWM Pin as the servo above, but this are the to other angles
servos[9].functionnumber=9;
servos[9].stimer=5;
servos[10].angle=145;
servos[10].offangle=145;
servos[10].onangle=123;
servos[10].servo=10; // this servo is on PWM Pin1
servos[10].functionnumber=10;
servos[10].stimer=5;
servos[11].angle=123;
servos[11].offangle=145;
servos[11].onangle=123;
servos[11].servo=11; // This is the same PWM Pin as the servo above, but this are the to other angles
servos[11].functionnumber=11;
servos[11].stimer=5;
servos[12].angle=123;
servos[12].offangle=145;
servos[12].onangle=121;
servos[12].servo=12; // this servo is on PWM Pin1
servos[12].functionnumber=12;
servos[12].stimer=5;
servos[13].angle=124;
servos[13].offangle=145;
servos[13].onangle=124;
servos[13].servo=13; // this servo is on PWM Pin1
servos[13].functionnumber=13;
servos[13].stimer=5;
servos[14].angle=143;
servos[14].offangle=143;
servos[14].onangle=123;
servos[14].servo=14; // This is the same PWM Pin as the servo above, but this are the to other angles
servos[14].functionnumber=14;
servos[14].stimer=5;
servos[15].angle=121;
servos[15].offangle=142;
servos[15].onangle=121;
servos[15].servo=15; // this servo is on PWM Pin1
servos[15].functionnumber=15;
servos[15].stimer=5;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// A servo is coupled to an accessory[n]. It rotates based on accessory[n].output = 1 or 0
// If you have multiple servos you need to couple them to different accessories. However ...
// accessories may switch the same output pin (e.g. pin 13, which has the on board led attached)
} // END ConfigureDecoderServos
/////////////////////////////////////////////////////////////////////////////////////////
// DCC packet handler
/////////////////////////////////////////////////////////////////////////////////////////
void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
{
// Convert NMRA packet address format to human address
address -= 1;
address *= 4;
address += 1;
address += (data & 0x06) >> 1;
boolean enable = (data & 0x01) ? 1 : 0;
for(int i=0; i<maxservos; i++)
{
if(address == accessory[i].address)
{
if (enable)
{
if (accessory[i].output != 1)accessory[i].change = 1;
accessory[i].output = 1;
}
else
{
if (accessory[i].output != 0)accessory[i].change = 1;
accessory[i].output = 0;
}
if (accessory[i].address != lastaddr) accessory[i].change = 1;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup (run once)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);
ConfigureDecoderFunctions();
ConfigureDecoderServos();
DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );
pinMode(2,INPUT_PULLUP); //Interrupt 0 with internal pull up resistor (can get rid of external 10k)
//pinMode(A5,INPUT_PULLUP); //If made LOW, all servos go to their min angle, to avoid jitter at starup. - Not to use with PWM Servoshield because it uses already pinMode A5
pinMode(13,OUTPUT);
digitalWrite(13,LOW); //switch off Arduino led at startup
Serial.begin(9600);
pwm.begin();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates ( false freq setting may destroy your servo ! ) IMPORTANT!!!!!!!
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
for (int n=0; n<maxservos; n++)
{
pinMode(accessory[n].outputPin,OUTPUT); //Set accessory pins to OUTPUT mode
servos[n].onangle = map(servos[n].onangle,0,180,SERVOMIN,SERVOMAX); // Adjust the angles to the range given by Servomin and Servomax
servos[n].offangle = map(servos[n].offangle,0,180,SERVOMIN,SERVOMAX);
servos[n].angle = map(servos[n].angle,0,180,SERVOMIN,SERVOMAX);
pwm.setPWM(servos[n].servo, 0, servos[n].angle); // Set Servos to angle at startup
servos[n].suptimer = millis() + servos[n].stimer; // Set the individuel servotimers on startup
accessory[n].output = 3; // internal use, functionchange is acitvated for initial startup
}
yield();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main loop (run continuous)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
static int addr = 0;
DCC.loop(); // DCC library
if( ++addr >= maxservos ) addr = 0; // Next address to test
// Set accessory output pin
if (accessory[addr].change == 1)
{
if (accessory[addr].output)
{
digitalWrite(accessory[addr].outputPin, HIGH);
}
else
{
digitalWrite(accessory[addr].outputPin, LOW);
}
}
// Every 'servotimer' ms, modify setpoints and move servos 1 step (if needed)
if (millis() > timetoupdatesetpoint)
{
timetoupdatesetpoint = millis() + servotimer;
for (int n=0; n<maxservos; n++)
{
if (millis() > servos[n].suptimer)
{
if (accessory[servos[n].functionnumber].change == 1)
{
if (accessory[servos[n].functionnumber].output) servos[n].setpoint=servos[n].onangle;
else servos[n].setpoint=servos[n].offangle;
if (servos[n].angle < servos[n].setpoint) servos[n].angle++;
if (servos[n].angle > servos[n].setpoint) servos[n].angle--;
if (servos[n].stimer==0)servos[n].angle=servos[n].setpoint;
pwm.setPWM(servos[n].servo, 0, servos[n].angle);
servos[n].suptimer = millis()+ servos[n].stimer;
if (servos[n].angle == servos[n].setpoint)
{
Serial.println("Weiche wurde gestellt!");
Serial.println(servos[n].setpoint);
lastaddr = accessory[n].address;
for (int k=0; k<maxservos; k++)
{
if (servos[k].servo == servos[n].servo)
{
servos[k].angle=servos[n].setpoint;
}
}
accessory[servos[n].functionnumber].change = 0;
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Move all servos to min position and set all function outputs to 0, to eliminate startup servo jerk current draw
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//if (digitalRead(A5)==LOW) {for (int n=0; n<maxservos; n++) accessory[n].output = 0;} - Not to use with PWM Servoshield because it uses already pinMode A5
} //END MAIN LOOP
