Roco Multimaus

Hallo zusammen. ich versuche seit zwei Tagen einen Weichendecoder zu bauen. Leider will das nicht so wie es soll.

Als Library neme ich "NmraDcc" und das Beispielprogramm "Decoder_10Serv_7LED_4Function".

Hat da jemand Erfahrung mit gesammelt und kann mir ein paar Tipps geben.

Gruß Kalli

Kally: Hat da jemand Erfahrung mit gesammelt und kann mir ein paar Tipps geben.

Mit Erfahrungen kann ich zwar nicht dienen, aber mit einem Tipp: Du solltest noch Deinen Code und ggf. die Schaltung mitteilen. Dann kann Dir garantiert geholfen werden.

Gruß

Gregor

Kally:
Als Library neme ich “NmraDcc” und das Beispielprogramm “Decoder_10Serv_7LED_4Function”.

Hat da jemand Erfahrung mit gesammelt und kann mir ein paar Tipps geben.

Bitte poste den Link zur Library und den verwendeten Sketch hier im Forum.
Code-Tags verwenden.

Dann können wir sicher schneller helfen.

Verwende dazu die Schaltfläche </> oben links im Editorfenster.
Das kannst du auch nachträglich machen.
Dazu den Sketch markieren und die Schaltfläche klicken.

Damit wird dieser für alle besser lesbar.

Kally: Hallo zusammen. ich versuche seit zwei Tagen einen Weichendecoder zu bauen. Leider will das nicht so wie es soll.

Als Library neme ich "NmraDcc" und das Beispielprogramm "Decoder_10Serv_7LED_4Function".

Hat da jemand Erfahrung mit gesammelt und kann mir ein paar Tipps geben.

Gruß Kalli

Hallo Kalli, Die nmraDcc-Lib kenne ich eigentlich ganz gut. Ich habe damit auch mal einen Zubehördecoder erstellt, was gut funktioniert hat. Aber Du solltest schon etwas genauer schreiben, wo deine Probleme liegen. Wie bringst Du denn das DCC-Signal an den Arduino? Gruß Franz-Peter

Danke für die Antworten.

Ich benutze die nmraDcc Library.

Das Demoprogramm mit dem ich teste:

// 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];

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, 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
...
  {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
...
         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);

}

Der Code ist an einigen Stellen gekürzt.

Das Signal kommt nach der Schaltung im Anhang an den Arduino.

Als This_Decoder_Address ist 24 eingestellt. Ist das dann die Adresse für den ersten Ausgang? Bzw plus die Mulitimaus üblichen vier = 28.

Oder hab ich da den total falschen Ansatz?

Gruß
Kalli

Eingang.JPG

Hallo Kalli, dein Hauptproblem scheint mir die Optokopplerschaltung zu sein. Der PC817 ist zu langsam für das DCC-Signal. Eigentlich alle Schaltungen im Netz benutzen die 6N137, hier ist ein Beispiel. Den PC817 könntest Du für die Rückmeldung zum Auslesen der CV-Werte verwenden ( oberer Teil im Beispiel ). Aber das geht mit der Multimaus ja eh nicht ( und ist in Geoff Bunzas Beispiel auch nicht enthalten ). Vielleicht geht es, wenn Du den Collectorwiderstand am Optokoppler deutlich verkleinerst, aber der 6N137 ist die saubere und zuverlässige Lösung.

Du hast auch einen recht alten Stand des Sketches von Geoff. In den Beispielen der aktuellen Lib-Version ist er da schon bei V5.4. Unabhängig davon sollte sein Sketch aber schon funktionieren.

Hallo Franz-Peter,
der Hinweis auf einen kleineren Widerstand war gut. Ich hatte noch eine Stange mit den PC827 in der Schublade. Durch den kleineren Widerstand sind die Impulse nach dem Optokoppler schon besser. Da werd ich mal ein paar 6N137 mitbestellen. Dann kann auch der SN7414 entfallen.

Danke und Gruß

Kalli

Kally:
Durch den kleineren Widerstand sind die Impulse nach dem Optokoppler schon besser.

Hallo Kalli,
Kommt denn jetzt im Sketch auch was an oder hast Du das nur mit einem Oszi gemessen?
Franz-Peter

Hallo Franz-Peter, deine Programme funktionieren fehlerfrei. Ich versuche nun das ganze zu verstehen. Die 'alten' Demoprogramme aus der Nmra-Lib funktionieren nicht. Vielleicht vertragen sich die alten programme nicht mit der neueren Library?

Gruß Kalli

Kally: deine Programme funktionieren fehlerfrei.

Hallo Kalli, welche Programme meinst Du? Die Beispiele in der aktuellen nmraDcc sind immer noch von Geoff ;)

Kally: Vielleicht vertragen sich die alten programme nicht mit der neueren Library?

jetzt wo Du's sagst... wenn ich mich recht entsinne, gab's vor längerem mal eine inkompatible Änderung in der Schnittstelle zu einem Callback-Aufruf. Müsste ich mal nachforschen. Dürfte so ca. 1-2 Jahre her sein, und da dein obiges Beispiel ja von 2014 ist, könnte das durchaus damit zusammenhängen.