Na du bist mir ja einer...... ![]()
Weil es schon wieder spät ist, antworte ich nur eben kurz auf Deine Fragen. Bitte nicht als abfällig werten.Hatte gestern schon mal probiert, aber da wollte mein Decoder plötzlich nicht mehr.....bis ich den Fehler gefunden habe war es 23:00 uhr ![]()
#define BENZINER ....er war's
Die Funktion hast Du geschrieben
, wenn ich es richtig sehe sind das die Anzahl Zeichen für die obere LCD-Zeile beim eintritt in die Farbeinstellung.
War wohl ein Überbleibsel.....Überflüssig
Habe ich überarbeitet...
Anzeige, muss ich noch machen.....
Hinzugefügt habe ich noch
void clearBrightness() // Alle TM1637-Anzeigen auf eingestellten bzw. gespeicherten Wert zurücksetzen
{
for (byte d = 0; d < 8; d++)
{
tmDisp[d].setBrightness(lumi);
}
}
Diese Funktion wird bei Anzeigewechsel (ausser bei Runden-Anzeige) vorher durchgeführt.
Hatte sonst immer in den anderen Anzeigebilder eine Zeile heller.... ![]()
Aber nun mal im ganzen...
[code]
// Tower-Control auf MEGA 2560
const char ver[] = {" Tower-V1.25edit "}; // Stand 10.11.2021
//#define DEBUG
#define BENZINER
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print (x)
#define DEBUG_PRINTLN(x) Serial.println (x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#endif
#include <Wire.h>
#include <EEPROM.h> // Zum Abspeichern der Einstellungen
// Tower 7-Segmentanzeigen
#include <TM1637Display.h> // Einbinden der Bibliothekt zum ansteuern des 7 Segment-Displays
const uint8_t clk[8] = {22, 24, 26, 28, 30, 32, 34, 36}; // CLK Pin´s der TM 1637
const uint8_t dio[8] = {6, 7, 8, 9, 10, 11, 12, 13}; // DIO Pin´s der TM 1637
uint8_t lumi = EEPROM.read(1); // Helligkeit für alle 7-Segment Anzeigen
uint8_t lumiPole = 7; // Helligkeit für führenden Fahrer bzw. Spur bei der Rundenanzeige
uint8_t kanal = EEPROM.read(2); // Kanal für NRF24 Empfänger
uint8_t id = EEPROM.read(3); // Id für Fernsteuerung vom Converter
uint8_t SBild = EEPROM.read(4); // Anzeigebild Turm nach dem Einschalten
uint8_t AnzahlSpuren = EEPROM.read(5); // Anzahl der Fahrspuren
uint8_t Wsl = SBild; // Imaginärer Wahlschalter ;-)
uint8_t spuren = AnzahlSpuren; // Anzahl der Bahnspuren !!!
uint8_t exitMenu = false; // Aufruf (true) im Hauptmenü = verlassen, wenn kein subMenu
uint8_t ExternAnz_state = 0; // Anzeigestatus für Externabfrage
uint8_t ExternLich_state[3] = {0}; // Anzeigestatus für Externabfrage Licht
//erzeugen des Display 1 bis 8 Objektes mit den Parametern für die PINs
TM1637Display tmDisp[] = { TM1637Display (clk[0], dio[0]), // 1 Reihe von oben / - links
TM1637Display (clk[1], dio[1]), // 1 Reihe von oben / - rechts
TM1637Display (clk[2], dio[2]), // 2 Reihe von oben / - links
TM1637Display (clk[3], dio[3]), // 2 Reihe von oben / - rechts
TM1637Display (clk[4], dio[4]), // 3 Reihe von oben / - links
TM1637Display (clk[5], dio[5]), // 3 Reihe von oben / - rechts
TM1637Display (clk[6], dio[6]), // 4 Reihe von oben / - links
TM1637Display (clk[7], dio[7]) // 4 Reihe von oben / - rechts
};
// Array für ***Uhr***
const uint8_t Uhr[] = {0, SEG_F | SEG_E | SEG_D | SEG_C | SEG_B, SEG_F | SEG_E | SEG_G | SEG_C, SEG_E | SEG_G , };
// Array für ***Jahr***
const uint8_t Jahr[] = {SEG_B | SEG_C | SEG_D | SEG_E, SEG_G | SEG_C | SEG_D | SEG_E, SEG_F | SEG_E | SEG_G | SEG_C, SEG_E | SEG_G , };
// Array für ***Cal***
const uint8_t Cal[] = {0, SEG_A | SEG_F | SEG_E | SEG_D, SEG_G | SEG_C | SEG_D | SEG_E, SEG_E | SEG_F, };
// Array für ***C***
const uint8_t C[] = { SEG_A | SEG_E | SEG_F | SEG_D , };
// Array für ***Grad***
const uint8_t Grad[] = { SEG_A | SEG_F | SEG_E | SEG_D | SEG_C | SEG_G , SEG_E | SEG_G , SEG_G | SEG_C | SEG_D | SEG_G | SEG_E, SEG_E | SEG_D | SEG_C | SEG_B | SEG_G, };
// Array für ***U--***
const uint8_t U[] = {0, SEG_F | SEG_E | SEG_D | SEG_C | SEG_B , SEG_G,};
// Array für ***AL-***
const uint8_t AL[] = {SEG_E | SEG_F | SEG_A | SEG_B | SEG_C | SEG_G , SEG_F | SEG_E | SEG_D, SEG_G,};
// Array für ***SP-***
const uint8_t Sp[] = {SEG_A | SEG_F | SEG_G | SEG_C | SEG_D, SEG_E | SEG_F | SEG_A | SEG_B | SEG_G , SEG_G, SEG_G,};
// Array für ***,***
const uint8_t Komma[] = {SEG_E,};
// Array für ***1***
const uint8_t Eins[] = {SEG_B | SEG_C,};
// Array für ***2***
const uint8_t Zwei[] = {SEG_A | SEG_B | SEG_G | SEG_E | SEG_D,};
// Array für ***3***
const uint8_t Drei[] = {SEG_A | SEG_B | SEG_G | SEG_C | SEG_D,};
// Array für ******
const uint8_t Vier[] = {SEG_F | SEG_G | SEG_B | SEG_C,};
// Radio
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>
RF24 radio(4, 5); // CE=4, CS=5, SCK=, MO=, MI=
const byte address[6] = "00001"; // Sender-Adresse
// Vorbereitung LCD-Menu Zeichenketten
constexpr unsigned menueStrLen {12};
constexpr unsigned hauptMenuePunkte {11};
constexpr unsigned turmAnzeigePunkte{5};
constexpr unsigned turmLichtPunkte{6};
using ConstStrPtr = const char *;
using FlashStrPtr = const __FlashStringHelper *;
using MenuePunkt = const char[menueStrLen + 1];
// LCD
#include <LiquidCrystal_I2C.h>
const uint8_t lcdRow = 16;
const uint8_t lcdCol = 2;
LiquidCrystal_I2C lcd(0x27, lcdRow, lcdCol);
// Licht
#include <Adafruit_NeoPixel.h> // Einbinden der Bibliothekt zum ansteuern der WS2812 LEDs
const uint8_t ledPin = 45; // Pin für WS2812 LEDs
const uint16_t numPixel = 7; // Anzahl der WS2812 LEDs
Adafruit_NeoPixel pixel(numPixel, ledPin, NEO_GRB + NEO_KHZ800);
// Verarbeitung
uint8_t temp = 10; // Einschalt-Temperatur vor dem Empfang des Converter's
const uint8_t maxSpuren = 8; // Mögliche Anzahl der Spuren
uint16_t AR[maxSpuren + 1] = {0}; // Runden je Spur
uint16_t RZvk[maxSpuren + 1] = {0}; // Rundenzeit Vorkomma je Spur
uint16_t RZnk[maxSpuren + 1] = {0}; // Rundenzeit Nachkomma je Spur
uint16_t Voltage[maxSpuren + 1] = {0}; // Spannung für die Spur
uint8_t VoltVK[maxSpuren + 1] = {0}; // Bahnstrom Vorkomma je Spur
uint8_t VoltNK[maxSpuren + 1] = {0}; // Bahnstrom Vorkomma je Spur
const uint8_t charNum = 26; // Anzahl Buchstaben -1 für Fahrernamen
char Fahrer[maxSpuren + 1][charNum] = {0};
// RGB Werte
byte rgbLicht[3][3] = {0}; // Auswahl RGB-Werte Beleuchtung Eingang,Erdgeschoss,Obergeschoss
// Uhr
#include <DS1307RTCB.h> // auf die TimeLibB angepasste 1307 von Paul Stoffregen
#include <TimeLibB.h> // auf deutsch umgeschriebene TimeLib von Paul Stoffregen
uint8_t minutealt = 61; // Zwangsaktuallisierung Uhrzeit! - nur alle Minute neue Abfrage
// RotaryEncoder
#include <rotary.h>
#ifdef BENZINER
Rotary r = Rotary(2, 3, 40); // Rotary(Encoder Pin 1, Encoder Pin 2, Button Pin)
#else
Rotary r = Rotary(5, 3, 23); // Rotary(Encoder Pin 1, Encoder Pin 2, Button Pin) 5,3,23
#endif
const uint8_t bounce = 10;
// Extern-AbfragePin´s
// 23=Rundenzeiten Wsl-1,25=Runden Wsl-2,27= Uhr Wsl-3,29=Bahnstrom Wsl-4,31=Tagesrunden Wsl-5
// 33=Licht Eingang,35=Licht Erdgeschoss,37=Licht Obergeschoss,39=Frei,41=Licht Chaos Blinken
const uint8_t ExternPin[] = {23, 25, 27, 29, 31, 33, 35, 37, 39, 41};
// Gesamtzähler
uint16_t TagZahl[maxSpuren + 1] = {0}; // Tageszähler, zählt alle Runden pro Spur zusammen
uint16_t lastAR[maxSpuren + 1] = {0}; // Vergleicher, für Tageszähler
uint16_t lastTagesrunden[maxSpuren + 1] = {0}; // Vergleicher, für Tageszähler Anzeigetafel
uint16_t maxRunden; // Merker für größte Rundenzahl
void setup()
{
Serial.begin(115200);
DEBUG_PRINTLN(F("Start..."));
lcd.init(); // Für Benziner
//lcd.begin(); // Für XY Projekt
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(ver);
//Setzt die Helligkeit des Displays mögliche Werte sind 0 bis 7, 0 dunkel und 7 hell
for (uint8_t i = 0; i < 8 ; i++)
{
tmDisp[i].setBrightness(lumi);
}
clearAll();
// setzt die Farbwerte aus EEprom
for (uint8_t i = 0; i < 3 ; i++)
{
rgbLicht[0][i] = //Farbe für Eingang
EEPROM.read(i + 10);
rgbLicht[1][i] = //Farbe für Erdgeschoss
EEPROM.read(i + 20);
rgbLicht[2][i] = //Farbe für Obergeschoss
EEPROM.read(i + 30);
}
// Setup Radio
radio.begin();
radio.enableDynamicPayloads(); // wichtig! Es werden nur Nutzdaten übertragen!
radio.setPALevel(RF24_PA_MAX); // der Sender muss nicht hoch sein (MAX,HIGH,LOW,MIN)
radio.setDataRate(RF24_1MBPS); // je schneller desto...
radio.setChannel(kanal); // Für Benziner
radio.setAutoAck(0); // NoACK - ein Sender multiple Empfänger
radio.openReadingPipe(0, address);
radio.startListening(); // Start des Empfängermodus
pixel.begin();
// Init ExternPin
for (uint8_t i = 0; i < sizeof(ExternPin); i++)
{
pinMode(ExternPin[i], INPUT_PULLUP);
}
}
// Ende Setup
void loop()
{
if (!menue()) // fragt das menu ab
{
displayKalender(); // wenn kein menu dann Kalender
}
anzeige(); // Auswahl für Anzeigetafel
leseEmpfang(); // Empfange NRF 24 und werte aus
leseEingaenge(); // Abfrage der Extern-Eingänge
merkeRunden(); // Zählt alle Runden je Spur zusammen"Tageszähler"
}
bool menue() // gibt true zurück, wenn ein Menu aufgemacht - sonst false
{
static uint8_t nextMenu = 0;
if (!nextMenu && r.buttonPressedReleased(bounce)) // Kein Menu? aber auf Button gedrückt
{
DEBUG_PRINTLN(F("Button pressed Aufruf Hauptmenue"));
nextMenu = Hauptmenue(0); // übergebe Startzeichen für Menu
}
else if (nextMenu != 0) // wenn doch Menu
{
nextMenu = Hauptmenue(nextMenu); // ... dann einmal durchs Menu
}
return nextMenu; // gib Zustand zurück (0=false - alles andere ist true)
}
uint8_t getRotary(uint8_t rotaryWert, const uint8_t rotaryMin, const uint8_t rotaryMax)
{
// *INDENT-OFF*
//uint8_t lastRotary = rotaryWert; // fuer debugausgabe
uint8_t val = r.process(); // Check the encoder
//DEBUG_PRINTLN(val);
if (val == r.clockwise()) { rotaryWert ++; }
else if (val == r.counterClockwise() && rotaryWert>0)
{ rotaryWert --; }
if (rotaryWert > rotaryMax) { rotaryWert = rotaryMax; }
else if (rotaryWert < rotaryMin) { rotaryWert = rotaryMin; }
// if (lastRotary != rotaryWert) DEBUG_PRINTLN(rotaryWert); // debugausgabe
return (rotaryWert);
// *INDENT-ON*
}
MenuePunkt hauptMenu[] PROGMEM // TAB Hauptmenu
{
{"Hauptmenue"},
{"Anzeigetafel"},
{"Beleuchtung"},
{"Helligkeit"},
{"Farbe-Licht"},
{"Fahrspuren"},
{"Startanzeige"},
{"IDNummer"},
{"Funkkanal"},
{"WerksWerte"},
{"Verlassen"},
};
uint8_t Hauptmenue(uint8_t menuRotary) // Auswahl Hauptmenue...
{
const uint8_t rotaryMin = 1; // erster Eintrag
const uint8_t rotaryMax = sizeof(hauptMenu) / sizeof(hauptMenu[0]) - 1; // letzer Menueintrag -> Menu verlassen
static uint8_t subMenu = 0; // Merker auf switch/case
static uint8_t nextMenu = 0;
static bool lcdInitMerker = false; // fuer erstmalige Anzeige des UnterMenu
if (menuRotary == 0) // Initialisiert Variablen
{
lcdMenuLine(0, 0);
subMenu = 0;
nextMenu = 0;
menuRotary++;
Serial.println(rotaryMax);
}
if (!subMenu) // bisher kein SubMenu ausgewählt
{
uint8_t tikRotary = getRotary(nextMenu, rotaryMin, rotaryMax); // Abfrage RotaryEncoder
if (nextMenu != tikRotary) // neuer Wert? dann zeige an
{
nextMenu = tikRotary; // merke den aktuellen RotaryWert
Serial.println(nextMenu);
if (nextMenu <= rotaryMax) // Untermenu geht nur bis vorletzten Eintrag
lcdMenuLine(1, nextMenu); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce)) // EncoderButton ausgelöst?
{
if (nextMenu < rotaryMax)
lcdMenuLine(0, nextMenu); // schreibt erste Zeile mit nächstem Menupunkt
subMenu = nextMenu; // übernimmt den Wert zur Weitergabe
DEBUG_PRINT(F("switch Menu: "));
DEBUG_PRINTLN(nextMenu);
}
if (exitMenu == true)
{
lcd.setCursor(0, 0);
lcd.print(ver);
minutealt = 61;
subMenu = false;
exitMenu = false;
menuRotary = 0;
}
}
if (subMenu)
switch (nextMenu)
{
case rotaryMin: // Gehe zu Turmanzeige-Menue
if (!lcdInitMerker)lcdSubTurmLineTwo(0);
subMenu = turmAnzeige(subMenu);
break;
case 2: // Gehe zu Turmlicht-Menue
if (!lcdInitMerker)turmLicht(false);
subMenu = turmLicht(subMenu);
break;
case 3: // Gehe zu Helligkeit-Menue
if (!lcdInitMerker) subMenu = Helligkeit(false);
subMenu = Helligkeit(subMenu);
break;
case 4: // Gehe zu LEDFarben-Menue
if (!lcdInitMerker)ledFarben(0);
subMenu = ledFarben(subMenu);
break;
case 5: // Gehe zu Fahrspuren-Menue
if (!lcdInitMerker)subMenu = Fahrspuren(false);
subMenu = Fahrspuren(subMenu);
break;
case 6: // Gehe zu Startanzeige-Menue
if (!lcdInitMerker)subMenu = Startanzeige(false);
subMenu = Startanzeige(subMenu);
break;
case 7: // Gehe zu IDNummer-Menue
if (!lcdInitMerker)subMenu = IDNummer(false);
subMenu = IDNummer(subMenu);
break;
case 8: // Gehe zu Funkkanal-Menue
if (!lcdInitMerker)subMenu = Funkkanal(false);
//if (!lcdInitMerker)Funkkanal(0);
subMenu = Funkkanal(subMenu);
break;
case 9: // Gehe zu WerksWerte-Menue
if (!lcdInitMerker)WerksWerte(0);
subMenu = WerksWerte(subMenu);
break;
case rotaryMax: // Hauptmenue verlassen
//DEBUG_PRINTLN(F("Button pressed Abfrage ob speichern und Hauptmenue verlassen"));
if (!lcdInitMerker)Speichern(0);
subMenu = Speichern(subMenu);
break;
}
if (subMenu) lcdInitMerker = true; else lcdInitMerker = false;
return (menuRotary);
}
void lcdMenuLine(const uint8_t line, const uint8_t auswahl) // Inhalt der ersten Zeile des LCD-Menu
{
lcd.setCursor(0, line);
if (line == 0)
{
lcd.print("*"); //DEBUG_PRINT("*");
lcdLineZentriert(auswahl); //DEBUG_PRINT(auswahl);
lcd.print("*"); //DEBUG_PRINTLN("*");
}
else if (line == 1)
{
if (auswahl > 1) lcd.print("<"); else lcd.print(" ");
lcdLineZentriert(auswahl);
if (auswahl < sizeof(hauptMenu) / sizeof(hauptMenu[0]) - 1) lcd.print(">"); else lcd.print(" ");
}
}
void lcdLineZentriert(uint8_t ausgabe)
{
const uint8_t gesamt = lcdRow - 2;
uint8_t vor = 0;
uint8_t nach = 0;
vor = (gesamt - txtlaenge(ausgabe)) / 2;
nach = gesamt - txtlaenge(ausgabe) - vor;
for (; vor >= 1; vor--)
{
lcd.print(" "); //DEBUG_PRINT(" ");
}
lcd.print(lcdHauptMenu(ausgabe));
// DEBUG_PRINT(lcdHauptMenu(ausgabe));
for (; nach >= 1; nach--)
{
lcd.print(" ");// DEBUG_PRINT(" ");
}
//DEBUG_PRINTLN();
}
FlashStrPtr lcdHauptMenu(byte index)
{
return FlashStrPtr(&hauptMenu[index]);
}
uint8_t txtlaenge(byte index)
{
return strlen_P(ConstStrPtr(&hauptMenu[index]));
}
const uint8_t stripeLen[][2] = // Tab RGB - Stand 26.08.
{
{0, 1}, // Eingang: start, länge
{1, 3}, // Unten
{4, 3}, // Oben
};
uint8_t ledFarben(uint8_t menuRotary)
{
// my_xy_Erinnerung: 3 WS RGB -> 2D Array!
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = sizeof(rgbLicht) / 3 + 1; // Wenn das mal erweitert wird...
static uint8_t colorType = 0; // 1=rt 2=gn 3=bl 4=Weiter/Ende
static uint8_t ledType = 0; // zaehlt die Einsatzorte durch
uint8_t tempRotary = 0; // temporäre Aufnahme RotaryWert
static bool holdPixel = false; // Merker für Zustand der Beleuchtung
if (menuRotary == 0) // erster Aufruf der Einstellung
{
colorType = 1;
ledType = 0 ;
holdPixel = pixel.getPixelColor(0); // Merkt sich den Zustand des Pixel
pixelAnAus(0, 1); // Macht Stripe an
lcd.clear();
lcdSubLedOne(ledType);
lcd.blink();
lcd.setCursor(0, 1);
lcdSubLedTwo(ledType, 0); // 0 löst Init für LCD aus!
menuRotary++; // setzt != 0 für Dauerschleife
// DEBUG_PRINTLN(colorType);
// DEBUG_PRINT(F("RGB-"));
// DEBUG_PRINTLN(ledType);
}
switch (colorType)
{
case rotaryMin:
tempRotary = getRotary(rgbLicht[ledType][0], 0, 255); // rot für WS Nummer: ledType Eingang
if (rgbLicht[ledType][0] != tempRotary)
{
rgbLicht[ledType][0] = tempRotary;
lcdSubLedTwo(ledType, colorType);
pixelAnAus(ledType, 1);
}
break;
case 2:
tempRotary = getRotary(rgbLicht[ledType][1], 0, 255); // gruen für WS Nummer: ledType Erdgeschoss
if (rgbLicht[ledType][1] != tempRotary)
{
rgbLicht[ledType][1] = tempRotary;
lcdSubLedTwo(ledType, colorType);
pixelAnAus(ledType, 1);
}
break;
case 3:
tempRotary = getRotary(rgbLicht[ledType][2], 0, 255); // blau für WS Nummer: ledType Obergeschoss
if (rgbLicht[ledType][2] != tempRotary)
{
rgbLicht[ledType][2] = tempRotary;
lcdSubLedTwo(ledType, colorType);
pixelAnAus(ledType, 1);
}
break;
case rotaryMax:
{
pixelAnAus(ledType, holdPixel);
if (ledType < sizeof(rgbLicht) / 3 - 1) // noch nicht alle WS durch...
{
colorType = 1; // fange an von vorn
ledType++; // naechste WS
holdPixel = pixel.getPixelColor(stripeLen[ledType][0]);
pixelAnAus(ledType, 1);
lcdSubLedOne(ledType);
lcdSubLedTwo(ledType, 0);
DEBUG_PRINT(F("RGB-"));
DEBUG_PRINTLN(ledType);
DEBUG_PRINTLN(colorType);
}
else
{
colorType = 0;
ledType = 0;
menuRotary = 0;
lcdMenuLine(0, 0);
lcdMenuLine(1, 4);
}
}
break;
}
if (r.buttonPressedReleased(bounce))
{
colorType++;
lcdSubLedTwo(ledType, colorType);
}
#ifdef DEBUG
serialColor(ledType, rgbLicht[ledType][0], rgbLicht[ledType][1], rgbLicht[ledType][2]);
#endif
if (!menuRotary)lcd.noBlink(); // wenn menuRotary wieder auf 0 gesetzt, ist Ende lcd und damit Ende blink
return menuRotary;
}
void pixelAnAus(uint8_t stripeNum, bool anAus)
{
Serial.print(F("Pixel "));
if (anAus)
{
Serial.println(F("an"));
pixel.fill(pixel.Color(rgbLicht[stripeNum][0],
rgbLicht[stripeNum][1],
rgbLicht[stripeNum][2]), stripeLen[stripeNum][0], stripeLen[stripeNum][1]);
}
else
{
Serial.println(F("aus"));
pixel.fill(0, stripeLen[stripeNum][0], stripeLen[stripeNum][1]);
}
pixel.show();
}
void lcdSubLedOne(const uint8_t number)
{
const uint8_t laenge = 5; // RGB-0
uint8_t vor = 0;
uint8_t nach = 0;
vor = (lcdRow - laenge) / 2;
nach = lcdRow - laenge - vor;
for (; vor >= 1; vor--)
{
lcd.print(" "); DEBUG_PRINT(" ");
}
lcd.print(F("RGB- ")); DEBUG_PRINT(F("RGB- "));
for (; nach >= 1; nach--)
{
lcd.print(" "); DEBUG_PRINT(" ");
}
lcd.setCursor(9, 0);
lcd.print(number);
DEBUG_PRINTLN();
}
void lcdSubLedTwo(const uint8_t farbenWert, const uint8_t farbenType) // lcd Zeile 2 fuer ledFarben
{
const uint8_t row = 1;
uint8_t col = 3;
if (farbenType == 1) col = 3;
if (farbenType == 2) col = 7;
if (farbenType == 3) col = 11;
if (farbenType == 0 || farbenType == 1) // alle oder rot
{
lcd.setCursor(0, row);
lcd.print(" ");
if (rgbLicht[farbenWert][0] < 100) lcd.print(" ");
if (rgbLicht[farbenWert][0] < 10 ) lcd.print(" ");
lcd.print(rgbLicht[farbenWert][0]);
}
if (farbenType == 0 || farbenType == 2) // alle oder gruen
{
lcd.setCursor(4, row);
lcd.print(" ");
if (rgbLicht[farbenWert][1] < 100) lcd.print(" ");
if (rgbLicht[farbenWert][1] < 10 ) lcd.print(" ");
lcd.print(rgbLicht[farbenWert][1]);
}
if (farbenType == 0 || farbenType == 3) // alle oder blau
{
lcd.setCursor(8, row);
lcd.print(" ");
if (rgbLicht[farbenWert][2] < 100) lcd.print(" ");
if (rgbLicht[farbenWert][2] < 10 ) lcd.print(" ");
lcd.print(rgbLicht[farbenWert][2]);
}
lcd.setCursor(col, row);
}
void serialColor(const uint8_t t, const uint8_t r, const uint8_t g, const uint8_t b)
{
static uint32_t oldColor = {0};
uint32_t myColor = pixel.Color(r, g, b);
if (oldColor != myColor)
{
oldColor = myColor;
DEBUG_PRINT(F("RGB: "));
for (uint8_t i = 0; i < 3; i++)
{
DEBUG_PRINT(rgbLicht[t][i]);
DEBUG_PRINT("\t");
}
DEBUG_PRINTLN();
}
}
uint8_t Helligkeit(uint8_t menuRotary) // TAB SubMenu Helligkeit
{
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = 7;
if (menuRotary == 0)
{
lcd.blink();
menuRotary = lumi;
lcdSubHelligLineTwo(menuRotary);
}
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubHelligLineTwo(tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINTLN(F("Button pressed Helligkeit -> Werte übernehmen und zurück ins Hauptmenu"));
lcdMenuLine(0, 0);
lcdMenuLine(1, 3);
lumi = tikRotary;
for (uint8_t i = 0; i < 8 ; i++)
{
tmDisp[i].setBrightness(tikRotary);
}
if (Wsl == 2)spurAnzeigeLinks();
if (Wsl == 3)
{
uhrAnzeigeLinks();
}
lcd.noBlink();
menuRotary = 0;
}
return menuRotary;
}
uint8_t Fahrspuren(uint8_t menuRotary) // TAB SubMenu Fahrspuren
{
const uint8_t rotaryMin = 2;
const uint8_t rotaryMax = 8;
if (menuRotary == 0)
{
lcd.blink();
menuRotary = AnzahlSpuren;
lcdSubSpurenLineTwo(menuRotary);
}
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubSpurenLineTwo(tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINTLN(F("Button pressed Fahrspuren -> Werte übernehmen und zurück ins Hauptmenu"));
lcdMenuLine(0, 0);
lcdMenuLine(1, 5);
AnzahlSpuren = tikRotary;
lcd.noBlink();
menuRotary = 0;
return false;
}
return menuRotary;
}
uint8_t Startanzeige(uint8_t menuRotary)
{
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = 5;
if (menuRotary == 0)
{
lcd.blink();
menuRotary = SBild;
lcdSubStartanzeigeLineTwo(menuRotary);
}
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubStartanzeigeLineTwo(tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINTLN(F("Button pressed Startanzeige -> zurück ins Hauptmenu"));
lcdMenuLine(0, 0);
lcdMenuLine(1, 6);
SBild = tikRotary;
menuRotary = 0;
lcd.noBlink();
return false;
}
return menuRotary;
}
uint8_t IDNummer(uint8_t menuRotary)
{
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = 50;
if (menuRotary == 0)
{
lcd.blink();
menuRotary = id;
lcdSubIDNummerLineTwo(menuRotary);
}
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubIDNummerLineTwo(tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINTLN(F("Button pressed IDNummer -> zurück ins Hauptmenu"));
lcdMenuLine(0, 0);
lcdMenuLine(1, 7);
id = tikRotary;
menuRotary = 0;
lcd.noBlink();
return false;
}
return menuRotary;
}
uint8_t Funkkanal(uint8_t menuRotary)
{
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = 127;
if (menuRotary == 0)
{
lcd.blink();
menuRotary = kanal;
lcdSubkanalLineTwo(menuRotary);
}
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubkanalLineTwo(tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINTLN(F("Button pressed FunkKanal -> zurück ins Hauptmenu"));
lcdMenuLine(0, 0);
lcdMenuLine(1, 8);
radio.setChannel(kanal);
kanal = tikRotary;
menuRotary = 0;
lcd.noBlink();
return false;
}
return menuRotary;
}
uint8_t WerksWerte(uint8_t menuRotary)
{
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = 2;
if (menuRotary == 0)
{
lcd.blink();
}
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubWerksWerteLineTwo(tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINTLN(F("Button pressed WerksWerte -> zurück ins Hauptmenu"));
lcdMenuLine(0, 0);
lcdMenuLine(1, 10);
if (tikRotary == 1)
{
Werkseinstellung();
DEBUG_PRINTLN("Es werden Daten wiederhergestellt");
}
if (tikRotary == 2)
{
DEBUG_PRINTLN("Es wurden keine Daten wiederhergestellt");
}
exitMenu = true;
return false;
}
return menuRotary;
}
uint8_t Speichern(uint8_t menuRotary)
{
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = 2;
if (menuRotary == 0)
{
lcd.blink();
}
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubSpeichernLineTwo(tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINTLN(F("Button pressed Speichern -> zurück ins Hauptmenu"));
lcdMenuLine(0, 0);
lcdMenuLine(1, 10);
if (tikRotary == 1)
{
Datensicherung();
DEBUG_PRINTLN("Es wurden Daten gesichert");
}
if (tikRotary == 2)
{
DEBUG_PRINTLN("Es wurden keine Daten gesichert");
}
exitMenu = true;
return false;
}
return menuRotary;
}
uint8_t turmAnzeige(uint8_t menuRotary)// TAB Turmanzeige menue "Was soll Turm anzeigen werden: Rundenzeit / Rundenanzahl / Uhr_Datum / Extern "
{
const uint8_t rotaryMin = 1;
const uint8_t rotaryMax = 6;
uint8_t tikRotary = getRotary(menuRotary, rotaryMin, rotaryMax);
if (menuRotary != tikRotary)
{
menuRotary = tikRotary;
lcdSubTurmLineTwo(tikRotary - 1); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINT(F("Button pressed Turmanzeige -> Wert: "));
DEBUG_PRINTLN(tikRotary);
switch (menuRotary)
{
case rotaryMin: // Turmanzeige "Rundenzeit"
DEBUG_PRINT(F("Rundenzeit"));
Wsl = 1;
break;
case 2: // Turmanzeige "Rundenanzahl"
DEBUG_PRINT(F("Rundenanzahl"));
Wsl = 2;
break;
case 3: // Turmanzeige "Datum / Uhrzeit"
DEBUG_PRINT(F("Datum / Uhrzeit"));
Wsl = 3;
break;
case 4: // Turmanzeige "Extern-Auswahl"
DEBUG_PRINT(F("Bahnstrom-Auswahl"));
Wsl = 4;
for (uint8_t i = 1; i <= spuren; i++)
{
Voltage[i] = 0;
}
break;
case 5: // Turmanzeige "Extern-Auswahl"
DEBUG_PRINT(F("Gesamtrunden-Auswahl"));
Wsl = 5;
break;
case rotaryMax: // Turmanzeige gehe zurück zu Hauptmenue
DEBUG_PRINT(F("-> ins Hauptmenu"));
break;
}
DEBUG_PRINTLN(F(" ausgewaehlt"));
DEBUG_PRINTLN();
lcdMenuLine(0, 0);
lcdMenuLine(1, 1);
return 0;
}
return menuRotary;
}
void lcdSubTurmLineTwo(const uint8_t auswahl) // Inhalt der zweiten Zeile des Lcd-Menu im Turmmenu
{
static uint8_t oldAuswahl = 0;
lcd.setCursor(0, 1);
const char *line2[] = {" Zeiten-Anzeige>" , "<Runden-Anzeige>" , "< Uhr/Datum >" , "< Bahnstrom >" , "< Gesamtrunden >" , "< Zurueck "}; // Tab Turmlich - Stand 19.09.
lcd.print(line2[auswahl]);
if (oldAuswahl != auswahl)
{
oldAuswahl = auswahl;
DEBUG_PRINT(F("SubMenu Tumranzeige: "));
DEBUG_PRINTLN(line2[auswahl]);
}
}
/* my_xy_Erinnerung: 3 WS RGB -> 2D Array!
byte rgbLicht[3][3] =
{
{55, 20, 0}, // Eingang ab Pixel 0
{0, 50, 0}, // Unten ab Pixel 1
{0, 0, 50} // Oben ab Pixel 3
};
*/
MenuePunkt turmLichtMenu[] PROGMEM
{
{"Eingang"},
{"Licht EG"},
{"Licht OG"},
{"zurueck"},
};
uint8_t turmLicht(bool menuRotary) // Turmleuchten.....
{
const uint8_t rotaryMin = 0; // erster Menupunkt turmLichtMenu[] ist auf 0!
const uint8_t rotaryMax =
sizeof(turmLichtMenu) /
sizeof(turmLichtMenu[0]) - 1; // letzter Menuepunkt aus Anzahl der Eintraege
static bool subMenu = false; // Merker fuer lcd vs. switch/case
static uint8_t tempRotary = 0; // temporäre Aufnahme RotaryWert
if (!menuRotary) // beim ersten Aufruf der Funktion: Grundeinstellung
{
subMenu = false;
tempRotary = 0;
menuRotary = true;
lcd.clear();
lcdMenuLine(0, 2); // schreibt "Turmlicht" in obere Zeile
lcd.blink(); // wenn kein weiteres Menu, kann das entfallen
lcdSubLichtLine(1, tempRotary); // schreibt ersten Menupunkt in untere Zeile
}
if (!subMenu) // noch kein Menu ausgewaehlt
{
uint8_t tikRotary = getRotary(tempRotary, rotaryMin, rotaryMax);
if (tempRotary != tikRotary)
{
tempRotary = tikRotary;
lcdSubLichtLine(1, tikRotary); // untere Zeile im lcd
}
if (r.buttonPressedReleased(bounce))
{
DEBUG_PRINT(F("Button pressed Turmlicht -> Wert: "));
DEBUG_PRINTLN(tikRotary);
subMenu = true; // Ende der Auswahl - gehe zur Auswertung
}
}
if (subMenu) // Fange mit der Auswertung an
{
DEBUG_PRINT(F("Licht "));
switch (tempRotary) // gehe zum ausgewaehlten
{
case rotaryMin: // Turmlicht Eingang
DEBUG_PRINT(F("Eingang"));
// fragt den ersten Pixel ab und schaltet den Stripe um
pixelAnAus(0, !pixel.getPixelColor(0));
subMenu = false; // zetze Merker zurueck
break;
case (rotaryMin+1): // Turmlicht "EG"
DEBUG_PRINTLN(F("EG"));
pixelAnAus(1, !pixel.getPixelColor(1));
subMenu = false; // setze Merker zurück
break;
case (rotaryMin+2): // Turmlicht "OG"
DEBUG_PRINTLN(F("OG"));
pixelAnAus(2, !pixel.getPixelColor(4));
subMenu = false;
break;
case rotaryMax: // zurück zum Hauptmenue
DEBUG_PRINT(F("-> ins Hauptmenu"));
subMenu = false;
menuRotary = 0;
break;
}
if (!subMenu) // Wenn hier der Merker gelöscht...
{
pixel.show(); // Aktuallisiere Stripe
lcdMenuLine(0, 0); // Anzeige letztes Menu
lcdMenuLine(1, 2);
menuRotary = false; // sorgt für Ende des Aufrufs dieser Funktion
}
}
return (menuRotary);
}
void lcdSubLichtLine(const uint8_t line, const uint8_t auswahl) // Inhalt der zweiten Zeile des Lcd-Menu im Lichtmenu
{
lcd.setCursor(0, line);
if (line == 0)
{
lcd.print("*"); DEBUG_PRINT("*");
lcdTurmLichtZentriert(auswahl); DEBUG_PRINT(auswahl);
lcd.print("*"); DEBUG_PRINTLN("*");
}
else if (line == 1)
{
lcdTurmLichtZentriert(auswahl);
}
}
void lcdTurmLichtZentriert(uint8_t ausgabe)
{
Serial.println(ausgabe);
const uint8_t gesamt = lcdRow - 2;
uint8_t vor = 0;
uint8_t nach = 0;
vor = (gesamt - strlen_P(ConstStrPtr(&turmLichtMenu[ausgabe]))) / 2;
nach = gesamt - strlen_P(ConstStrPtr(&turmLichtMenu[ausgabe])) - vor;
for (; vor >= 1; vor--)
{
lcd.print(" "); DEBUG_PRINT(" ");
}
lcd.print(FlashStrPtr(&turmLichtMenu[ausgabe])); DEBUG_PRINT(FlashStrPtr(&turmLichtMenu[ausgabe]));
for (; nach >= 1; nach--)
{
lcd.print(" "); DEBUG_PRINT(" ");
}
DEBUG_PRINTLN();
}
void lcdSubHelligLineTwo(uint8_t menuRotary)
{
lcd.setCursor(0, 1);
lcd.print(F(" Ist=")); // 5 Stellen merken
lcd.print(lumi); // Anzahl Stellen wird errechnet
lcd.print(F(" Soll=")); // 8 Stellen merken
lcd.print(menuRotary); // Stellen wird auch errecnet
uint8_t curPos = 13; // "Ist = " + " Soll = "!!! gemerkt ;)
if (lumi > 99) curPos++; // Jede Stelle gibt einen weiteren +Punkt
if (lumi > 9) curPos++;
curPos++;
if (menuRotary > 99) curPos++;
if (menuRotary > 9) curPos++;
curPos++;
// Bis zum Ende der Zeile löschen:
for (uint8_t i = curPos; i < lcdRow; i++) lcd.print(" "); // Bis zum ende der Zeile Leerzeichen setzen!
lcd.setCursor(curPos - 1, 1); // Ach schau es blinkt!
}
void lcdSubStartanzeigeLineTwo(uint8_t menuRotary)
{
lcd.setCursor(0, 1);
lcd.print(F(" Ist=")); // 5 Stellen merken
lcd.print(SBild); // Anzahl Stellen wird errechnet
lcd.print(F(" Soll=")); // 8 Stellen merken
lcd.print(menuRotary); // Stellen wird auch errecnet
uint8_t curPos = 13; // "Ist = " + " Soll = "!!! gemerkt ;)
if (SBild > 99) curPos++; // Jede Stelle gibt einen weiteren +Punkt
if (SBild > 9) curPos++;
curPos++;
if (menuRotary > 99) curPos++;
if (menuRotary > 9) curPos++;
curPos++;
// Bis zum Ende der Zeile löschen:
for (uint8_t i = curPos; i < lcdRow; i++) lcd.print(" "); // Bis zum ende der Zeile Leerzeichen setzen!
lcd.setCursor(curPos - 1, 1); // Ach schau es blinkt!
}
void lcdSubSpurenLineTwo(uint8_t menuRotary)
{
lcd.setCursor(0, 1);
lcd.print(F(" Ist=")); // 5 Stellen merken
lcd.print(AnzahlSpuren); // Anzahl Stellen wird errechnet
lcd.print(F(" Soll=")); // 8 Stellen merken
lcd.print(menuRotary); // Stellen wird auch errecnet
uint8_t curPos = 13; // "Ist = " + " Soll = "!!! gemerkt ;)
if (AnzahlSpuren > 99) curPos++; // Jede Stelle gibt einen weiteren +Punkt
if (AnzahlSpuren > 9) curPos++;
curPos++;
if (menuRotary > 99) curPos++;
if (menuRotary > 9) curPos++;
curPos++;
// Bis zum Ende der Zeile löschen:
for (uint8_t i = curPos; i < lcdRow; i++) lcd.print(" "); // Bis zum ende der Zeile Leerzeichen setzen!
lcd.setCursor(curPos - 1, 1); // Ach schau es blinkt!
}
void lcdSubIDNummerLineTwo(uint8_t menuRotary)
{
lcd.setCursor(0, 1);
lcd.print(F("Ist=")); // 4 Stellen merken
lcd.print(id); // Anzahl Stellen wird errechnet
lcd.print(F(" Soll=")); // 7 Stellen merken
lcd.print(menuRotary); // Stellen wird auch errecnet
uint8_t curPos = 12; // "Ist = " + " Soll = "!!! gemerkt ;)
if (id > 99) curPos++; // Jede Stelle gibt einen weiteren +Punkt
if (id > 9) curPos++;
curPos++;
if (menuRotary > 99) curPos++;
if (menuRotary > 9) curPos++;
curPos++;
// Bis zum Ende der Zeile löschen:
for (uint8_t i = curPos; i < lcdRow; i++) lcd.print(" "); // Bis zum ende der Zeile Leerzeichen setzen!
lcd.setCursor(curPos - 1, 1); // Ach schau es blinkt!
}
void lcdSubkanalLineTwo(uint8_t menuRotary)
{
lcd.setCursor(0, 1);
lcd.print(F("Ist=")); // 4 Stellen merken
lcd.print(kanal); // Anzahl Stellen wird errechnet
lcd.print(F(" Soll=")); // 6 Stellen merken
lcd.print(menuRotary); // Stellen wird auch errecnet
uint8_t curPos = 11; // "Ist = " + " Soll = "!!! gemerkt ;)
if (id > 99) curPos++; // Jede Stelle gibt einen weiteren +Punkt
if (id > 9) curPos++;
curPos++;
if (menuRotary > 99) curPos++;
if (menuRotary > 9) curPos++;
curPos++;
// Bis zum Ende der Zeile löschen:
for (uint8_t i = curPos; i < lcdRow + 1; i++) lcd.print(" "); // Bis zum ende der Zeile Leerzeichen setzen!
lcd.setCursor(curPos - 1 , 1); // Ach schau es blinkt!
}
void lcdSubSpeichernLineTwo(uint8_t menuRotary)
{
for (uint8_t i = 0; i < 16; i++) lcd.print(" "); // Bis zum ende der Zeile Leerzeichen setzen!
lcd.setCursor(0, 1);
lcd.print(F(" Speichern J/N")); // 15 Stellen merken
uint8_t curPos = 15; // "Ist = " + " Soll = "!!! gemerkt ;)
if (menuRotary == 1) curPos = curPos - 3; // Jede Stelle gibt einen weiteren +Punkt
if (menuRotary == 2) curPos = curPos - 1;
lcd.setCursor(curPos , 1); // Nu schau es blinkt an verschiedenen Stellen!
}
void lcdSubWerksWerteLineTwo(uint8_t menuRotary)
{
for (uint8_t i = 0; i < 16; i++) lcd.print(" "); // Bis zum ende der unteren Zeile Leerzeichen setzen!
lcd.setCursor(0, 1); // Untere Zeile
lcd.print(F("Werkeinstell J/N")); // 16 Stellen
uint8_t curPos = 16; // "J = -3 N = -1)
if (menuRotary == 1) curPos = curPos - 3;
if (menuRotary == 2) curPos = curPos - 1;
lcd.setCursor(curPos , 1); // Nu schau es blinkt an verschiedenen Stellen!
}
// ********** ab hier Renndaten / Display - Verarbeitung *********
void displayKalender() // LCD Start Anzeige und nicht Menü
{
if (minute() != minutealt)
{
minutealt = minute();
char zeileAnzeige[16] = {0};
memset(zeileAnzeige, 0, sizeof(zeileAnzeige - 1));
sprintf(zeileAnzeige, "%s %02u.%02u. %02u:%02u", dayShortStr(weekday()), day(), month(), hour(), minute());
lcd.setCursor(0, 0);
lcd.print(ver);
lcd.setCursor(0, 1);
lcd.print(zeileAnzeige);
DEBUG_PRINTLN(zeileAnzeige);
}
}// Ende Start-Tab
void leseEmpfang() // Lese NFR24 und werte aus
{
if (radio.available())
{
char text[32] = {0};
radio.read(&text, radio.getDynamicPayloadSize());
char *c; // Teilstring
uint8_t zahl = 0;
//Serial.println(text);
//tik();
c = strtok(text, " "); // Lese bis erstes Leerzeichen
if (isDigit(c[0]))
{
uint8_t spur = (c[0] - '0');
switch (c[1])
{
case 'R': // Runde für die Spur
AR[spur] = atoi(strtok(NULL, " "));
break;
case 'Z': // Zeit für die Spur
RZvk[spur] = atoi(strtok(NULL, " "));
RZnk[spur] = atoi(strtok(NULL, " "));
break;
case 'V': // Spannung für die Spur
Voltage[spur] = atoi(strtok(NULL, " "));
break;
case 'F': // Fahrername für die Spur
// strcpy(Fahrer[spur], strtok(NULL, " "));
// strcat(Fahrer[spur], " ");
// strcat(Fahrer[spur], strtok(NULL, " "));
break;
}
}
else // Ab hier nur zeigen Fernkonfiguration
{
switch (c[0])
{
case 'T': // T Zeit für RTC
setTime(atol(strtok(NULL, " "))); // übernimmt den Zeitstempel
RTC.set(now()); // setzt die RTC
break;
case 'C': // C für Celsius Vorkomma
temp = atol(strtok(NULL, " ")); // übernimmt die Temperatur
break;
case 'i':
zahl = atoi(strtok(NULL, " "));
break;
case 'r': // r setzt die Anzeige auf Rundenzeiten
zahl = atoi(strtok(NULL, " "));
if (zahl == id)
{
lcd.clear(); // Lösche gesamte LCD-Display
Wsl = 1; // Anzeige Rundenzeiten
}
break;
case 'l': // l setzt die Anzeige auf Runden
zahl = atoi(strtok(NULL, " "));
if (zahl == id)
{
lcd.clear(); // Lösche gesamte LCD-Display
Wsl = 2; // Anzeige Runden
}
break;
case 'u': // u setzt das Display auf Uhrzeit / Datum / Temperatur
zahl = atoi(strtok(NULL, " "));
if (zahl == id) // Entspricht empfangende Zahl der Empfänger-ID
{
lcd.clear(); // Lösche gesamte LCD-Display
Wsl = 3; // Anzeige Uhrzeit / Datum / Temperatur
}
break;
case 'b': // b setzt das Display auf Bahnstrom
zahl = atoi(strtok(NULL, " "));
if (zahl == id) // Entspricht empfangende Zahl der Empfänger-ID
{
lcd.clear(); // Lösche gesamte LCD-Display
Wsl = 4; // Anzeige Bahnstrom
}
break;
case 'f': // f setzt die Anzeige auf Fahrernamen "BEIM TURM NICHT MÖGLICH"
break;
}
}
}
}
void anzeige() // TAB TM Auswahl Anzeigetafel
{
// *INDENT-OFF*
static uint8_t anzeigeType = 1;
static bool merker = false;
// Auswahl, was angezeigt werden soll mit Wahlschalter links
// Zeiten,Runden,Uhrzeit,Bahnstrom
if (anzeigeType !=Wsl)
{
anzeigeType = Wsl;
merker = false;
}
switch (anzeigeType)
{
case 1:
static uint16_t lastTime[8] = {0};
if (!merker)
{
Serial.println(F("Rundenzeiten"));
lcd.setCursor(0, 1);
lcd.print(F(" Runden-Zeiten "));
clearRight();
clearBrightness();
for (uint8_t i = 1; i < spuren; i++)
{
zeitenAnzeige(i);
}
merker = true;
}
else
{
if ((lastTime[0] != RZvk[1]) || (lastTime[1] != RZnk[1]))
{ zeitenAnzeige(1); lastTime[0] = RZvk[1]; lastTime[1] = RZnk[1]; }
if ((lastTime[2] != RZvk[2]) || (lastTime[3] != RZnk[2]))
{ zeitenAnzeige(2); lastTime[2] = RZvk[2]; lastTime[3] = RZnk[2]; }
if ((lastTime[4] != RZvk[3]) || (lastTime[5] != RZnk[3]))
{ zeitenAnzeige(3); lastTime[4] = RZvk[3]; lastTime[5] = RZnk[3]; }
if ((lastTime[6] != RZvk[4]) || (lastTime[7] != RZnk[4]))
{ zeitenAnzeige(4); lastTime[6] = RZvk[4]; lastTime[7] = RZnk[4]; }
}
break;
case 2:
static uint16_t lastSpuren[maxSpuren + 1] = {0};
if (!merker)
{
Serial.println(F("Rundenanzeige"));
lcd.setCursor(0, 1);
lcd.print(F(" Runden-Anzeige "));
clearLeft();
//spurAnzeigeLinks();
for (uint8_t i = 1; i <= spuren; i++)
{
spurAnzeigeRechts(i);
lastSpuren[i] = AR[i];
}
merker = true;
}
else
{
for (uint8_t i = 1; i <= spuren; i++)
{
if (lastSpuren[i] != AR[i])
{
spurAnzeigeRechts(i);
lastSpuren[i] = AR[i];
}
}
}
break;
case 3:
{
const uint32_t dotTime = 500;
static uint32_t lastMillis = 0;
static int16_t lYear = 0;
static uint8_t lDay, lMonth = 61;
static int8_t ltemp = 0;
static uint8_t lastDot = 2; // Start Merker mit dot AUS
if (!merker)
{
Serial.println(F("Uhranzeige"));
lcd.setCursor(0, 1);
lcd.print(F("Uhrzeit-Anzeige "));
clearRight();
clearBrightness();
uhrAnzeigeLinks();
for (uint8_t i = 1; i < 7; i++) // Init der case 1-7 in uhrAnzeigeRechts //
{
uhrAnzeigeRechts(i);
}
merker = true;
}
else
{
// Begin Erzeugung Dot blinken
if (millis() - lastMillis <= dotTime) // Zeit nicht abgelaufen?
{if (lastDot == 2) { lastDot = uhrAnzeigeRechts(1); }} // DotMerker ist AUS -> dann
else if (lastDot == 1) { lastDot = uhrAnzeigeRechts(2); } // Zeit abgelaufen UND DotMerker ist EIN -> dann
if (millis() - lastMillis >= 1000) { lastMillis = millis(); }// Zeitmerker zurücksetzen
// Ende Erzeugung Dot blinken
if (lDay != day()) { lDay = uhrAnzeigeRechts(3); } // Kalenderdaten aktuallisieren
if (lMonth != month()) { lMonth = uhrAnzeigeRechts(4); }
if (lYear != year()) { lYear = uhrAnzeigeRechts(5); }
if (ltemp != temp) { ltemp = uhrAnzeigeRechts(6); } // Temperatur...
}
}
break;
case 4:
static uint16_t lastVoltage[maxSpuren + 1] = {0};
if (!merker)
{
Serial.println(F("Spannungsanzeige"));
lcd.setCursor(0, 1);
lcd.print(" Bahnstrom ");
clearRight();
clearBrightness();
StromAnzeigeLinks();
for (uint8_t i = 1; i <= spuren; i++)
{
VoltageAnzeigeRechts(i);
lastVoltage[i] = Voltage[i];
}
merker = true;
}
else
{
for (uint8_t i = 1; i <= spuren; i++)
{
if (lastVoltage[i] != Voltage[i])
{
VoltVK[i] = (Voltage[i]) / 10;
VoltNK[i] = (Voltage[i]) - (VoltVK[i] * 10);
if ((VoltNK[i]) < 3) (VoltNK[i]) = 0;
if ((VoltNK[i]) > 2 && (VoltNK[i]) < 8 )(VoltNK[i]) = 5;
if ((VoltNK[i]) > 7)
{
(VoltNK[i]) = 0;
(VoltVK[i])= (VoltVK[i])+ 1;
}
VoltageAnzeigeRechts(i);
lastVoltage[i] = Voltage[i];
}
}
}
break;
case 5:
if (!merker)
{
Serial.println(F("Tages-Rundenanzeige"));
lcd.setCursor(0, 1);
lcd.print(" Gesamtrunden ");
clearAll();
clearBrightness();
Serial.println("case 5");
TagesAnzeigeLinks();
for (uint8_t i = 1; i <= spuren; i++)
{
spurTagesRundenRechts(i);
}
merker = true;
}
else
{
for (uint8_t i = 1; i <= spuren; i++)
{
if (lastTagesrunden[i] != TagZahl[i]){
spurTagesRundenRechts(i);
lastTagesrunden[i] = TagZahl[i];
}
}
}
break;
default:
anzeigeType = 1;
break;
}
// *INDENT-ON*
}
void zeitenAnzeige(const uint8_t spur) // Anzeigetafel links/rechts für Rundenzeiten
{
tmDisp[(spur - 1) * 2].showNumberDec(RZvk[spur]);
tmDisp[(spur - 1) * 2 + 1].showNumberDec(RZnk[spur], true, 3, 0);
}
void uhrAnzeigeLinks() // Anzeigetafel links für Uhr/Datum Anzeige
{
tmDisp[0].setSegments(Uhr);
tmDisp[2].setSegments(Cal);
tmDisp[4].setSegments(Jahr);
tmDisp[6].setSegments(Grad);
}
uint16_t uhrAnzeigeRechts(const uint8_t type) // Anzeigetafel rechts für Uhr/Datum Anzeige
{
// *INDENT-OFF*
uint16_t rueckgabe = 0;
switch (type)
{
case 1: tmDisp[1].showNumberDecEx((hour() * 100) + minute(), 0b01000000, true); rueckgabe = 1; break;
case 2: tmDisp[1].showNumberDecEx((hour() * 100) + minute(), true); rueckgabe = 2; break;
case 3: tmDisp[3].showNumberDec(day(), DEC, 2, 0); rueckgabe = day(); break;
case 4: tmDisp[3].showNumberDec(month(), DEC, 2, 2); rueckgabe = month(); break;
case 5: tmDisp[5].showNumberDec(year()); rueckgabe = year(); break;
case 6: tmDisp[7].showNumberDec(temp, false, 2, 0); tmDisp[7].setSegments(C, 1, 3); rueckgabe = temp; break;
}
return rueckgabe;
// *INDENT-ON*
}
void spurAnzeigeLinks() // Anzeigetafel links für Rundenanzeige
{
tmDisp[0].setSegments(Sp);
tmDisp[2].setSegments(Sp);
tmDisp[4].setSegments(Sp);
tmDisp[6].setSegments(Sp);
teil2AnzeigeLinks();
}
void TagesAnzeigeLinks() // Anzeigetafel links für Gesamtrunden
{
tmDisp[0].setSegments(AL);
tmDisp[2].setSegments(AL);
tmDisp[4].setSegments(AL);
tmDisp[6].setSegments(AL);
teil2AnzeigeLinks();
}
void StromAnzeigeLinks() // Anzeigetafel links für Bahnstrom
{
tmDisp[0].setSegments(U);
tmDisp[2].setSegments(U);
tmDisp[4].setSegments(U);
tmDisp[6].setSegments(U);
teil2AnzeigeLinks();
}
void teil2AnzeigeLinks()
{
tmDisp[0].setSegments(Eins, 1, 3);
tmDisp[2].setSegments(Zwei, 1, 3);
tmDisp[4].setSegments(Drei, 1, 3);
tmDisp[6].setSegments(Vier, 1, 3);
}
void spurTagesRundenRechts(const uint8_t spur) // Anzeigetafel rechts für Gesamtrunden
{
// *INDENT-OFF*
switch (spur)
{
case 1: tmDisp[1].showNumberDec(TagZahl[spur]); break;
case 2: tmDisp[3].showNumberDec(TagZahl[spur]); break;
case 3: tmDisp[5].showNumberDec(TagZahl[spur]); break;
case 4: tmDisp[7].showNumberDec(TagZahl[spur]); break;
}
// *INDENT-ON*
}
void spurAnzeigeRechts(const uint8_t spur) // Anzeigetafel rechts für Rundenanzeige
{
switch (spur)
{
case 1: tmDisp[0].setSegments(Sp, 3, 0);
tmDisp[0].setSegments(Eins, 1, 3);
tmDisp[1].showNumberDec(AR[spur]);
break;
case 2: tmDisp[2].setSegments(Sp, 3, 0);
tmDisp[2].setSegments(Zwei, 1, 3);
tmDisp[3].showNumberDec(AR[spur]); break;
case 3: tmDisp[4].setSegments(Sp, 3, 0);
tmDisp[4].setSegments(Drei, 1, 3);
tmDisp[5].showNumberDec(AR[spur]); break;
case 4: tmDisp[6].setSegments(Sp, 3, 0);
tmDisp[6].setSegments(Vier, 1, 3);
tmDisp[7].showNumberDec(AR[spur]); break;
}
}
void VoltageAnzeigeRechts(const uint8_t spur) // Anzeigetafel rechts für Bahnstrom
{
switch (spur)
{
case 1:
tmDisp[1].showNumberDec(VoltVK[spur], false, 2, 0);
tmDisp[1].setSegments(Komma, 1, 2);
tmDisp[1].showNumberDec(VoltNK[spur], false, 1, 3); break;
case 2:
tmDisp[3].showNumberDec(VoltVK[spur], false, 2, 0);
tmDisp[3].setSegments(Komma, 1, 2);
tmDisp[3].showNumberDec(VoltNK[spur], false, 1, 3); break;
case 3:
tmDisp[5].showNumberDec(VoltVK[spur], false, 2, 0);
tmDisp[5].setSegments(Komma, 1, 2);
tmDisp[5].showNumberDec(VoltNK[spur], false, 1, 3); break;
case 4:
tmDisp[7].showNumberDec(VoltVK[spur], false, 2, 0);
tmDisp[7].setSegments(Komma, 1, 2);
tmDisp[7].showNumberDec(VoltNK[spur], false, 1, 3); break;
}
}
void clearAll() // Anzeigetafel komplett löschen
{
clearLeft();
clearRight();
}
void clearLeft() // Anzeigetafel Links löschen
{
for (uint8_t i = 0; i <= 6; i += 2)
{
tmDisp[i].clear();
}
}
void clearRight() // Anzeigetafel Rechts löschen
{
for (uint8_t i = 1; i <= 7; i += 2)
{
tmDisp[i].clear();
}
}
void Datensicherung() // Prüfen ob Wert sich verändert hat, wenn ja neuen Wert ins EEprom schreiben
{
EEPROM.update(1, lumi);
EEPROM.update(2, kanal);
EEPROM.update(3, id);
EEPROM.update(4, SBild);
EEPROM.update(5, AnzahlSpuren);
for (uint8_t i = 0; i < 3 ; i++)
{
EEPROM.update(i + 10, rgbLicht[0][i]); //Farbe für Eingang
EEPROM.update(i + 20, rgbLicht[1][i]); //Farbe für Erdgeschoss
EEPROM.update(i + 30, rgbLicht[2][i]); //Farbe für Obergeschoss
}
DEBUG_PRINT(F("Ich war bei der Datensicherung"));
}
void Werkseinstellung() // Setzt alle Werte zurück auf Standard
{
// Es werden die Voreinstellungen abgespeichert und neu gestartet!!!
EEPROM.update(1, 2); // Speicheradresse ,Helligkeit (Werte 1 bis 7) Werkseinstellung=2
EEPROM.update(2, 127); // Speicheradresse ,Funkkanal (Werte 1 bis 127)Werkseinstellung=127
EEPROM.update(3, 10); // Speicheradresse ,ID (Werte 1 bis 50) Werkseinstellung=10
EEPROM.update(4, 2); // Speicheradresse ,Startbild (Werte 1 bis 4) Werkseinstellung=2
EEPROM.update(10, 55); // Speicheradresse ,Farbe Rot für Eingang
EEPROM.update(11, 20); // Speicheradresse ,Farbe Grün für Eingang
EEPROM.update(12, 0); // Speichersdresse ,Farbe Blau für Eingang
EEPROM.update(20, 20); // Speichersdresse ,Farbe Rot für Erdgeschoss
EEPROM.update(21, 20); // Speichersdresse ,Farbe Grün Erdgeschoss
EEPROM.update(22, 20); // Speichersdresse ,Farbe Blau für Erdgeschoss
EEPROM.update(30, 25); // Speichersdresse ,Farbe Rot für Obergeschoss
EEPROM.update(31, 25); // Speichersdresse ,Farbe Grün für Obergeschoss
EEPROM.update(32, 25); // Speichersdresse ,Farbe Blau für Obergeschoss
DEBUG_PRINT(F("Werkseinstellungen wurden geladen"));
{
asm volatile (" jmp 0"); // Software-Reset
}
}
void leseEingaenge() // Abfrage Extern für Anzeigetafel und Licht
{
uint32_t jetzt = millis();
static uint32_t vorhin = 0;
const uint32_t intervall = 500;
//uint8_t Wsl_old; // soll aktuelle Wsl vor Chaos merken und dort zurückschalten nach wenn kein Chaos "BAUSTELLE"
// Abfrage der Externeingänge für Turmanzeige
if ((digitalRead(ExternPin[0])) && (ExternAnz_state == 0)) // Extern EingangPin X=Low und kein anderes Extern EingangsSignal für Anzeigetafel
{
ExternAnz_state = 1; // Setze EingangsSignal
Wsl = 1; // Wechsel die Turmanzeige zu Wsl=1 Rundenzeiten
Serial.println(ExternAnz_state);
}
if ((digitalRead(ExternPin[1])) && (ExternAnz_state == 0)) // Extern EingangPin X=Low und kein anderes Extern EingangsSignal für Anzeigetafel
{
ExternAnz_state = 1; // Setze EingangsSignal
Wsl = 2; // Wechsel die Turmanzeige zu Wsl=2 Anzahl Runden
Serial.println("WSL 2");
Serial.println(ExternAnz_state);
}
if ((digitalRead(ExternPin[2])) && (ExternAnz_state == 0)) // extern EingangPin X=Low und kein anderes Extern EingangsSignal für Anzeigetafel
{
ExternAnz_state = 1; // Setze EingangsSignal
Wsl = 3; // Wechsel die Turmanzeige zu Wsl=3 Datum/Uhrzeit
Serial.println(ExternAnz_state);
}
if ((digitalRead(ExternPin[3])) && (ExternAnz_state == 0)) // extern EingangPin X=Low und kein anderes Extern EingangsSignal für Anzeigetafel
{
ExternAnz_state = 1; // Setze EingangsSignal
Serial.println("WSL 4");
Serial.println(ExternAnz_state); // Wechsel die Turmanzeige zu Wsl=4 Bahnstrom
Wsl = 4;
for (uint8_t i = 1; i <= spuren; i++)
{
Voltage[i] = 0; // Setze Anfangswert bis zum ersten Empfang der Daten
}
}
if ((digitalRead(ExternPin[4])) && (ExternAnz_state == 0)) // extern EingangPin X=Low und kein anderes Extern EingangsSignal für Anzeigetafel
{
ExternAnz_state = 1; // Setze EingangsSignal
Serial.println("WSL 5");
Serial.println(ExternAnz_state);
Wsl = 5; // Wechsel die Turmanzeige zu Wsl=5 Tagesrunden
}
if ((!digitalRead(ExternPin[0])) && // Rücksetzen des EingangsSignal
(!digitalRead(ExternPin[1])) && // Erst wenn alle 5 Eingänge HIGH sind wird zurückgesetzt
(!digitalRead(ExternPin[2])) &&
(!digitalRead(ExternPin[3])) &&
(!digitalRead(ExternPin[4])))
{
ExternAnz_state = 0; // EingangsSignal zurückgesetzt
}
// Ab hier Externlicht Abfrage
if ((digitalRead(ExternPin[5])) && ((ExternLich_state[0]) == 0)) // extern EingangPin X=Low und Merker ob Schalter / Taster nicht gedrückt ist
{
pixelAnAus(0, 1); // Schalte Licht Eingang ein
ExternLich_state[0] = 1; // Merker Licht Eingang Schalter / Taster ist gedrückt
}
if ((!digitalRead(ExternPin[5])) && ((ExternLich_state[0]) == 1)) // Abfrage Externeingänge für Turmlicht Eingang Aus
{
pixelAnAus(0, 0); // Schalte Licht Eingang aus
ExternLich_state[0] = 0; // Merker Schalter / Taster nicht mehr gedrückt
}
if ((digitalRead(ExternPin[6])) && ((ExternLich_state[1]) == 0)) // extern EingangPin X=Low und Merker ob Schalter / Taster nicht gedrückt ist
{
pixelAnAus(1, 1); // Schalte Licht Erdgeschoss ein
ExternLich_state[1] = 1; // Merker Licht Erdgeschoss Schalter / Taster ist gedrückt
}
if ((!digitalRead(ExternPin[6])) && ((ExternLich_state[1]) == 1)) // Abfrage Externeingänge für Turmlicht Erdgeschoss Aus
{
pixelAnAus(1, 0); // Schalte Licht Erdgeschoss aus
ExternLich_state[1] = 0; // Merker Schalter / Taster nicht mehr gedrückt
}
if ((digitalRead(ExternPin[7])) && ((ExternLich_state[2]) == 0)) // extern EingangPin X=Low und Merker ob Schalter / Taster nicht gedrückt ist
{
pixelAnAus(2, 1); // Schalte Licht Obergeschoss ein
ExternLich_state[2] = 1; // Merker Licht Obergeschoss Schalter / Taster ist gedrückt
}
if ((!digitalRead(ExternPin[7])) && ((ExternLich_state[2]) == 1)) // Abfrage Externeingänge für Turmlicht Obergeschoss Aus
{
pixelAnAus(2, 0); // Schalte Licht Obergeschoss aus
ExternLich_state[2] = 0; // Merker Schalter / Taster nicht mehr gedrückt
}
if (digitalRead(ExternPin[9])) // extern EingangPin X=Low
{ // Chaos Licht, Alle LED's blinken
Wsl = 3; // Zeige Uhrzeit während Chaostste betätigt ist....später vielleicht eine Chaos Anzeigetafel
ExternLich_state[3] = 1; // Merker Schalter / Taster ist gedrückt
if (jetzt - vorhin >= intervall)
{
vorhin = jetzt;
if (pixel.getPixelColor(1) > 0) //
{
pixel.fill(0, 0); // Alle Pixel ausschalten
}
else
{
pixel.fill(pixel.Color(110, 40, 0), 0, 7); // Pixel Orange setzen - Farbe, ab LED 0, für 7 LED
}
pixel.show(); // Zeige alle Pixel in Orange
}
}
if ((!digitalRead(ExternPin[9])) && ((ExternLich_state[3]) == 1 )) //Abfrage Externeingänge für Turmlicht Chaos blinken = LOW und Merker ob Schalter / Taster gedrückt ist
{
pixel.fill(pixel.Color(0, 0, 0), 0, 7); // Setze alle LED's auf Aus
pixel.show();
ExternLich_state[3] = 0; // Merker Schalter / Taster nicht mehr gedrückt
for (uint8_t i = 0; i < 3; i++)
{
if ((ExternLich_state[i]) == 1) // Prüfen welcher Schalter / Taster gedrückt
{
pixelAnAus(i, 1); // Schalte entsprechende LED's wieder ein
}
}
Wsl = SBild; // Wechsel wieder zu SBild.....Baustelle soll zu Old_Wsl wechseln
}
}
void merkeRunden() // Zählt alle Runden pro Spur zusammen
{
for (uint8_t i = 1; i <= spuren; i++)
{
if ((AR[i] > maxRunden) && (Wsl == 2)) // hat AR[i] mehr Runden gefahren als maxRunden
{
maxRunden = AR[i]; // dann hat AR[i] die meist gefahrenden Runden
poleZeile(i); // Lass entsprechende Zeile heller leuchten
}
if (AR[i] > lastAR[i])
{
TagZahl[i] = TagZahl[i] + AR[i] - lastAR[i];
lastAR[i] = AR[i];
}
else
{
bool neustart = true;
for (byte b = 1; b <= spuren; b++)
{
if (AR[b] >= 1) neustart = false;
}
if (neustart)
{
lastAR[i] = 0;
maxRunden = 0;
}
}
}
}
void poleZeile(const uint8_t pole) // Anzeigetafel rechts für Pole
{
for (byte b = 0; b < sizeof(tmDisp) / sizeof(tmDisp[0]); b++)
{
tmDisp[b].setBrightness(lumi);
}
tmDisp[ (pole - 1) * 2 ].setBrightness(lumiPole);
tmDisp[ ((pole - 1) * 2) + 1 ].setBrightness(lumiPole);
}
void clearBrightness() // Alle TM1637-Anzeigen auf eingestellten bzw. gespeicherten Wert zurücksetzen
{
for (byte d = 0; d < 8; d++)
{
tmDisp[d].setBrightness(lumi);
}
}
[/code]