So, hier ist nun der bereinigte und vollständig kommentierte Code.
Die Verbesserungsvorschläge von mkl0815 sind auch schon vollständig miteingeflossen.
Wer findet den Fehler, der die Uhr nach drücken auf "weiter" wieder auf 0 setzt?
/*
Feuerwerk
Zündung
*/
#include <LiquidCrystal.h>
#include <Time.h>
// Kanäle und Module für Zündung, 7 Kanäle auf 3 Modulen --> 21 Kanäle
#define KANAL_1 2
#define KANAL_2 3
#define KANAL_3 11
#define KANAL_4 12
#define KANAL_5 13
#define KANAL_6 A1
#define KANAL_7 A2
#define MODUL_A A3
#define MODUL_B A4
#define MODUL_C A5
int Kanal[21] =
{KANAL_1, KANAL_2, KANAL_3, KANAL_4, KANAL_5, KANAL_6, KANAL_7, KANAL_1, KANAL_2, KANAL_3, KANAL_4, KANAL_5, KANAL_6, KANAL_7,
KANAL_1, KANAL_2, KANAL_3, KANAL_4, KANAL_5, KANAL_6, KANAL_7};
int Modul[21] =
{MODUL_A, MODUL_A, MODUL_A, MODUL_A, MODUL_A, MODUL_A, MODUL_A, MODUL_B, MODUL_B, MODUL_B, MODUL_B, MODUL_B, MODUL_B, MODUL_B,
MODUL_C, MODUL_C, MODUL_C, MODUL_C, MODUL_C, MODUL_C, MODUL_C};
// Variablen die den Ablauf steuern
int i = 0; // wird nach jeder Zündung erhöht
int anzahlzuender = 7; // Anzahl der Kanäle die tatsächlich genutzt werden
int Start = 0; // solange Wert 0 bleibt, läuft Loop nicht. Wird durch drücken des Startknopfs erhöht
int UhrenStart = 0; // wird nach Start der Uhr erhöht und verhindert somit, dass die Uhr nicht noch einmal bei neu anfängt zu laufen
unsigned int Ende = 0; // sobald Wert 1 ist, wird Display gelöscht und Ende-Nachricht erstellt
unsigned int Pause = 0; // solange 0 läuft die Feuerwerks-Routine, sobald 1 wird diese angehalten
unsigned int Feuer = 1; // Variable um den jeweiligen Zünder auf dem Display zu bennenen, wird nach jeder Zündung erhöht
unsigned long prev_time; // wird für die Uhren und Countdown Routine benötigt
unsigned long feuerdauer; // soll die die Zeit in der der jeweilige Pin auf HIGH steht begrenzen
// Werte für LCD-Display
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Pins, die LCD ansteuern
int lcd_key = 0; // LCD-Buttons
int adc_key_in = 0; // Wert des analogen Eingangs der die Displayknöpfe überwacht
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
// Zeitvariablen
time_t t; // dient dem speichern der Zeit sobald Pause Taste gedrückt wird
time_t dif; // berechnet die Zeit bis zum Abschuss des nächsten Zünders
time_t z[7] ={5,10,15,20,25,30,35}; // die einzelen Zündzeitpunkte
void setup() {
pinMode(KANAL_1, OUTPUT);
pinMode(KANAL_2, OUTPUT);
pinMode(KANAL_3, OUTPUT);
pinMode(KANAL_4, OUTPUT);
pinMode(KANAL_5, OUTPUT);
pinMode(KANAL_6, OUTPUT);
pinMode(KANAL_7, OUTPUT);
pinMode(MODUL_A, OUTPUT);
pinMode(MODUL_B, OUTPUT);
pinMode(MODUL_C, OUTPUT);
lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("Feuerwerk");
delay(2000);
lcd.clear();
lcd.print("Start Show?");
prev_time=millis();
} // beendet setup
void loop() {
readButtons(); // Wartet auf Tastendruck
if(lcd_key == btnSELECT) //Starttaste gedrückt
{
Start++;
}
if(Start >= 1 && Ende == 0) //Hauptroutine, die durch Betätigung des Startknopfs losläuft
{
if(UhrenStart == 0) // Führt Uhren-Reset herbei, nur beim ersten drücken des Startknopfes!
{
lcd.clear();
setTime(0,0,0,1,1,1970);
UhrenStart++;
} // beendet Uhr-Reset
if((millis()-prev_time)>999 && Pause == 0) // Ruft Uhren- und Countdownsubroutine im Sekundentakt auf
{
digitalUhrAnzeige();
Countdown();
prev_time=millis();
} // beendet Uhren und Countdown Routine
if (Pause == 0)
{
Feuerwerk(); //Subroutine-Feuerwerk
} //beendet Subroutinenaufruf
if (lcd_key == btnLEFT) //Left, bzw. PauseTaste
{
Pause = 1;
time_t t = now();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("mit Zuender ");
lcd.setCursor(11,0);
lcd.print(" ");
lcd.print(Feuer);
lcd.setCursor(0,1);
lcd.print("weiter?");
lcd.print(" ");
printZiffernGenulltOhnePunkt(minute(t));
printZiffernGenulltmitPunkt(second(t));
} // beendet Pause Routine
if (lcd_key == btnRIGHT) // Right, bzw. WeiterTaste
{
lcd.clear();
Pause = 0;
setTime(t);
lcd.setCursor(0, 1);
lcd.print(" Zuender");
lcd.print(Feuer);
}
} // beendet die Routine, die durch Start ausgelöst wird
} // beendet den gesamten Loop
void Feuerwerk(){ //Subroutine für Feuerwerk
if(i == 0)
{
lcd.setCursor(0, 1);
lcd.print(" Zuender");
lcd.print(Feuer);
}
if(now() == z[i] && i <= anzahlzuender)
{
lcd.setCursor(0, 1);
lcd.print("Feuer"); // Zeigt aktuelle Zündung auf LCD an
lcd.print(Feuer);
feuerdauer=millis();
while(millis() - feuerdauer < 30) // Begrenzt Zeit in der Pin auf HIGH steht auf 30ms
{
digitalWrite(Kanal[i], HIGH);
digitalWrite(Modul[i], HIGH);
}
digitalWrite(Kanal[i], LOW); //schaltet nach 30ms Pin auf LOW
digitalWrite(Modul[i], LOW); //schaltet nach 30ms Pin auf LOW
Feuer ++;
i=i+1;
}
if(now()==(z[i-1]+1)) // entfernt aktuelle Zündung 1 Sekunde später von LCD
{
lcd.setCursor(0, 1);
lcd.print(" Zuender"); // zeigt dafür nächsten Zünder an
lcd.print(Feuer);
}
if(now() == (z[(anzahlzuender-1)]+2)) // sobald alle Zünder gezündet haben, wird das Programm beendet
{ // und die Ende Nachricht erscheint auf dem Display
lcd.setCursor(7,0); // mit der Anzeige wie viele Zünder gezündet wurden
lcd.print(" Ende ");
lcd.setCursor(0, 1);
printZiffernGenulltOhnePunkt(Feuer);
lcd.print(" Zuendungen ");
Ende++;
}
}
void digitalUhrAnzeige(){ // Subroutine für Uhrenanzeige
lcd.setCursor(0, 0);
printZiffernGenulltOhnePunkt(minute()); // Subroutine, die den Minuten eine 0 voranstellt, falls einstellig
printZiffernGenulltmitPunkt(second()); // Subroutine, die den Sekunden : und 0 voranstellt, falls einstellig
} // beendet Subroutine Uhr
void printZiffernGenulltOhnePunkt(int zahl){ // definiert Subroutine Minuten
if(zahl < 10) // wenn kleiner als 10 ...
{
lcd.print("0");
}
lcd.print(zahl);
} // beendet Subroutine Minuten
void printZiffernGenulltmitPunkt(int zahl){ // definiert Subroutine Sekunden
lcd.print(":");
if(zahl < 10) // wenn kleiner als 10 ...
{
lcd.print('0');
}
lcd.print(zahl);
} // beendet Subroutine Sekunden
void Countdown(){ // Subroutine Countdown
time_t dif=z[i]-now();
lcd.setCursor(11,0);
printZiffernGenulltOhnePunkt(dif);
} // beendet Subroutine Countdown
void readButtons(){ // Liest LCD Buttons vom analogen Eingang
lcd_key = read_LCD_buttons(); // Buttons auslesen
} // beendet Read-Buttons
int read_LCD_buttons() // Variablen-Funktion um auszulesen, welcher Knopf gedrückt wird
{
adc_key_in = analogRead(0); // Sensorwert auslesen
// Die Standardwerte sind: 0, 144, 329, 504, 741
// zur Sicherheit wird ein bisschen aufgerundet
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195 && adc_key_in > 60) return btnUP;
if (adc_key_in < 380 && adc_key_in > 200) return btnDOWN;
if (adc_key_in < 555 && adc_key_in > 390) return btnLEFT;
if (adc_key_in < 790 && adc_key_in > 560) return btnSELECT;
return btnNONE; // Falls gar kein Wert ausgelesen wird
} // beendet Button-Sensor Funktion