# include <Wire.h>
////////////////// Display //////////////////////////
#include <LiquidCrystal_I2C.h>
//# include <LiquidCrystal_I2C.h> //LCD Modul aufrufen
LiquidCrystal_I2C lcd(0x27, 20, 4);
////////////////////Urzeit Datum ///////////////////
# include <RTClib.h> // Uhrzeit Modul aufrufen
#include "TimeLib.h"
# include "Uhr_RTC.h"
//////////////////// Temperatur ////////////////////
# include <SimpleDHT.h>
# include "Temperatur_DHT22.h"
//////////////////// Ultraschall ///////////////////
# include "Ultraschall.h" // Ultraschall Modul starten
//////////////////// Menü Drehregler ///////////////
# include "ClassRotMenue.h"
# include "rotary.h";
# include "menue.h" // das Menü selber
/////////////////////Wochenplaner ///////////////////
# include "wochenplan.h"
/////////////////////////////////////////////////////
/*
void setup()
{
Serial.begin(115200);// serial Monitor starten
//////////////LCD Display Starten ///////////////
// pinMode(Ultra_SENDEN, OUTPUT);
// pinMode(Ultra_ECHO, INPUT);
// LCD starten
lcd.init();
lcd.backlight();
//////////////LCD Display Starten Ende ///////////////
// auf serielle Verbindung warten
Serial.println("Programm Start");
}
void loop()
{
Uhrzeit_Anzeigen();
Ultraschall_messen();
Temperatur_Anzeige();
wochenplan();
}
void Menue_aufruf(void) {
if (digitalRead(Encoder_Taster) == 0)
{
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Enter ");
menue();
// hier muss das was man will bestädigt werden
}
}*/
/*
ec2021 - Beispiel für die Anwendung der Klasse RotMenue
*/
// Verschiedene - zum Teil über den Encoder anwählbare -
// States einer beispielhaften State Machine
// a) Hauptmenü zur Auswahl der Submenüs
// - Ansteuerung einer grünen Led
// - Ansteuerung einer roten Led
// - Ansteuerung eines Buzzers
// b) In den Submenüs für die Leds
// - Einschalten der Led
// - Ausschalten der Led
// - Rückkehr ins Hauptmenü
// c) In dem Submenü für den Buzzer
// - Auslösen eines Tones 262 Hz für 250 ms
// - Rückkehr ins Hauptmenü
enum MenueStates{
MAIN, // Zustand Hauptmenü
SUBGREEN, // Submenü Grüne Led
SUBGREENON, // Einschalten der grünen Led -> automatisch zurück Submenü Grüne Led
SUBGREENOFF, // Ausschalten der grünen Led -> automatisch zurück Submenü Grüne Led
SUBRED, // Submenü Rote Led
SUBREDON, // Einschalten der Roten Led -> automatisch zurück Submenü Rote Led
SUBREDOFF, // Ausschalten der Roten Led -> automatisch zurück Submenü Rote Led
SUBBUZZER, // Submenü Buzzer
SUBBUZZERTONE // Auslösen des Tones -> automatisch zurück zu SUBBUZZER
};
// Pinbelegung
const int clkPin = 2; // CLK Anschluss des Encoders
const int dtPin = 3; // DT Anschluss des Encoders
const int swPin = 4; // SW Anschluss des Encoders
const int GreenLedPin = 5; // Grüne Led
const int RedLedPin = 6; // Rote Led
const int buzzerPin = 8; // Buzzer
int state = MAIN; // Startzustand der State Machine
// Instanziieren der verschiedenen Menüobjekte
RotMenue HauptMenue(clkPin,dtPin, swPin);
RotMenue GreenLedMenue(clkPin,dtPin, swPin);
RotMenue RedLedMenue(clkPin,dtPin, swPin);
RotMenue BuzzerMenue(clkPin,dtPin, swPin);
void setup() {
Serial.begin(115200);
pinMode(GreenLedPin, OUTPUT);
pinMode(RedLedPin, OUTPUT);
// Mit true oder false kann im Folgenden für alle Menüs
// das Verhalten "endlos durchwählen" oder "Anschlag links/rechts"
// gewählt werden; Default wäre "true" also endloses Durchwählen
boolean Revolve = false;
HauptMenue.SetRevolving(Revolve);
// Hier werden die Einträge des "Hauptmenüs" eingegeben
// Der State neben der Bezeichnung legt fest, welcher Zustand
// vom Menü mit HeuptMenue.ActMenueState() zurückgegeben wird.
HauptMenue.Add("Control Green Led",SUBGREEN);
HauptMenue.Add("Control Red Led",SUBRED);
HauptMenue.Add("Control Buzzer",SUBBUZZER);
// Submenü für die Grüne Led
// Hier wird (wie auch bei den weiteren Submenüs)
// mit dem Eintrag "Back to..." und MAIN die Möglichkeit
// gegeben, wieder ins Hauptmenü zu kommen
// Praktisch könnte man aber von hier aus aber auch
// in weitere Submenüs wechseln.
// Die Möglichkeiten dazu werden im Hauptsketch verwaltet,
// für das Objekt sind Zusammenhänge wie Haupt-, Sub- oder Subsub-Menü
// transparent.
GreenLedMenue.SetRevolving(Revolve);
GreenLedMenue.Add("Green On",SUBGREENON);
GreenLedMenue.Add("Green Off",SUBGREENOFF);
GreenLedMenue.Add("Back to Main Menue",MAIN);
// Submenü für die Rote Led
RedLedMenue.SetRevolving(Revolve);
RedLedMenue.Add("Red On",SUBREDON);
RedLedMenue.Add("Red Off",SUBREDOFF);
RedLedMenue.Add("Back to Main Menue",MAIN);
// Submenü für den Buzzer
BuzzerMenue.SetRevolving(Revolve);
BuzzerMenue.Add("Tone 262 Hz for 250 msec",SUBBUZZERTONE);
BuzzerMenue.Add("Back to Main Menue",MAIN);
// Startzustand sicherheitshalber hier nochmals gesetzt
state = MAIN;
}
void loop() {
StateMachine();
}
void StateMachine(){
switch(state){
case MAIN : ActMenue(HauptMenue);
break;
case SUBGREEN : ActMenue(GreenLedMenue);
break;
case SUBGREENON : digitalWrite(GreenLedPin,HIGH);
state = SUBGREEN;
break;
case SUBGREENOFF : digitalWrite(GreenLedPin,LOW);
state = SUBGREEN;
break;
case SUBRED : ActMenue(RedLedMenue);
break;
case SUBREDON : digitalWrite(RedLedPin,HIGH);
state = SUBRED;
break;
case SUBREDOFF : digitalWrite(RedLedPin,LOW);
state = SUBRED;
break;
case SUBBUZZER : ActMenue(BuzzerMenue);
break;
case SUBBUZZERTONE : tone(buzzerPin, 262, 250); // Freq 252, Dauer 250 msec
state = SUBBUZZER;
break;
default : state = MAIN;
break;
}
}
// Diese Funktion erledigt die Abfrage, ob der Encoder
// gedreht und ob der Taster betätigt wurde und gibt dies
// bei positivem Ergebnis über Serial aus. Hier würde man ggf.
// Routinen zur Ausgabe eines Displays einfügen.
//
// Außerden wird bei Bestätigung durch den Taster (confirmed())
// der Zustand der State Machine auf den Wert gesetzt, der dem
// aktuell ausgewählten Menüpunkt zugewiesen wurde.
// Auf diese Weise gelangt die State Machine dann ggf. in einen
// neuen Zustand (siehe die enums oben)
//
void ActMenue(RotMenue &aMenue){
if (aMenue.StateHasChanged() || aMenue.Changed()) {
Serial.print(aMenue.ActMenueNo());
Serial.print("\t");
Serial.println(aMenue.ActMenueName());
}
if (aMenue.confirmed()) {
Serial.println(" Confirmed Menue\t"+aMenue.ActMenueName());
state = aMenue.ActMenueState();
}
}