#include <Arduino.h>
#include <stdio.h>
#include <stdint.h>
enum menuStates {
home,
aufgabe1,
aufgabe2,
aufgabe3
};
typedef struct {
bool isDisplayed;
menuStates state;
}menu;
enum lights_state {
trafficLightRed,
trafficLightRedYellow,
trafficLightGreen,
trafficLightYellow,
stateNone
};
enum lights_event {
eventTick
};
struct lights_context {
enum lights_state state;
uint8_t requestGreen;
uint32_t greenLED;
uint32_t yellowLED;
uint32_t redLED;
uint16_t tick_cnt;
};
void turnOnRedLight(int pin) {
digitalWrite(pin, HIGH);
// Serial.print("Red light on at pin ");
// Serial.println(pin);
}
void turnOffRedLight(int pin) {
digitalWrite(pin, LOW);
// Serial.print("Red light off at pin ");
// Serial.println(pin);
}
void turnOnYellowLight(int pin) {
digitalWrite(pin, HIGH);
// Serial.print("Yellow light on at pin ");
// Serial.println(pin);
}
void turnOffYellowLight(int pin) {
digitalWrite(pin, LOW);
// Serial.print("Yellow light off at pin ");
// Serial.println(pin);
}
void turnOnGreenLight(int pin) {
digitalWrite(pin, HIGH);
// Serial.print("Green light on at pin ");
// Serial.println(pin);
}
void turnOffGreenLight(int pin) {
digitalWrite(pin, LOW);
// Serial.print("Green light off at pin ");
// Serial.println(pin);
}
void displayMenu(menu * m) {
if (!m->isDisplayed) {
Serial.println("Wählen Sie einen Eintrag per Eingabe der Nummer:");
Serial.println("1. Auslesen des Leucht-Zustands einer Ampel");
Serial.println("2. Auslesen des Request-Zustands einer Ampel");
Serial.println("3. Setzen des Requests bei einer Ampel");
Serial.print("Auswahl: ");
}
m->isDisplayed = true;
}
void init_menu(menu * m) {
m->isDisplayed = false;
m->state = home;
}
void empty_Buffer() {
while (Serial.available() > 0) {
Serial.read(); // Liest und ignoriert alle Daten im Puffer falls hier noch welche übrig sind.
}
}
void process_menu(menu * m, int input, struct lights_context *ctx, struct lights_context *ctx2) {
switch (m->state) {
case home:
switch (input) {
case 1:
m->state = aufgabe1;
break;
case 2:
m->state = aufgabe2;
break;
case 3:
m->state = aufgabe3;
break;
default:
Serial.println("No state selected!");
break;
}
if (m->state != home) {Serial.println("Ampel 1 oder Ampel 2?");}
break;
case aufgabe1:
Serial.println("Aktueller Leuchtzustand: ");
if (input == 1) {
Serial.print("Rot: ");
Serial.println(digitalRead(ctx->redLED) ? "HIGH" : "LOW");
Serial.print("Gelb: ");
Serial.println(digitalRead(ctx->yellowLED) ? "HIGH" : "LOW");
Serial.print("Grün: ");
Serial.println(digitalRead(ctx->greenLED) ? "HIGH" : "LOW");
} else if (input == 2) {
Serial.print("Rot: ");
Serial.println(digitalRead(ctx2->redLED) ? "HIGH" : "LOW");
Serial.print("Gelb: ");
Serial.println(digitalRead(ctx2->yellowLED) ? "HIGH" : "LOW");
Serial.print("Grün: ");
Serial.println(digitalRead(ctx2->greenLED) ? "HIGH" : "LOW");
}
Serial.println();
init_menu(m);
break;
case aufgabe2:
Serial.println(ctx->requestGreen == 1 ? "Grünphase wurde angefragt" : "Grünphase wurde nicht angefragt");
Serial.println();
init_menu(m);
break;
case aufgabe3:
if(input == 1) {
ctx->requestGreen = 1;
} else if (input == 2) {
ctx2->requestGreen = 1;
}
Serial.println();
init_menu(m);
default:
break;
}
empty_Buffer();
}
void enter_action(struct lights_context* ctx) {
switch(ctx->state) {
case trafficLightRed:
turnOnRedLight(ctx->redLED);
break;
case trafficLightRedYellow:
turnOnRedLight(ctx->redLED);
turnOnYellowLight(ctx->yellowLED);
break;
case trafficLightGreen:
turnOnGreenLight(ctx->greenLED);
break;
case trafficLightYellow:
turnOnYellowLight(ctx->yellowLED);
break;
default:
break;
}
}
void exit_action(struct lights_context* ctx) {
switch (ctx->state) {
case trafficLightRed:
turnOffRedLight(ctx->redLED);
break;
case trafficLightRedYellow:
turnOffRedLight(ctx->redLED);
turnOffYellowLight(ctx->yellowLED);
break;
case trafficLightGreen:
turnOffGreenLight(ctx->greenLED);
break;
case trafficLightYellow:
turnOffYellowLight(ctx->yellowLED);
break;
default:
break;
}
}
void lights_process_event(struct lights_context* ctx) {
enum lights_state next = stateNone;
ctx->tick_cnt++;
delay(1);
switch(ctx->state) {
case trafficLightRed:
if(ctx->requestGreen) {
next = trafficLightRedYellow;
}
break;
case trafficLightRedYellow:
if(ctx->tick_cnt > 3000) {
next = trafficLightGreen;
}
break;
case trafficLightGreen:
if(ctx->tick_cnt > 6000) {
next = trafficLightYellow;
}
break;
case trafficLightYellow:
if(ctx->tick_cnt > 3000) {
next = trafficLightRed;
ctx->requestGreen = 0;
}
break;
default:
break;
}
if (next != stateNone && ctx->state != next) {
exit_action(ctx);
ctx->state = next;
enter_action(ctx);
ctx->tick_cnt = 0;
}
}
void init_context(struct lights_context* ctx) {
ctx->state = trafficLightRed;
ctx->requestGreen = 0;
ctx->tick_cnt = 0;
}
int button = 35;
int buttonState;
struct lights_context sm1;
struct lights_context sm2;
menu myMenu;
void setup() {
pinMode(2, OUTPUT);
pinMode(0, OUTPUT);
pinMode(4, OUTPUT);
pinMode(12, OUTPUT);
pinMode(14, OUTPUT);
pinMode(27, OUTPUT);
pinMode(button, INPUT);
Serial.begin(9600);
init_context(&sm1);
sm1.greenLED = 2;
sm1.yellowLED = 0;
sm1.redLED = 4;
enter_action(&sm1);
init_context(&sm2);
sm2.greenLED = 12;
sm2.yellowLED = 14;
sm2.redLED = 27;
enter_action(&sm2);
init_menu(&myMenu);
}
void loop() {
displayMenu(&myMenu);
if (Serial.available() > 0) {
int input = Serial.parseInt();
process_menu(&myMenu, input, &sm1, &sm2);
}
buttonState = digitalRead(button);
if (sm1.requestGreen) {
lights_process_event(&sm1);
}
if (sm2.requestGreen) {
lights_process_event(&sm2);
}
if (buttonState == HIGH && !sm1.requestGreen && !sm2.requestGreen) {
sm1.requestGreen = 1;
sm2.requestGreen = 1;
lights_process_event(&sm1);
lights_process_event(&sm2);
}
}