Hallo Forum, ich lese hier schon ein paar Tage.
Aktuell bin ich dabei einen DCC Decoder auf Basis der NMRADCC Biblothek zu programmieren.
Das funktioniert eigentlich soweit, dass Problem ist nun, das ich ein Menü zur Einstellung der Paramter "bauen" möchte. Problem ist das einlesen von Zahlen über die Schnittstelle, ein einfaches "atoi" auf den gelesenen Wert reicht hier nicht, da wenn keine Umwandlung möglich ist, ja "0" zurück gegeben wird, dies wird aber auch für die Eingabe gebraucht.
Im Sketch ist aktuell das "void menue()" aktiv, eigentlich soll dann das noch nicht fertige "void menue_ori()" zum Menü werden.
Selbst die von der Arduino-Referenz Seite kopierte Funktion isDigit() bringt mich nicht weiter.
Noch eine Anmerkung: Die Adafruit_NeoPixel Biblothek ist zwar schon eingebunden, macht aber im Moment noch nichts, mir fehlt dafür noch die Hardware.
[code]
/*Steuerung für bis zu 4 Searlight Signale mit 2 Signalschirmen
Verwendet Adruino NANO Board V3 (neuer Boadloader)
Verwendete NmraDcc Bibliothek = 2.0.10
Verwendete Adafruit_NeoPixel Bibliothek = 1.10.4
Einstellungen über USB Schnittstelle über ARDUINO IDE (Baurate 115200)
® by Georg Hüsken 02.2022
*/
#include <Adafruit_NeoPixel.h>
#include <NmraDcc.h>
#include <EEPROM.h>
#define EESIZE 1024
typedef struct
{
int address;
uint8_t arduinoPin;
}
DCCAccessoryAddress;
NmraDcc Dcc;
uint16_t lastAddr = 0xFFFF;
uint8_t lastDirection = 0xFF;
byte SignalBefehl [4] = {0, 0, 0, 0};
byte Old_SignalBefehl [4] = {255, 255, 255, 255};
byte SignalTyp [4] = {0, 0, 0, 0}; // Wert = 0 = Main Signal Wert = 1 = Distanz Signal (Vorsignal nur ein Schirm)
byte SignalDimWert = 127; // In 0-255 entsprechend 0-100%, bei der Eingabe auf 40-200 Begrenzt
byte Signale = 4, Signal = 0, writeCVs = 0;
const byte DCC_Signal = 3; //LED wird eingeschaltet wenn ein Paket für irgendeine Weiche Empfanger wird
const byte Decoder_Signal = 5; //LED wird eingeschaltet wenn ein Paket für eine der 5 Programmierten Adressen empfangen wird
byte i, ii, Signal_aendern, Signal_dimmen, byteDummy, dimmer_on_off, inMenue;
int intDummy, intEingabe = -1;
int dcc_adresse [5] {399, 400, 403, 406, 409}; //1. Wert für Dimmer ein/aus Werte 2-5 für Signalansteuerung (nur bei Reset Decoder oder wenn neu)
//byte Signalbild enthält die Werte für die einzelnen Farben nach dem Muster:
//oberes Searchlight: rot, gelb, blau, weiß /unteres Searchlight: rot, gelb, blau, weiß
byte Signalbild [8][8] = {
{255, 000, 000, 000, 255, 000, 000, 000}, //Adresse gerade [STOP] / rot über rot
{000, 128, 128, 000, 255, 000, 000, 000}, //Adresse gebogen [Clear] / grün über rot
{000, 256, 000, 000, 000, 128, 128, 000}, //Adresse+1 gerade [Advance Approach] / gelb über grün
{000, 256, 000, 000, 000, 256, 000, 000}, //Adresse+1 gebogen [Advance Approach Medium] / gelb über gelb
{000, 256, 000, 000, 000, 000, 060, 256}, //Adresse+2 gerade [Approach restricting] / gelb über lunar (bläuliches weiß)
{255, 000, 000, 000, 000, 000, 060, 256}, //Adresse+2 gebogen [Restricting] / rot über lunar (bläuliches weiß)
{000, 256, 000, 000, 000, 000, 000, 000}, //Adressen wie oben [Approach expect] / gelb
{000, 128, 128, 000, 000, 000, 000, 000}, //Adressen wie oben [Clear expect] / grün
};
char* Searchlight_state[] = { "STOP", "Clear", "Advance Approach", "Advance Approach Medium", "Restricting", "Approach Restricting", "Approach expect", "Clear expect"};
unsigned long altzeit; //Timervariable
char* Eingabe = "";
bool stringComplete = false;
const unsigned int READ_BUFFER_SIZE = 6; //5 Zeichen + Terminator
void setup()
{
Serial.begin(115200);
Serial.println("Initializing....");
pinMode(DCC_Signal, OUTPUT);
pinMode(Decoder_Signal, OUTPUT);
//Nachfolger Block Auskommentieren löscht alle gespeicherten Werte!
// for (int i = 0 ; i < EEPROM.length() ; i++) {
// EEPROM.write(i, 0);
// }
// Serial.println("eeprom gelöscht....");
//Nachfolger Block Auskommentieren zeigt alle EEPROM Wetre beim Start an!
// for (int i = 0 ; i < EEPROM.length() ; i++) {
// ii = EEPROM.read(i);
// Serial.print(i); Serial.print(" , "); Serial.println(ii);
// }
// Serial.println("eeprom gelesen....");
// Eingabe.reserve(10); //Reserviert 10 Byte für Eingabe
setupDCCDecoder();
}
void setupDCCDecoder()
{
byte low, high;
Serial.println("Setting up DCC Decorder...");
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
Dcc.pin(0, 2, 1);
// Call the main DCC Init function to enable the DCC Receiver
Dcc.init(MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0);
for (i = 0; i < sizeof(dcc_adresse); i = i + 2) { //DCC Adressen lesen /schreiben (LOW & HIGH Byte), Schrittweite 2 da immer ein INT gelesen/geschrieben wird
low = Dcc.getCV(i + 300); ///CV Adresse + 300 wegen NMRADCC Libery
high = Dcc.getCV(i + 300 + 1);
intDummy = low + ((high << 8) & 0xFF00);
if ((intDummy >= 1) && (intDummy <= 2046) && !writeCVs) { // Wert aus CVs muss zwischen 1 und 2046 (Adresse + 3 pro Kommando , max 2046 Adressen) liegen für Adressen
dcc_adresse[i / 2] = intDummy;
//Serial.print("read DCC Adresse: "); Serial.println(i + 300);
Serial.print("read DCC Adresse: "); Serial.println(dcc_adresse[i / 2]);
}
else
{
low = dcc_adresse[(i / 2)] & 0xFF;
high = (dcc_adresse[(i / 2)] >> 8) & 0xFF;
Dcc.setCV(i + 300, low);
Dcc.setCV(i + 300 + 1, high);
//Serial.print("write DCC Adresse: "); Serial.println(i + 300);
Serial.print("write DCC Adresse: "); Serial.println(dcc_adresse[i / 2]);
}
}
for (i = 0; i < 4; i++) { //Signaltyp Speichern
byteDummy = Dcc.getCV(i + 310); //CV Adresse
if ((byteDummy <= 1) && !writeCVs) { // Wert aus CVs muss zwischen 0 und 1 liegen für Signaltyp
SignalTyp[i] = byteDummy;
Serial.print("read Signaltyp: "); Serial.println(SignalTyp[i]);
}
else
{
Dcc.setCV(i + 310, SignalTyp[i]);
Serial.print("write Signaltyp: "); Serial.println(SignalTyp[i]);
}
}
byteDummy = Dcc.getCV(314); //CV Adresse
if ((byteDummy) >= 1 && (byteDummy <= 4) && !writeCVs)Signale = byteDummy;
else Dcc.setCV(314, Signale) ;
Serial.print("Signale: "); Serial.println(Signale);
byteDummy = Dcc.getCV(315); //CV Adresse
if ((byteDummy) >= 40 && (byteDummy <= 200) && !writeCVs)SignalDimWert = byteDummy;
else Dcc.setCV(315, SignalDimWert) ;
Serial.print("Dimwert "); Serial.println(SignalDimWert);
writeCVs = 0;
Eingabe = "";
}
void serialEvent()
{
Eingabe = readLine(Serial);
if (Eingabe != nullptr) stringComplete = true;
}
char* readLine(Stream& stream) {
static byte index;
static char buffer[READ_BUFFER_SIZE];
while (stream.available()) {
char c = stream.read();
if (c == '\n') { //wenn LF eingelesen
buffer[index] = '\0'; //String terminieren
index = 0;
return buffer; //melden dass String fertig eingelesen wurde
}
else if (c >= 32 && index < READ_BUFFER_SIZE - 1) { //solange noch Platz im Puffer ist
buffer[index++] = c; //Zeichen abspeichern und Index inkrementieren
}
}
return nullptr; //noch nicht fertig
}
void menue()
{
if (isDigit(Eingabe)) { // Testet, ob das Zeichen eine Zahl ist.
intEingabe = atoi(Eingabe);
Serial.print("Das Zeichen ist eine Zahl"), Serial.println(intEingabe);
}
else Serial.println("Das Zeichen ist keine Zahl!!");
Serial.print ("Zahl als String: "); Serial.println(Eingabe);
Serial.print ("Zahl: "); Serial.println(atoi(Eingabe));
Serial.print ("Länge: "); Serial.println(strlen(Eingabe));
Eingabe = "";
stringComplete = false;
}
void menue_ori()
{
Serial.print("Eingabe 2: "); Serial.println(Eingabe);
Serial.print("Menü Zähler 2: "); Serial.println(inMenue);
if (strncmp(Eingabe, "m", 1) == 0) {
Serial.print("Eingabe 3: "); Serial.println(Eingabe);
Serial.print("Menü Zähler 3: "); Serial.println(inMenue);
Serial.println(F("!! ---- Menü ---- !!"));
Serial.println(F("Derzeit aktive Decoder Adressen"));
Serial.print (F("Adresse für Dimmer : ")); Serial.println(dcc_adresse[0]);
Serial.print (F("Adresse für Signal 1: ")); Serial.println(dcc_adresse[1]);
Serial.print (F("Adresse für Signal 2: ")); Serial.println(dcc_adresse[2]);
Serial.print (F("Adresse für Signal 3: ")); Serial.println(dcc_adresse[3]);
Serial.print (F("Adresse für Signal 4: ")); Serial.println(dcc_adresse[4]);
Serial.print (F("Anzahl der aktiven Signale: ")); Serial.println(Signale);
Serial.println(F("Wert = 0 = Main Signal, Wert = 1 = Distanz Signal (Vorsignal nur ein Schirm)"));
Serial.print (F("Signal Typ Signal 1: ")); Serial.println(SignalTyp[0]);
Serial.print (F("Signal Typ Signal 2: ")); Serial.println(SignalTyp[1]);
Serial.print (F("Signal Typ Signal 3: ")); Serial.println(SignalTyp[2]);
Serial.print (F("Signal Typ Signal 4: ")); Serial.println(SignalTyp[3]);
Serial.println(F("!----------------------------!"));
Serial.println(F("! mögliche Befehle !"));
Serial.println(F("! DCC Adressen ändern: d !"));
Serial.println(F("! Anzahl Signale: s !"));
Serial.println(F("! Typ Signale: t !"));
Serial.println(F("! Speichern & Beenden: w !"));
Serial.println(F("! Beenden ohne speichern: q !"));
Serial.println(F("! Test der LEDs: l !"));
Serial.println(F("! Reset auf default Werte: r !"));
Serial.println(F("! Seite erneut aufrufen: m !"));
Serial.println(F("!----------------------------!"));
inMenue = 1;
}
//Untermenüs aufrufen
if ((strncmp(Eingabe, "d", 1) == 0) || (inMenue >= 2) && (inMenue <= 6)) {
// intDummy = Eingabe.toInt();
Serial.print ("Zahl als String: "); Serial.println(atoi(Eingabe));
Serial.print ("Zahl: "); Serial.println(intDummy);
if (isDigit(Eingabe)) { // Testet, ob das Zeichen eine Zahl ist.
intEingabe = atoi(Eingabe);
Serial.print("Das Zeichen ist eine Zahl"), Serial.println(intEingabe);
}
else Serial.println("Das Zeichen ist keine Zahl!!");
inMenue = 2;
Serial.println (F("Bitte die DCC Adresse Auswählen: 1 = Dimmer Kanal, 2 - 5 DCC Adresse Signal 1-4"));
switch (intEingabe) {
case 0:
Serial.print (F("DCC Adresse für Dimmer (Erlaubte Werte 1-2046 : ")); Serial.println(dcc_adresse[0]);
break;
case 1:
Serial.print (F("DCC Adresse für Signal 1 (Erlaubte Werte 1-2046 : ")); Serial.println(dcc_adresse[0]);
break;
case 2:
Serial.print (F("DCC Adresse für Signal 2 (Erlaubte Werte 1-2046 : ")); Serial.println(dcc_adresse[0]);
break;
case 3:
Serial.print (F("DCC Adresse für Signal 3 (Erlaubte Werte 1-2046 : ")); Serial.println(dcc_adresse[0]);
break;
case 4:
Serial.print (F("DCC Adresse für Signal 4 (Erlaubte Werte 1-2046 : ")); Serial.println(dcc_adresse[0]);
break;
default:
Eingabe = "";
break;
}//switch
}
if ((strncmp(Eingabe, "s", 1) == 0) && (inMenue = 1)) {
// Anzahl Signale
}
if ((strncmp(Eingabe, "t", 1) == 0) && (inMenue = 1)) {
// Typ Signale
}
if ((strncmp(Eingabe, "w", 1) == 0) && (inMenue = 1)) {
// Speichern & Beenden
writeCVs = 1;
inMenue = 0;
Serial.println(F("!--------------------------------!"));
Serial.println(F("! Ende, Änderungen gespeichert! !"));
Serial.println(F("!--------------------------------!"));
setupDCCDecoder();//neue Werte in die CVs schreiben
}
if ((strncmp(Eingabe, "q", 1) == 0) && (inMenue = 1)) {
// Beenden ohne speichern
writeCVs = 0;
inMenue = 0;
Serial.println(F("!--------------------------------!"));
Serial.println(F("! Menü verlassen OHNE Änderungen !"));
Serial.println(F("!--------------------------------!"));
setupDCCDecoder(); //Werte aus CVs neu lesen!
}
if ((strncmp(Eingabe, "l", 1) == 0) && (inMenue = 1)) {
// Test der LEDs
Serial.println("! Test der LEDs !");
}
if ((strncmp(Eingabe, "r", 1) == 0) && (inMenue = 1)) {
Serial.println(F("!----------------------------!"));
Serial.println(F("! Reset auf default Werte!!! !"));
Serial.println(F("!----------------------------!"));
for (i = 0; i < 4; i++) {
SignalBefehl [i] = 0;
SignalTyp [i] = 0;
}
Signale = 4;
dcc_adresse[0] = 399;
for (i = 1; i < 5; i++) dcc_adresse[i] = 400 + (i * 3) - 3;
SignalDimWert = 127;
writeCVs = 1;
inMenue = 0;
setupDCCDecoder();
}
Serial.print("Eingabe 4: "); Serial.println(Eingabe);
Serial.print("Menü Zähler 4: "); Serial.println(inMenue);
Eingabe = "";
stringComplete = false;
}//Menue gestartet
void LEDs_loeschen()
{
if (millis() - altzeit >= 1000) {
altzeit = millis();
if (digitalRead(Decoder_Signal)) digitalWrite(Decoder_Signal, 0);
if (digitalRead(DCC_Signal)) digitalWrite(DCC_Signal, 0);
}
}
//
// Ausgabe Adafruit_NeoPixel
//
void OutputNeoPixel()
{
for (i = 0; i < Signale; i++) {
Serial.print("Signal Aspect: "); Serial.print(i + 1); Serial.print(" : "); Serial.println(Searchlight_state[SignalBefehl[i]]);
}
Signal_aendern = false;
}
// Diese Funktion wird aufgerufen wenn ein DCC Turnout Packet empfangen wird
void notifyDccAccTurnoutOutput(uint16_t Addr, uint8_t Direction, uint8_t OutputPower)
{
digitalWrite(DCC_Signal, 1); //Steuert LED an, wenn für den DCC Signal für Weichen empfangen wurde
if (Addr == (dcc_adresse[0]) && !dimmer_on_off) {
if (!Direction) Signal_dimmen = true;
else Signal_dimmen = false;
Signal_aendern = true;
dimmer_on_off = true;
Serial.print("Dimmen : "); Serial.println(Signal_dimmen);
}
else
{
//Signal 1 /pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[1]) && OutputPower) SignalBefehl[0] = (!Direction); //pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[1] + 1) && OutputPower) SignalBefehl[0] = (2 + !Direction);
if ((Addr == dcc_adresse[1] + 2) && OutputPower) SignalBefehl[0] = (4 + !Direction);
//Signal 2 /pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[2]) && OutputPower && (Signale >= 2)) SignalBefehl[1] = (!Direction); //pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[2] + 1) && OutputPower && (Signale >= 2)) SignalBefehl[1] = (2 + !Direction);
if ((Addr == dcc_adresse[2] + 2) && OutputPower && (Signale >= 2)) SignalBefehl[1] = (4 + !Direction);
//Signal 3 /pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[3]) && OutputPower && (Signale >= 3)) SignalBefehl[2] = (!Direction); //pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[3] + 1) && OutputPower && (Signale >= 3)) SignalBefehl[2] = (2 + !Direction);
if ((Addr == dcc_adresse[3] + 2) && OutputPower && (Signale >= 3)) SignalBefehl[2] = (4 + !Direction);
//Signal 4 /pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[4]) && OutputPower && (Signale >= 4)) SignalBefehl[3] = (!Direction); //pro Signal werden 3 Adressen belegt.
if ((Addr == dcc_adresse[4] + 1) && OutputPower && (Signale >= 4)) SignalBefehl[3] = (2 + !Direction);
if ((Addr == dcc_adresse[4] + 2) && OutputPower && (Signale >= 4)) SignalBefehl[3] = (4 + !Direction);
for (i = 0; i < Signale; i++) { //Array der Signalbefehle auf Änderung auswerten
if (SignalBefehl[i] != Old_SignalBefehl[i]) Signal_aendern = true;
Old_SignalBefehl[i] = SignalBefehl[i];
}
}
if (Signal_aendern)
{
digitalWrite(Decoder_Signal, 1); //Steuert LED an, wenn für den Decoder Daten empfangen wurden.
Serial.print("SignalBefehl Array: ");
for (i = 0; i < Signale; i++) { //zum Test
Serial.print("["); Serial.print(SignalBefehl[i]); Serial.print("]");
}
Serial.println("Fertig");
OutputNeoPixel(); //ruft die Änderung der Signalbilder auf
}
}
void loop()
{
Dcc.process(); //DDC Libary muss zyklisch aufgerufen werden
LEDs_loeschen();
if (stringComplete) menue();
}
[/code]