#include <NmraDcc.h>
#include <MobaTools.h>
#include <EEPROM.h>
// Demo: ein ganz einfacher Dcc-Servodecoder //
//------------------------------------------ //
// die NmraDcc - Library gibt es unter https://github.com/mrrwa/NmraDcc/archive/master.zip
// anzupassende Konstante:
const byte isROCO = 0 ; // wegen unterschiedlicher Weichenadressberechnung bei Roco (sonst = 0)
const byte weichenAdr[] = { 235, 235, 252, 252, 251, 251, 234, 234}; // DCC-Weichenadressen
const byte servoPins[] = { 3, 4, 5, 6, 7, 8, 9, 10}; // output-pin der Servos
const int geradePulse[] = {1320,1300,1320,1300,1380,1120,1300,1250}; // Pulslänge geradeaus
const int abzweigPulse[]= {1580,1680,1580,1600,1650,1550,1600,1660}; // Pulslänge abzweigend
const int speed = 8;
const byte autoOff = 1;
const byte ServoZahl = sizeof(weichenAdr);
Servo8 weicheS[ServoZahl];
NmraDcc Dcc;
///////////////////////////////////////////////////////////////
void setup() {
Dcc.pin(digitalPinToInterrupt(2), 2, 1); // Dcc-Signal an Pin2 ( = Int0 );
Dcc.init( MAN_ID_DIY, 15, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, 0 );
for ( byte i=0; i<ServoZahl; i++ ) {
int inipos;
// Weichenservos initiieren
weicheS[i].attach( servoPins[i], autoOff );
weicheS[i].setSpeed( speed );
EEPROM.get(i*2, inipos ); // letzten gespeicherten Wert aus dem EEPROM lesen
inipos = constrain( inipos, 600, 2500 ); // auf gültige Werte begrenzen
weicheS[i].write( inipos ); // Servo dorthin fahren ( sollte bereits da stehen )
}
}
////////////////////////////////////////////////////////////////
void loop() {
Dcc.process(); // Hier werden die empfangenen Telegramme analysiert
const byte isROCO = 4 ; // wegen unterschiedlicher Weichenadressberechnung bei Roco (sonst = 0)
}
//////////////////////////////////////////////////////////////
// Unterprogramme, die von der DCC Library aufgerufen werden:
// Die folgende Funktion wird von Dcc.process() aufgerufen, wenn ein Weichentelegramm empfangen wurde
//void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State ){
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t OutputAddr, uint8_t OutputPower ) {
// Weichenadresse berechnen
word wAddr = Addr+isROCO; // Roco zählt ab 0, alle anderen lassen die ersten 4 Weichenadressen frei
// Testen ob eigene Weichenadresse
for ( byte i = 0; i < ServoZahl; i++ ) {
if ( wAddr == weichenAdr[i] ) {
// ist eigene Adresse, Servo ansteuern
if ( OutputAddr & 0x1 ) {
weicheS[i].write( geradePulse[i] );
EEPROM.put(i*2,geradePulse[i]);
} else {
weicheS[i].write( abzweigPulse[i] );
EEPROM.put(i*2,abzweigPulse[i]);
}
//break; // Schleifendurchlauf abbrechen, es kann nur eine Weiche sein
}
}
}