/**************************************************************************************************
* DCC Signaldecoder & Schaltdecoder
*
* DCC Verarbeitung by https://pgahtow.de/w/DCC_Dekoder
*
*==========================================================================================
* 3 Einzelsteuerungen (Wartezeit Zufall zwischen T-Min und T-Max
* ----------------------------------------------------------------
* Port D3-D6: DCC +0 - +3 Akt/dekativ (Funktion ein/aus)
* +4 - +7 (ausgelöst)
*
*==========================================================================================
* GBHF-Steuerung (3-Gleise)
* ----------------------------------------------------------------
* +8 Akt/dekativ (Funktion ein/aus)
* Port D7-D9: DCC +9 - +11 Akt/dekativ Gleis1-3
* +12 - +14 (ausgelöst)
* +15 (SHBF-In)
* +16 (Belegung Rangiergleis BHF1_R)
*
*
* ║ ╔════GBHF1════════
* ║ ╠════GBHF2════════
*
*
*==========================================================================================
* Zufallssteuerung
* ----------------------------------------------------------------
* Port D10: DCC +17 Akt/dekativ (Funktion ein/aus)
*************************************************************************************************/
//include the library code:
#include <EEPROM.h>
#include <TimerOne.h>
//-----------------------------------------------------------------------------------
// IO-Ports
//-----------------------------------------------------------------------------------
const int dccPin = 21;
#define TimerPort0 3
#define TimerPort1 4
#define TimerPort2 5
#define TimerPort3 6
#define TimerPort4 7
#define TimerPort5 8
#define TimerPort6 9
#define TimerPort7 10
#define Led_test 12
#define Led_konfig 11
#define Taster_learn A0
//---------------------------------------------------------------------------------------------------------------
//Serial.read()
//---------------------------------------------------------------------------------------------------------------
char buffer[50];
byte b;
String serialBefehl;
int serialWert1;
int serialWert2;
byte serialEmpfang = 0;
;
//Befehlsname, Sprungadresse
String BefehlDB[10][3] = {{"?","255",""},
{"t_min","100"," :<0-7>-<0-250>"},
{"t_max","101"," :<0-7>-<0-250>"},
{"t_opt","102"," :<0-7>-<0-250>"},
{"t_verz","103"," :<0/1>"},
{"t_st","104",""},
{"test","200"," :<0-7>-<>"},
{"dcc","180"," <adr>:<1/0>"},
{"dcc_adr","181"," <500-2000>"},
{"dcc_st","182",""},
};
int BefehlDBLength = sizeof(BefehlDB)/sizeof(BefehlDB[0])-1;
//-----------------------------------------------------------------------------------
//Variablen für DCC Erkennung
//-----------------------------------------------------------------------------------
int countone = 0; //Zähle die high so das man eine Präambel erkennen kann (min. 10 high)
boolean getdata = false; //Es werden DCC Daten gelesen und im Array data abgespeichert
boolean dataReady = false; //Es wurden DCC Daten vollständig eingelesen
byte data[20]; //eingelesene Byte-Werte nach einer Präambel
byte datalength = 0; //Position in data wo gerade der nächste Wert hinkommt
byte countbit = 0; //Zähle Bits, nach 8 Bit wurde ein Byte gelesen und setzte dann die Variable auf 0
byte dxor = 0; //xor Prüfsumme
int dccAdr = 0; //Adresse
byte dccZustand; //0:aus, 1: aktiv
byte dccType = 0xFF; //Art der DCC Daten (Long, Short, Accessory)
int DCC_Portadressen[20]; //Adressenspeicher
int dcc_wh; //Hilfsvariable um DCC-wiederholungen zu unterdrücken
//---------------------------------------------------------------------------------------------------------------
//Timer (über Millis)
//---------------------------------------------------------------------------------------------------------------
unsigned long timer_01;
long ueberlauf;
uint16_t timerIntervall_01 = 100; // 1/10 Sekunde
int TimeOut[10]; //Timeouttabelle [Dauer in 1/10 Sekunden]
//---------------------------------------------------------------------------------------------------------------
//Betrieb
//---------------------------------------------------------------------------------------------------------------
byte BetriebsMode; // 0: Betrieb; 1:Learning DCC-Adressen; 2:Learning Lautstärke
//---------------------------------------------------------------------------------------------------------------
uint16_t LED_DB[10][4]; //Beschreibung siehe: LED_Steuerung()
byte Tasten_DB[10]; //Beschreibung siehe: Auswertung_Taster_Eingaben()
byte TimerKonfigDB[8][6];
/*
* TimerKonfigDB[8][6]
* | |--- Wartezeit : [][0]:Min, [][1]:Max, [][2]:opt, [][3]:Verzögerter Start (nein/ja), [][4]:akt/deAkt/gesperrt, [][5]:ausgelöst (aktion)
* |-------[PortNummer]: 0-7 | | |--- Wenn Zug in BHF einfährt tmp-gesperrt für "DCC_Verarbeiten_Gleis_Zufall()""
* | |--------- Sperre für "DCC_Verarbeiten_Gleis_Zufall()""
* |<-------------- Berücksichtigen bei "DCC_Verarbeiten_Gleis_Zufall()"
* |
* |----------------Belegt/frei Port 4-6
*
* Port: 0-3
* Port: 4: GBHF1
* Port: 5: GBHF2
* Port: 6: LS
*/
;
byte GleisAlt=0; //Letzte ausgewälte Gleis
bool ZugAktiv=0; //Globale Variable ob Funktion ein/aus
/***************************************************************************************
* Setup
*************************************************************************************/
void setup(){
//*** Konfig-Start ******************************************
DCC_Portadressen[0] = 2044; //Test-LED
//**** Konfig Ende ******************************************
;
Serial.begin(9600);
;
//Pinmodes
pinMode(TimerPort0, OUTPUT);
pinMode(TimerPort1, OUTPUT);
pinMode(TimerPort2, OUTPUT);
pinMode(TimerPort3, OUTPUT);
pinMode(TimerPort4, OUTPUT);
pinMode(TimerPort5, OUTPUT);
pinMode(TimerPort6, OUTPUT);
pinMode(TimerPort7, OUTPUT);
pinMode(Led_test, OUTPUT);
pinMode(Led_konfig, OUTPUT);
;
//Daten von EEProm einlesen
loadfromEeprom();
//Interrupt
//attachInterrupt(0, dccdata, RISING); //ISR für den Dateneingang
// ;
//Timer1 zum bestimmen der Impulslängen des DCC Signals
Timer1.initialize(70); // set a timer of length 70 microseconds
Timer1.attachInterrupt(dcctime); // attach the service routine here
Timer1.stop(); // Timer anhalten
//Init fertig
Serial.println(" DCC-Timerdecoder x8");
;
LED_Setzen(8,6,0,0);
LED_Setzen(9,6,0,0);
}
/*************************************************************************************
* Loop
*************************************************************************************/
void loop(){
;
//DCC-Auswertung ------------------------
if(dataReady == true){
dccauswertung(); //eingelesene Daten auswerten
if(BetriebsMode == 0){DCC_Bewertung();} //Ports schalten();
//if(BetriebsMode == 1){DCC_AdressenLernen();} //Lernen der DCC-Adressen;
dataReady = false;
}
//Zyklische Routinen
Auswertung_Serielle_Eingaben();
//Timersteuerung
ueberlauf = millis()- timer_01;if (millis()- timer_01 > timerIntervall_01 || ueberlauf < 0){timer_01 = millis();Timer_01sek();}
}
/*****************************************************************************************
* Tasterabfrage
*****************************************************************************************/
void Auswertung_Taster_Eingaben(){
/*
* [0]= Tastentimeout
* [1]= Nr der gedrückten Taste (1: Adresse lernen; 2=laut, 2=leise)
*/
byte tastentimeout= 5; // enstprich ? x 10 ms
;
byte T_learn = analogRead(Taster_learn);
;
if(Tasten_DB[0]==0){
if(T_learn > 100){
Tasten_DB[0]=tastentimeout;
Tasten_DB[1]=3;
}
Bewertung_Taster_Eingaben();
}
}
void Bewertung_Taster_Eingaben(){
/*
* Bwerten der Drei Tastereingaben
*/
//Taster Adresse lernen
if(Tasten_DB[1]==3 && BetriebsMode==0){
Serial.println("> DCC-lernen");
LED_Setzen(9,3,0,0); //Blinken: test-LED
TimeOut[1] = 100; //Timeout 10Sekunden
BetriebsMode=1;
Tasten_DB[0]=0;
}
;
Tasten_DB[1]=0;
}
/*****************************************************************************************
* Serielle Eingaben
****************************************************************************************/
void Auswertung_Serielle_Eingaben(){
/*
* Abfrage Serielles Interface
* Struktur: "BEFEHL", Trennzeichen=':' ", WERT, Beispliel "Servo1Low:40"
*
*/
if (Serial.available()){
;
int ascii = Serial.read();
;
//Befehl & Werte
if(ascii != 10 && ascii != 58){
buffer[b] = ascii;
b++;
;
if(serialEmpfang==0){
serialBefehl = buffer;
}
;
if(serialEmpfang==1){serialWert1 = atoi(buffer);}
if(serialEmpfang==2){serialWert2 = atoi(buffer);}
}
;
//Trenner ":"
if(ascii == 58){
serialEmpfang = 1;
memset(buffer, 0, sizeof(buffer)); b=0;
}
//Trenner "-"
if(ascii == 45){
serialEmpfang = 2;
memset(buffer, 0, sizeof(buffer)); b=0;
}
;
//Verarbeitung nach CR
if(ascii == 10){
;
//Clear Eingabe
memset(buffer, 0, sizeof(buffer)); b=0;
serialEmpfang = false;
;
Bewertung_Serielle_Eingaben();
}
}
}
void Bewertung_Serielle_Eingaben(){
/*
*
*/
//Serial.println("Eingabe: " + String(serialBefehl) + " <> " + String(serialWert1) + "-" + String(serialWert2));
//Serial.println("Länge BefehlDB: " + String(BefehlDBLength));
//Serial.println("gefunden: "+String(gefunden));
//Suche Befehl in der DB
byte gefunden=0;
for(byte z=0;z<=BefehlDBLength;z++){
if(serialBefehl == BefehlDB[z][0]){
gefunden=(BefehlDB[z][1]).toInt();
}
}
//Einträge KonfigDB
if(gefunden >= 100 && gefunden <=103){
//Verifizierungsprüfung
bool pruefungOK=true;
if(serialWert2 > 254 && gefunden != 103){pruefungOK=false;}
if(serialWert2 > 1 && gefunden == 103){pruefungOK=false;}
if(serialWert1 > 7) {pruefungOK=false;}
;
if(pruefungOK == false){
Serial.println("Fehler");
}else{
TimerKonfigDB[serialWert1][gefunden-100] = serialWert2;
PrintTimerKonfigDB();
saveKonfigToEeprom();
;
}
}
//Print TimerKonfigDB
if(gefunden == 104){PrintTimerKonfigDB();}
//DCC Direkteingabe
if(gefunden == 180){
dataReady = true;
dccAdr = serialWert1;
dccZustand = serialWert2;
}
//DCC-Adresse
if(gefunden == 181){
//Verifizierungsprüfung
bool pruefungOK=true;
if(serialWert1 < 500 ||serialWert1 > 2000){pruefungOK=false;}
;
if(pruefungOK == false){
Serial.println("Fehler");
}else{
DCC_Portadressen[1]=serialWert1;
saveDccToEeprom();
loadfromEeprom();
PrintDccAdr();
}
}
//Einträge KonfigDB
if(gefunden == 200){
//Verifizierungsprüfung
bool pruefungOK=true;
if(serialWert1 > 7) {pruefungOK=false;}
;
if(pruefungOK == false){
Serial.println("Fehler");
}else{
LED_Setzen(serialWert1, 6, 0, 0);
}
}
//DCC-Status
if(gefunden == 182){PrintDccAdr();}
//Sonstige Befehle
if(gefunden == 0){Serial.println("???");}
if(gefunden == 255){printBefehle();}
serialWert1 = -1;
serialWert2 = -1;
}
/*****************************************************************************************
* DCC-Auswerten
/****************************************************************************************/
void dccdata() {
Timer1.start(); //Timer starten
}
void dcctime(){
Timer1.stop(); //Timer anhalten
int State = digitalRead(dccPin);
if (getdata == true) {
countbit += 1; //Abzählen der Bytes, also jeweils 8 Bit
}
;
if (State == LOW){ //1-Bit gelesen
countone += 1; //Zählen der 1-Bit für Präambel erforderlich
if (getdata == true && countbit <= 8){ //eingelesenen Bitwert im Array Speichern
bitWrite(data[datalength], 8-countbit, 1); //Speichert das ein 1-Bit gelesen wurde
}
if (countbit > 8) { //End-Bit gelesen.
countbit = 0;
getdata = false; //Stop des Einlesen der Daten
//XOR Prüfen:
if (data[datalength] != dxor) //Prüfen von XOR und letztes Byte
return; //verwerfen!
while (datalength < 4) { //Löschen des leeren Bereichs am Ende
datalength++;
data[datalength] = 0;
}
dataReady = true; //Fertig, Daten Auswerten!
}
} //Ende 1-Bit
else{ //0-Bit gelesen
if (getdata == true && countbit <= 8) { //eingelesenen Bitwert im Array Speichern
bitWrite(data[datalength], 8-countbit, 0); //Speichert das ein 0-Bit gelesen wurde
}
if (countone > 10){ //Präambel erkannt ab hier Daten lesen. (Es wurden mind. 10 HIGH erkannt)
getdata = true; //Einlesen der Bitwerte in Array aktivieren.
datalength = 0; //Position im Array an der die Bitwerte gespeichert werden.
countbit = 0; //beginne Bits zu zählen. Auswertung von 1 Byte Blöcken ermöglichen nach 8 Bit.
dxor = 0; //XOR zurücksetzten
}
if (countbit > 8){ //Null-Bit gelesen. (Immer nach 1 Byte)
countbit = 0;
dxor = dxor ^ data[datalength]; //XOR bestimmen!
datalength += 1; //Bitweise im Array weitergehen.
}
countone = 0; //Es wurde ein 0-Bit gelesen, lösche Anzahl gelesener 1-Bit
} //Ende 0-Bit
}
void dccauswertung() {
//für Schaladressen: 1-2044
if ((data[0] >> 6 == B10) && (data[1] >> 7 == 1)) {
//1. Adressteil
byte dccAdr1 = data[0] & B00111111;
;
//2. Adressteil
byte dccAdr2 = (data[1] & B00000110) >> 1;
;
//3. Adressteil
int dccAdr3 = (data[1] & B01110000) >> 4;
dccAdr3 = (7-dccAdr3)*256
;
//Summe
dccAdr = (dccAdr1-1)*4 + dccAdr2+1 + dccAdr3; //Adresse in 4er Blöcken
;
//DCC: Ein oder Ausschalten
dccZustand = 0;
if(data[1] & B1 == 1){dccZustand = 1;}
}
}
/*****************************************************************************************
* DCC-Bewertung
/****************************************************************************************/
void DCC_AdressenLernen(){
/*
* lernen der DCC Adresse
* 1. ankommende Adresse + 3 weitere nach DCC_Portadressen[1 bis 4]
* Adresse mus kleiner als 2039 sein
*/
BetriebsMode=0;
;
if(dccAdr > 2000 || dccAdr <= 500){
//Serial.println("Lerne DCC-Adresse: " + String(dccAdr));
DCC_Portadressen[1] = dccAdr;
PrintDccAdr();
saveDccToEeprom();
loadfromEeprom();
}else{
Serial.println("Fehler: Adr-Bereich 500-2000");
}
}
void DCC_Bewertung(){
/*
* Releais und Ports ein / Aus-Schalten
*/
//Serial.println("--------------------------------");
//Serial.println("DCC-Adresse: " + String(dccAdr) +" dccZustand: " + String(dccZustand));
;
bool dcc_unb=true;
for(byte z=0;z<=39;z++){
if(dccAdr == DCC_Portadressen[z]){
DCC_Verarbeiten(z, dccZustand);
dcc_unb=false;
}
}
if(dcc_unb==true){Serial.println("Unb. DCC-Adr.: " + String(dccAdr));}
}
void DCC_Verarbeiten(byte Nr, byte Zustand){
/*
*
* Port 0:
* DCC+0: Start: Wartezeit Zufall zwischen T_min und T_Max, oder bei Verzögert=0, Zufall=0
* DCC+4: Auslösung durch (Rocrail-Aktion), Warteueit Zufall ufall zwischen T_min und T_Max
*
* Weitere Port 1,2,3: "DCC+1 & +5", "DCC+2 & +6", "DCC+3 & +7"
*
*-------------------------------------------------------------------------------------
* Port 4-6
* Port 4-6: Zufallswartezeit und Zufallssauswahl des Ports, Berücksichtigung SBHF-in/Out
* +8 , bzw. Nr. 9: Akt/dekativ (Funktion ein/aus)
* DCC +9 - +11 10-12: belegt/frei Gleis 1-3
* +12 - +14 13-15: (ausgelöst) durch Aktion, Gleis 1-3
* +15 , bzw. Nr. 16: (SHBF-In)
* +16 17: (BHF1_R)
*-------------------------------------------------------------------------------------
* Port 7
*/
;
;
//um DCC-Wiederholungen vermeiden, Hilfsformel: "Nr+Nr*(Zustand+3)"; ist eine willkürliche formel für eine eindeutige ID
bool dcc_widerholungen=false;
if(dcc_wh == Nr+(Nr+1)*(Zustand+3)){dcc_widerholungen=true;}
dcc_wh = Nr+(Nr+1)*(Zustand+3);
TimeOut[2] = 10; //Timeout 1Sekunden
;
if(dcc_widerholungen==false){
//Serial.println("Schalte Nr: " + String(Nr) + ", DCC-Adresse: " + String(dccAdr) +" in " + String(Zustand));
//Test-LED
if(Nr == 0){digitalWrite(Led_test,Zustand);} //TestLED
if(Nr>= 1 && Nr<= 8){DCC_Verarbeiten_timer_1(Nr, Zustand);}
if(Nr>= 9 && Nr<= 17){DCC_Verarbeiten_timer_2(Nr, Zustand);}
if(Nr== 18 ){DCC_Verarbeiten_timer_3(Nr, Zustand);}
}else{
Serial.println("W.H.Befehl");
}
}
//↓↓↓↓ Timer Verarbeitungroutinen ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
void DCC_Verarbeiten_timer_1(byte Nr, byte Zustand){
/*
* Beschreibung
* DCC +0 - +3, bzw. Nr: 1-4 => Aktiv / Deakiv (Port 0-3)
* DCC +4 +7, bzw. Nr: 5-8 => bewerten ob Verzögert oder nicht => ausgelöst
*/
//Serial.println("Nr: " + String(Nr) + ":"+ String(Zustand));
//deaktivieren (Funktion)
if(Nr<=4 && Zustand==0){
TimerKonfigDB[Nr-1][4] = 0; //Deaktiv setzen
}
;
byte Wartezeit;
bool ausfuehren=false;
//aktiviern (Funktion)
if(Nr<=4 && Zustand==1){
TimerKonfigDB[Nr-1][4] = 1; // aktiv setzen
Wartezeit=0;
//Verzoegerter Start
if(TimerKonfigDB[Nr-1][3]==1){
Wartezeit = DCC_Verarbeiten_Zeit_Zufall(TimerKonfigDB[Nr-1][0], TimerKonfigDB[Nr-1][1]);
ausfuehren=true;
}
}
//Ausgelöst (Aktion)
if(Nr>=5 && Zustand==1 && TimerKonfigDB[Nr-5][4] == 1){
Wartezeit = DCC_Verarbeiten_Zeit_Zufall(TimerKonfigDB[Nr-5][0], TimerKonfigDB[Nr-5][1]);
dcc_wh = 0;
Nr=Nr-4;
ausfuehren=true;
}
//Port auslösen
if(ausfuehren==true){
LED_Setzen(Nr-1, 6, 0, Wartezeit);
Serial.println("LED-Warte: "+String(Nr)+":"+String(Wartezeit));
}else{
//Serial.println("...");
}
}
void DCC_Verarbeiten_timer_2(byte Nr, byte Zustand){
bool Gleissuche=false;
;
//Start (DCC+8)
if(Nr==9){
if(Zustand==1){Gleissuche=true;}
GleisAlt=0;
ZugAktiv=Zustand;
}
;
//Setzen der Gleisstati durch DCC
if(Nr>=10 && Nr <=12){
byte Gleis=Nr-9;
TimerKonfigDB[Gleis+3][4] = Zustand;
}
;
//Nur im Aktivem Zustand
if(ZugAktiv==1){
;
//Bewerten der Ausgelösten Kontakte
if(Nr>=13 && Nr <=15){
byte Gleis=Nr-12;
if(GleisAlt != 0){TimerKonfigDB[GleisAlt+3][4] = 0;}
TimerKonfigDB[Gleis+3][4] = 1;
Gleissuche=true;
}
;
//Bewerten SB_IN
if(Nr==16){
byte Gleis=Nr-15;
if(GleisAlt != 0){TimerKonfigDB[GleisAlt+3][4] = 0;}
Gleissuche=true;
}
//Bewerten BHF1_R
if(Nr==17){
byte Gleis=Nr-15;
//Prüfen ob beide Gleise im GBHF belegt sind
byte GBHF1=TimerKonfigDB[5][4];
byte GBHF2=TimerKonfigDB[6][4];
//nur wenn beide belegt sind
if(GBHF1==1 && GBHF2==1){
//Freigeben GBHF1 (ohne Gleissuche)
}
}
;
//Suche neues Gleis und ermittle die Wartezeit
if(Gleissuche==true){
byte Gleis = DCC_Verarbeiten_Gleis_Zufall();
;
//Wartezeit
byte Wartezeit;
if(Gleis > 0){
Wartezeit = TimerKonfigDB[Gleis+3][2];
if(Gleis != GleisAlt){Wartezeit = DCC_Verarbeiten_Zeit_Zufall(TimerKonfigDB[Gleis+3][0], TimerKonfigDB[Gleis+3][1]);}
;
//Gleise setzen
TimerKonfigDB[Gleis+3][4]=1;
GleisAlt = Gleis;
;
//Port ansteuern
LED_Setzen(Gleis+3, 6, 0, Wartezeit);
;
Serial.println("Gleis: " + String(Gleis)+ " Wartezeit: "+ String(Wartezeit));
}
}
}
}
void DCC_Verarbeiten_timer_3(byte Nr, byte Zustand){
}
//↑↑↑↑ Timer Verarbeitungroutinen ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
byte DCC_Verarbeiten_Zeit_Zufall(byte Wert1, byte Wert2){
/*
* Zufallzeit auswählen
*/
byte Ergebnis=random(Wert1, Wert2+1);
return Ergebnis;
}
byte DCC_Verarbeiten_Gleis_Zufall(){
/*
* Zufallsgleis Auswählen
*/
byte Ergebnis=0;
bool weiter = false;
byte counter;
;
//Prüfen ob Gleise belegt sind
if(TimerKonfigDB[4][4]!=0 || TimerKonfigDB[5][4]!=0 || TimerKonfigDB[6][4]!=0){
do{
byte zufall= random(1, 4);
if(TimerKonfigDB[3+zufall][4] == 1 ){
//Wichtung GlasAlt 1 zu 3
if(zufall==GleisAlt){counter++;}
;
if(zufall == GleisAlt && counter==2){weiter=true; Ergebnis=zufall;}
//Neues Gleis
if(zufall != GleisAlt){weiter=true; Ergebnis=zufall;}
}
} while (weiter==false);
}
return Ergebnis;
}
/*****************************************************************************************
* LED-Steuerung
*****************************************************************************************/
/*
* Modus 0: ignore
* Modus 1: aus
* Modus 2: an
* Modus 3: blink Slow
* Modus 4: blink fast
* Modus 5: Once
* Modus 6: Once lang
* Modus 7: Count
*
* LED-NR 0: TimerPort0
* NR 1: TimerPort1
* NR 2: TimerPort2
* NR 3: TimerPort3
* NR 4: TimerPort4
* NR 5: TimerPort5
* NR 6: TimerPort6
* NR 7: TimerPort7
* NR 8: test
* NR 9: konfig
*/
byte Blink_slow=10;
byte Blink_fast=1;
byte Blink_once=5;
byte Blink_count=2;
byte Blink_once_lang=20;
void LED_Setzen(byte Nr, byte Modus, byte Count, byte Verzoegerung){
/*
* NR : Nr. der Led
* Modus: Siehe Liste
* COUNT: Nur bei Modus 7
* Verzögerung: in Sek-Schritten
*/
LED_DB[Nr][0] = Modus;
LED_DB[Nr][2] = Count;
LED_DB[Nr][3] = Verzoegerung * 10;
}
void LED_Steuerung(){
/*
* LED_DB(Nr,0) = Modus
* LED_DB(Nr,1) = Timer
* LED_DB(Nr,2) = Counter, Anzahl von wiederholungen
*/
for(byte Nr=0;Nr<=9;Nr++){
byte Modus = LED_DB[Nr][0];
byte LED_Timer = LED_DB[Nr][1];
byte LED_Count = LED_DB[Nr][2];
byte Verz = LED_DB[Nr][3];
;
//Verzoegerung bewerten
if(Verz >= 1){Verz--; LED_DB[Nr][3]--;}
//--AUS-------------------------------------------
if(Modus==1 && Verz==0){
LED_Schalten(Nr, 0);
LED_DB[Nr][0] = 0;
}
//--EIN-------------------------------------------
if(Modus==2 && Verz==0){
LED_Schalten(Nr, 1);
LED_DB[Nr][0] = 0;
}
//--BLINK SLOW-------------------------------------
if(Modus==3 && Verz==0){
if(LED_Timer==0){
LED_Timer=Blink_slow*2;
LED_Schalten(Nr, 1);
}
if(LED_Timer==Blink_slow){
LED_Schalten(Nr, 0);
}
LED_Timer--;
LED_DB[Nr][1] = LED_Timer;
}
//--BLINK fast-------------------------------------
if(Modus==4 && Verz==0){
if(LED_Timer==0){
LED_Timer=Blink_fast*2;
LED_Schalten(Nr, 1);
}
if(LED_Timer==Blink_fast){
LED_Schalten(Nr, 0);
}
LED_Timer--;
LED_DB[Nr][1] = LED_Timer;
}
//--BLINK Once-------------------------------------
if(Modus==5 && Verz==0){
if(LED_Timer==0){
LED_Timer=Blink_once;
LED_Schalten(Nr, 1);
}
if(LED_Timer==1){
LED_Schalten(Nr, 0);
LED_DB[Nr][0] = 0;
}
LED_Timer--;
LED_DB[Nr][1] = LED_Timer;
}
//--BLINK Once lang --------------------------------
if(Modus==6 && Verz==0){
if(LED_Timer==0){
LED_Timer=Blink_once_lang;
LED_Schalten(Nr, 1);
}
if(LED_Timer==1){
LED_Schalten(Nr, 0);
LED_DB[Nr][0] = 0;
}
LED_Timer--;
LED_DB[Nr][1] = LED_Timer;
}
//--BLINK Count-------------------------------------
if(Modus==7 && Verz==0){
if(LED_Timer==0){
LED_Timer=Blink_count*2;
LED_Schalten(Nr, 1);
}
if(LED_Timer==Blink_count){
LED_Schalten(Nr, 0);
LED_Count--;
}
if(LED_Count==0){LED_DB[Nr][0]=0;}
;
LED_Timer--;
LED_DB[Nr][1] = LED_Timer;
LED_DB[Nr][2] = LED_Count;
}
}
}
void LED_Schalten(byte Nr, bool status){
if(Nr==0 && status==0){digitalWrite(TimerPort0,LOW);} if(Nr==0 && status==1){digitalWrite(TimerPort0,HIGH);}
if(Nr==1 && status==0){digitalWrite(TimerPort1,LOW);} if(Nr==1 && status==1){digitalWrite(TimerPort1,HIGH);}
if(Nr==2 && status==0){digitalWrite(TimerPort2,LOW);} if(Nr==2 && status==1){digitalWrite(TimerPort2,HIGH);}
if(Nr==3 && status==0){digitalWrite(TimerPort3,LOW);} if(Nr==3 && status==1){digitalWrite(TimerPort3,HIGH);}
if(Nr==4 && status==0){digitalWrite(TimerPort4,LOW);} if(Nr==4 && status==1){digitalWrite(TimerPort4,HIGH);}
if(Nr==5 && status==0){digitalWrite(TimerPort5,LOW);} if(Nr==5 && status==1){digitalWrite(TimerPort5,HIGH);}
if(Nr==6 && status==0){digitalWrite(TimerPort6,LOW);} if(Nr==6 && status==1){digitalWrite(TimerPort6,HIGH);}
if(Nr==7 && status==0){digitalWrite(TimerPort7,LOW);} if(Nr==7 && status==1){digitalWrite(TimerPort7,HIGH);}
;
if(Nr==8 && status==0){digitalWrite(Led_test,LOW);} if(Nr==8 && status==1){digitalWrite(Led_test,HIGH);}
if(Nr==9 && status==0){digitalWrite(Led_konfig,LOW);} if(Nr==9 && status==1){digitalWrite(Led_konfig,HIGH);}
}
/*****************************************************************************************
* EEPromRoutinen
****************************************************************************************/
void loadfromEeprom(){
/*
* Adressbereiche:
* Adr 1 & 2 => DCC-Adresse
* Adr 10- => KonfigDB
*/
;
//Einlesen DCC-Adressen
byte HSB = EEPROM.read(1);
byte LSB = EEPROM.read(2);
for(byte z=1;z<=19;z++){DCC_Portadressen[z] = HSB*255+LSB+(z-1);}
//Einlesen KonfigDB
byte c=10;
for(byte z=0;z<=7;z++){
for(byte y=0;y<=4;y++){
byte wert = EEPROM.read(c);
if(wert==255){wert=1;}
if(y==4){wert=0;}
TimerKonfigDB[z][y]=wert;
c++;
}}
;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HSB=3;LSB=235;
for(byte z=1;z<=19;z++){DCC_Portadressen[z] = HSB*255+LSB+(z-1);}
TimerKonfigDB[0][0]=3;
TimerKonfigDB[0][1]=10;
TimerKonfigDB[4][0]=4;
TimerKonfigDB[4][1]=9;
TimerKonfigDB[4][2]=5;
}
void saveDccToEeprom(){
/*
* Schreiben der erlernten DCC Adressen
*/
byte HSB = DCC_Portadressen[1]/255;
byte LSB = DCC_Portadressen[1]-(HSB*255);
;
EEPROM.write(1,HSB);
EEPROM.write(2,LSB);
}
void saveKonfigToEeprom(){
/*
* Sichern
*/
byte c=10;
for(byte z=0;z<=7;z++){
for(byte y=0;y<=4;y++){
byte wert=TimerKonfigDB[z][y];
EEPROM.write(c,wert);
c++;
}}
}
/*****************************************************************************************
* Timer Routinen
*****************************************************************************************/
void Timer_01sek(){
/* Timeoutbearbeitung
* Ausführung bei 1, Unberücksichtigt bei 0
*
* TimeOut[1]: Learning Mode
* TimeOut[2]: dcc_wh=0
* TimeOut[3]:
*/
//Zyklische Routinen
LED_Steuerung();
Auswertung_Taster_Eingaben();
//TimeoutVerarbeitung
byte ToDo=0;
for(byte z=1;z<=3;z++){
if(TimeOut[z] >= 2){TimeOut[z]--;}
if(TimeOut[z] == 1){ToDo = z; TimeOut[z]=0;}
}
if(ToDo==1){LED_Setzen(9, 1,0, 0); BetriebsMode=0; Tasten_DB[0]=0; Serial.println("> DCC-lernen-Timeout");} //Taster Adresse Lernen gedrückt
if(ToDo==2){dcc_wh=0;}
if(ToDo==3){;}
}
/*************************************************************
* PrintRoutinen
************************************************************/
void printBefehle(){
Serial.println("Befehle: ");
for(byte z=0;z<=BefehlDBLength;z++){
String text = String(BefehlDB[z][0]) + ">" + String(BefehlDB[z][2]);
Serial.println(text);
}
}
void PrintDccAdr(){
String text = "DCC-Adr: " + String(DCC_Portadressen[0]);
text = text + " : " + String(DCC_Portadressen[1]) +"..."+String(DCC_Portadressen[1]+19);
Serial.println(text);
}
void PrintTimerKonfigDB(){
//Serial.println(" TimerKonfigDB: ");
Serial.println(" min-max-opt-vrz-AKT");
for(byte z=0;z<=7;z++){
String text = " > Port_" + String(z) + ": ";
for(byte y=0;y<=4;y++){
byte wert=TimerKonfigDB[z][y];
if(wert<100){text=text+" ";}
if(wert<10) {text=text+" ";}
text=text+String(TimerKonfigDB[z][y])+"|";
}
Serial.println(text);
}
}