Compare commits
No commits in common. "43497376cbcbe6ef18a460a5bdac99b377d18174" and "73c0795e502fd9ec5211f032ae75ed1719395b36" have entirely different histories.
43497376cb
...
73c0795e50
@ -1,202 +0,0 @@
|
|||||||
# Doppelmayr Modell-Seilbahn
|
|
||||||
|
|
||||||
Arduino-basierte Steuerung einer Doppelmayr Modell-Seilbahn. Die Steuerung bildet das Bedienpanel einer echten Anlage nach — mit Taster-LED-Kombinationen, Betriebsmodi und einer vollständigen Fahrtrichtungssteuerung.
|
|
||||||
|
|
||||||
## Hardware
|
|
||||||
|
|
||||||
**Mikrocontroller:** Arduino Mega 2560
|
|
||||||
|
|
||||||
**Bedienpanel:**
|
|
||||||
|
|
||||||
| Taster / LED | Funktion |
|
|
||||||
|----------------------------|-------------------------------------------------------|
|
|
||||||
| Anlage Ein/Aus | Anlage ein- und ausschalten |
|
|
||||||
| Station Besetzt/Unbesetzt | Stationsstatus anzeigen |
|
|
||||||
| Servicebetrieb | In den Servicemodus wechseln |
|
|
||||||
| Fahrgastbetrieb | In den Fahrgastmodus wechseln |
|
|
||||||
| Quittieren | Zustandswechsel bestätigen |
|
|
||||||
| Start | Fahrt starten |
|
|
||||||
| Halt | Anlage anhalten |
|
|
||||||
| Nothalt | Anlage sofort stoppen |
|
|
||||||
| Vorwärts | Fahrtrichtung Vorwärts wählen |
|
|
||||||
| Rückwärts | Fahrtrichtung Rückwärts wählen |
|
|
||||||
|
|
||||||
**Ereignisanzeige (3-farbig, ohne Taster):**
|
|
||||||
|
|
||||||
| LED | Bedeutung |
|
|
||||||
|-------|----------------------------------|
|
|
||||||
| Rot | Servicebetrieb aktiv |
|
|
||||||
| Gelb | Zustandswechsel wartet auf Quittierung |
|
|
||||||
| Grün | Fahrgastbetrieb aktiv |
|
|
||||||
|
|
||||||
## Pinbelegung
|
|
||||||
|
|
||||||
| Signal | Pin |
|
|
||||||
|-----------------------------|-----|
|
|
||||||
| LED Anlage Ein/Aus | 2 |
|
|
||||||
| Taster Anlage Ein/Aus | 3 |
|
|
||||||
| LED Station | 4 |
|
|
||||||
| Taster Station | 5 |
|
|
||||||
| LED Servicebetrieb | 6 |
|
|
||||||
| Taster Servicebetrieb | 7 |
|
|
||||||
| LED Quittieren | 9 |
|
|
||||||
| Taster Quittieren | 10 |
|
|
||||||
| LED Grün Ereignisanzeige | 11 |
|
|
||||||
| LED Gelb Ereignisanzeige | 12 |
|
|
||||||
| LED Rot Ereignisanzeige | 13 |
|
|
||||||
| LED Fahrgastbetrieb | 22 |
|
|
||||||
| Taster Fahrgastbetrieb | 23 |
|
|
||||||
| LED Vorwärts | 30 |
|
|
||||||
| Taster Vorwärts | 31 |
|
|
||||||
| LED Rückwärts | 32 |
|
|
||||||
| Taster Rückwärts | 33 |
|
|
||||||
| LED Start | 36 |
|
|
||||||
| Taster Start | 37 |
|
|
||||||
| LED Halt | 38 |
|
|
||||||
| Taster Halt | 39 |
|
|
||||||
| LED Nothalt | 40 |
|
|
||||||
| Taster Nothalt | 41 |
|
|
||||||
|
|
||||||
## Software
|
|
||||||
|
|
||||||
### Architektur
|
|
||||||
|
|
||||||
```
|
|
||||||
main.cpp
|
|
||||||
└── CMainController
|
|
||||||
├── CEventQueue (zentrale Event-Queue)
|
|
||||||
├── CButton × 10 (je ein Objekt pro Taster/LED-Paar)
|
|
||||||
└── Zustandsmaschinen (AnlagenZustand + FahrtRichtung)
|
|
||||||
```
|
|
||||||
|
|
||||||
Die Steuerung basiert auf einer **Event-Queue**: Jeder `CButton` erkennt Tastendrücke per Flankenauswertung mit Entprellung und schreibt einen `SEvent` in die zentrale Queue. Der `CMainController` verarbeitet diese Events jeden Loop-Durchlauf und aktualisiert die Zustände sowie alle LEDs.
|
|
||||||
|
|
||||||
**Loop-Ablauf in `CMainController::work()`:**
|
|
||||||
1. `pollButtons()` — alle relevanten Buttons abfragen, Events in Queue schreiben
|
|
||||||
2. `processEvents()` — Events aus Queue lesen, Zustand ändern
|
|
||||||
3. `updateLEDs()` — alle LEDs anhand des aktuellen Zustands setzen
|
|
||||||
|
|
||||||
### LED-Modi
|
|
||||||
|
|
||||||
LEDs können drei Zustände haben, die in `CButton` verwaltet werden:
|
|
||||||
|
|
||||||
| Modus | Verhalten |
|
|
||||||
|----------------|------------------------------------|
|
|
||||||
| `LEDMode::OFF` | Aus |
|
|
||||||
| `LEDMode::ON` | Dauerhaft an |
|
|
||||||
| `LEDMode::BLINK` | Blinkt (500 ms Intervall) |
|
|
||||||
|
|
||||||
Alle LEDs im `BLINK`-Modus blinken synchron, da der Blink-Timer als `static` Member in `CButton` für alle Instanzen geteilt wird.
|
|
||||||
|
|
||||||
### Zustandsmaschinen
|
|
||||||
|
|
||||||
#### AnlagenZustand
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
stateDiagram-v2
|
|
||||||
[*] --> AUS
|
|
||||||
|
|
||||||
AUS --> SERVICE : BTN_ANLAGE_EIN_AUS
|
|
||||||
|
|
||||||
SERVICE --> AUS : BTN_ANLAGE_EIN_AUS
|
|
||||||
SERVICE --> FAHRGAST_QUITTIEREN : BTN_FAHRGAST
|
|
||||||
|
|
||||||
FAHRGAST_QUITTIEREN --> AUS : BTN_ANLAGE_EIN_AUS
|
|
||||||
FAHRGAST_QUITTIEREN --> FAHRGAST : BTN_QUIT
|
|
||||||
|
|
||||||
FAHRGAST --> AUS : BTN_ANLAGE_EIN_AUS
|
|
||||||
FAHRGAST --> SERVICE_QUITTIEREN : BTN_SERVICE
|
|
||||||
|
|
||||||
SERVICE_QUITTIEREN --> AUS : BTN_ANLAGE_EIN_AUS
|
|
||||||
SERVICE_QUITTIEREN --> SERVICE : BTN_QUIT
|
|
||||||
```
|
|
||||||
|
|
||||||
#### FahrtRichtung
|
|
||||||
|
|
||||||
Aktiv wenn `AnlagenZustand == SERVICE` oder `AnlagenZustand == FAHRGAST`.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
stateDiagram-v2
|
|
||||||
[*] --> HALT
|
|
||||||
|
|
||||||
HALT --> VORWAERTS_QUITTIEREN : BTN_VORWAERTS
|
|
||||||
HALT --> RUECKWAERTS_QUITTIEREN : BTN_RUECKWAERTS
|
|
||||||
HALT --> WARTE_START_VORWAERTS : BTN_QUIT\n[vorherigeRichtung != RUECKWAERTS]
|
|
||||||
HALT --> WARTE_START_RUECKWAERTS : BTN_QUIT\n[vorherigeRichtung == RUECKWAERTS]
|
|
||||||
|
|
||||||
NOTHALT --> VORWAERTS_QUITTIEREN : BTN_VORWAERTS
|
|
||||||
NOTHALT --> RUECKWAERTS_QUITTIEREN : BTN_RUECKWAERTS
|
|
||||||
NOTHALT --> WARTE_START_VORWAERTS : BTN_QUIT\n[vorherigeRichtung != RUECKWAERTS]
|
|
||||||
NOTHALT --> WARTE_START_RUECKWAERTS : BTN_QUIT\n[vorherigeRichtung == RUECKWAERTS]
|
|
||||||
|
|
||||||
VORWAERTS_QUITTIEREN --> WARTE_START_VORWAERTS : BTN_QUIT
|
|
||||||
VORWAERTS_QUITTIEREN --> RUECKWAERTS_QUITTIEREN : BTN_RUECKWAERTS
|
|
||||||
VORWAERTS_QUITTIEREN --> HALT : BTN_HALT
|
|
||||||
VORWAERTS_QUITTIEREN --> NOTHALT : BTN_NOTHALT
|
|
||||||
|
|
||||||
WARTE_START_VORWAERTS --> VORWAERTS : BTN_START
|
|
||||||
|
|
||||||
VORWAERTS --> HALT : BTN_HALT
|
|
||||||
VORWAERTS --> NOTHALT : BTN_NOTHALT
|
|
||||||
|
|
||||||
RUECKWAERTS_QUITTIEREN --> WARTE_START_RUECKWAERTS : BTN_QUIT
|
|
||||||
RUECKWAERTS_QUITTIEREN --> VORWAERTS_QUITTIEREN : BTN_VORWAERTS
|
|
||||||
RUECKWAERTS_QUITTIEREN --> HALT : BTN_HALT
|
|
||||||
RUECKWAERTS_QUITTIEREN --> NOTHALT : BTN_NOTHALT
|
|
||||||
|
|
||||||
WARTE_START_RUECKWAERTS --> RUECKWAERTS : BTN_START
|
|
||||||
|
|
||||||
RUECKWAERTS --> HALT : BTN_HALT
|
|
||||||
RUECKWAERTS --> NOTHALT : BTN_NOTHALT
|
|
||||||
```
|
|
||||||
|
|
||||||
## PlatformIO
|
|
||||||
|
|
||||||
Das Projekt verwendet [PlatformIO](https://platformio.org) als Build-System — eine Alternative zur Arduino IDE mit deutlich besserer Projekt- und Bibliotheksverwaltung.
|
|
||||||
|
|
||||||
### Voraussetzungen
|
|
||||||
|
|
||||||
- [VS Code](https://code.visualstudio.com/) mit der [PlatformIO-Extension](https://marketplace.visualstudio.com/items?itemName=platformio.platformio-ide)
|
|
||||||
- oder PlatformIO Core (CLI) via `pip install platformio`
|
|
||||||
|
|
||||||
### Projekt bauen und flashen
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Projekt kompilieren
|
|
||||||
pio run
|
|
||||||
|
|
||||||
# Auf den Arduino flashen (USB)
|
|
||||||
pio run --target upload
|
|
||||||
|
|
||||||
# Seriellen Monitor öffnen (9600 Baud)
|
|
||||||
pio device monitor
|
|
||||||
```
|
|
||||||
|
|
||||||
### Konfiguration (`platformio.ini`)
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[env:megaatmega2560]
|
|
||||||
platform = atmelavr
|
|
||||||
board = megaatmega2560
|
|
||||||
framework = arduino
|
|
||||||
lib_deps = mike-matera/ArduinoSTL@^1.3.3
|
|
||||||
```
|
|
||||||
|
|
||||||
- **board:** Arduino Mega 2560
|
|
||||||
- **lib_deps:** ArduinoSTL — stellt `std::vector` für die EventQueue bereit, da die Arduino-Standardbibliothek keine STL enthält
|
|
||||||
|
|
||||||
### Projektstruktur
|
|
||||||
|
|
||||||
```
|
|
||||||
Seilbahn/
|
|
||||||
├── platformio.ini # Board- und Bibliothekskonfiguration
|
|
||||||
├── src/
|
|
||||||
│ ├── main.cpp # setup() und loop()
|
|
||||||
│ ├── CMainController # Hauptsteuerung, besitzt alle Objekte
|
|
||||||
│ ├── CButton # Taster-LED-Abstraktion mit Entprellung
|
|
||||||
│ ├── CEventQueue # FIFO-Queue für Button-Events
|
|
||||||
│ └── SEvent # Event-Typ und -Struktur
|
|
||||||
├── include/ # Globale Header (leer)
|
|
||||||
├── lib/ # Projektlokale Bibliotheken (leer)
|
|
||||||
└── test/ # Unit-Tests (PlatformIO-Testframework)
|
|
||||||
```
|
|
||||||
@ -12,4 +12,3 @@
|
|||||||
platform = atmelavr
|
platform = atmelavr
|
||||||
board = megaatmega2560
|
board = megaatmega2560
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps = mike-matera/ArduinoSTL@^1.3.3
|
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
#include "CButton.h"
|
|
||||||
#include "Arduino.h"
|
|
||||||
|
|
||||||
// Einmalige Definition der static-Member (Speicher wird hier reserviert)
|
|
||||||
unsigned long CButton::s_lastBlinkTime = 0;
|
|
||||||
bool CButton::s_blinkState = false;
|
|
||||||
|
|
||||||
CButton::CButton(short btnPin, short ledPin, EVENT_TYPE eventType, CEventQueue* queue)
|
|
||||||
: m_btnPin(btnPin)
|
|
||||||
, m_ledPin(ledPin)
|
|
||||||
, m_eventType(eventType)
|
|
||||||
, m_queue(queue)
|
|
||||||
, m_currentButtonState(false)
|
|
||||||
, m_buttonState(false)
|
|
||||||
, m_ledMode(LEDMode::OFF)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CButton::setup()
|
|
||||||
{
|
|
||||||
pinMode(m_btnPin, INPUT_PULLUP);
|
|
||||||
pinMode(m_ledPin, OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CButton::setLEDMode(LEDMode mode)
|
|
||||||
{
|
|
||||||
m_ledMode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
LEDMode CButton::getLEDMode()
|
|
||||||
{
|
|
||||||
return m_ledMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CButton::work()
|
|
||||||
{
|
|
||||||
// ===== LED aktualisieren =====
|
|
||||||
switch (m_ledMode)
|
|
||||||
{
|
|
||||||
case LEDMode::ON:
|
|
||||||
digitalWrite(m_ledPin, HIGH);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LEDMode::OFF:
|
|
||||||
digitalWrite(m_ledPin, LOW);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LEDMode::BLINK:
|
|
||||||
// s_lastBlinkTime und s_blinkState sind static → werden von allen
|
|
||||||
// Instanzen geteilt. Der erste Button der in diesem Loop work() aufruft
|
|
||||||
// aktualisiert den Timer — alle anderen lesen denselben Zustand.
|
|
||||||
// So blinken alle LEDs im BLINK-Modus exakt synchron.
|
|
||||||
if (millis() - s_lastBlinkTime >= BLINK_INTERVAL_MS)
|
|
||||||
{
|
|
||||||
s_lastBlinkTime = millis();
|
|
||||||
s_blinkState = !s_blinkState;
|
|
||||||
}
|
|
||||||
digitalWrite(m_ledPin, s_blinkState ? HIGH : LOW);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== Button abfragen =====
|
|
||||||
m_currentButtonState = digitalRead(m_btnPin) == LOW;
|
|
||||||
|
|
||||||
// Flankenauswertung: nur bei steigender Flanke reagieren (nicht gedrückt → gedrückt)
|
|
||||||
if (m_currentButtonState && !m_buttonState)
|
|
||||||
{
|
|
||||||
// Entprellen
|
|
||||||
delay(20);
|
|
||||||
m_currentButtonState = digitalRead(m_btnPin) == LOW;
|
|
||||||
|
|
||||||
if (m_currentButtonState)
|
|
||||||
{
|
|
||||||
SEvent event;
|
|
||||||
event.m_eventType = m_eventType;
|
|
||||||
event.m_additionalInfo = 0;
|
|
||||||
m_queue->pushEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Immer aktualisieren — so wird der Button nach dem Loslassen wieder erkannt
|
|
||||||
m_buttonState = m_currentButtonState;
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
#ifndef CBUTTON_H_
|
|
||||||
#define CBUTTON_H_
|
|
||||||
|
|
||||||
#include "SEvent.h"
|
|
||||||
#include "CEventQueue.h"
|
|
||||||
|
|
||||||
enum class LEDMode { OFF, ON, BLINK };
|
|
||||||
|
|
||||||
class CButton
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CButton(short btnPin, short ledPin, EVENT_TYPE eventType, CEventQueue* queue);
|
|
||||||
void setup(); // pinMode setzen (im setup() aufrufen)
|
|
||||||
void work(); // Button abfragen + LED-Zustand aktualisieren
|
|
||||||
|
|
||||||
void setLEDMode(LEDMode mode);
|
|
||||||
LEDMode getLEDMode();
|
|
||||||
|
|
||||||
private:
|
|
||||||
short m_btnPin;
|
|
||||||
short m_ledPin;
|
|
||||||
EVENT_TYPE m_eventType;
|
|
||||||
CEventQueue* m_queue;
|
|
||||||
|
|
||||||
bool m_currentButtonState;
|
|
||||||
bool m_buttonState;
|
|
||||||
|
|
||||||
LEDMode m_ledMode;
|
|
||||||
|
|
||||||
// static: einmal für alle CButton-Instanzen — sorgt für synchrones Blinken
|
|
||||||
static unsigned long s_lastBlinkTime;
|
|
||||||
static bool s_blinkState;
|
|
||||||
static const int BLINK_INTERVAL_MS = 500;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CBUTTON_H_ */
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
#include "CEventQueue.h"
|
|
||||||
|
|
||||||
/*! \fn std::vector<SEvent> CEventQueue::popEvents(EVENT_TYPE eventType)
|
|
||||||
\brief Liefert einen chronologisch geordneten Vektor (FIFO) der aufgelaufenen
|
|
||||||
Events in dieser Queue zurueck. Diese werden daraufhin aus der Queue geloescht
|
|
||||||
\param eventType Falls nicht UNDEFINED, werden nur Events des angegebenen Typs
|
|
||||||
zurueckgegeben und aus der Queue geloescht, andernfalls alle
|
|
||||||
\return Chronologisch sortierter Vektor der Events (aelteste zuerst)
|
|
||||||
*/
|
|
||||||
std::vector<SEvent> CEventQueue::popEvents(EVENT_TYPE eventType)
|
|
||||||
{
|
|
||||||
std::vector<SEvent> ret;
|
|
||||||
|
|
||||||
switch(eventType)
|
|
||||||
{
|
|
||||||
case UNDEFINED:
|
|
||||||
ret = m_events;
|
|
||||||
m_events.clear();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
std::vector<SEvent> without;
|
|
||||||
for(std::vector<SEvent>::iterator it=m_events.begin(); it!=m_events.end(); it++)
|
|
||||||
{
|
|
||||||
if(it->m_eventType==eventType)
|
|
||||||
{
|
|
||||||
ret.push_back(*it);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
without.push_back(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_events = without;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \fn SEvent CEventQueue::popEvent(bool* pValid)
|
|
||||||
\brief Liefert das chronologisch letzte (neueste) Event in der Queue zurueck
|
|
||||||
\param pValid true, falls ein Event aus der Queue zurueckgegeben wird,
|
|
||||||
false andernfalls (dann war die Queue naemlich leer)
|
|
||||||
\return Das chronologisch letzte (neueste) Event in der Queue
|
|
||||||
*/
|
|
||||||
SEvent CEventQueue::popEvent(bool* pValid)
|
|
||||||
{
|
|
||||||
return popEvent(m_events.size()-1, pValid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \fn SEvent CEventQueue::popEvent(unsigned short eventNumber,
|
|
||||||
* bool* pValid)
|
|
||||||
\brief Liefert das Event mit dem angegebenen Index in der Queue der gespeicherten
|
|
||||||
Events zurueck. Das Event wird daraufhin aus der Queue geloescht
|
|
||||||
\param eventNumber Index des zurueckzuliefernden Events in der Queue
|
|
||||||
\param pValid true, falls ein Event aus der Queue zurueckgegeben wird,
|
|
||||||
false andernfalls (dann existiert kein Event mit dem angegebenen Index)
|
|
||||||
\return Falls eventNumber nicht INVALID_EVENT_NUMBER, das Event mit dem
|
|
||||||
angegebenen Index in der Queue, das chronologisch erste (aelteste) Event
|
|
||||||
andernfalls
|
|
||||||
*/
|
|
||||||
SEvent CEventQueue::popEvent(unsigned short eventNumber, bool* pValid)
|
|
||||||
{
|
|
||||||
if(eventNumber<m_events.size())
|
|
||||||
{
|
|
||||||
*pValid=true;
|
|
||||||
std::vector<SEvent>::iterator it;
|
|
||||||
SEvent ret;
|
|
||||||
it=(m_events.begin() + eventNumber);
|
|
||||||
ret=*it;
|
|
||||||
m_events.erase(it);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pValid=false;
|
|
||||||
SEvent e;
|
|
||||||
e.m_eventType=UNDEFINED;
|
|
||||||
e.m_additionalInfo=0;
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \fn void CEventQueue::pushEvent(SEvent event)
|
|
||||||
\brief Fuegt der Queue ein Event hinzu. Sensoren und Aktoren
|
|
||||||
rufen diese Methode auf, um ueber ein Event zu informieren
|
|
||||||
\param event Hinzuzufuegendes Event
|
|
||||||
*/
|
|
||||||
void CEventQueue::pushEvent(SEvent event)
|
|
||||||
{
|
|
||||||
m_events.push_back(event);
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
#ifndef CEVENTQUEUE_H_
|
|
||||||
#define CEVENTQUEUE_H_
|
|
||||||
|
|
||||||
#include "SEvent.h"
|
|
||||||
#include "ArduinoSTL.h"
|
|
||||||
|
|
||||||
class CEventQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::vector<SEvent> popEvents(EVENT_TYPE eventtype=UNDEFINED);
|
|
||||||
SEvent popEvent(bool* pValid);
|
|
||||||
SEvent popEvent(unsigned short eventNumber, bool* pValid);
|
|
||||||
void pushEvent(SEvent event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<SEvent> m_events;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CEVENTQUEUE_H_ */
|
|
||||||
@ -1,363 +0,0 @@
|
|||||||
#include "CMainController.h"
|
|
||||||
#include "Arduino.h"
|
|
||||||
|
|
||||||
// Initialisierungsliste: m_queue wird zuerst gebaut (steht zuerst im Header),
|
|
||||||
// danach die Buttons — jeder bekommt &m_queue, was zu diesem Zeitpunkt bereits
|
|
||||||
// gültig ist.
|
|
||||||
CMainController::CMainController()
|
|
||||||
: m_queue()
|
|
||||||
, m_btnAnlageEinAus (PIN_KNOPF_ANLAGE_EIN_AUS, PIN_LED_ANLAGE_EIN_AUS, BTN_ANLAGE_EIN_AUS, &m_queue)
|
|
||||||
, m_btnStation (PIN_KNOPF_STATION, PIN_LED_STATION, BTN_STATION, &m_queue)
|
|
||||||
, m_btnServicebetrieb(PIN_KNOPF_SERVICEBETRIEB, PIN_LED_SERVICEBETRIEB, BTN_SERVICE, &m_queue)
|
|
||||||
, m_btnFahrgastbetrieb(PIN_KNOPF_FAHRGASTBETRIEB, PIN_LED_FAHRGASTBETRIEB, BTN_FAHRGAST, &m_queue)
|
|
||||||
, m_btnQuitBetrieb (PIN_KNOPF_QUIT_BETRIEB, PIN_LED_QUIT_BETRIEB, BTN_QUIT, &m_queue)
|
|
||||||
, m_btnStart (PIN_KNOPF_START_BETRIEB, PIN_LED_START_BETRIEB, BTN_START, &m_queue)
|
|
||||||
, m_btnHalt (PIN_KNOPF_HALT, PIN_LED_HALT, BTN_HALT, &m_queue)
|
|
||||||
, m_btnNothalt (PIN_KNOPF_NOTHALT, PIN_LED_NOTHALT, BTN_NOTHALT, &m_queue)
|
|
||||||
, m_btnVorwaerts (PIN_KNOPF_VORWAERTS, PIN_LED_VORWAERTS, BTN_VORWAERTS, &m_queue)
|
|
||||||
, m_btnRueckwaerts (PIN_KNOPF_RUECKWAERTS, PIN_LED_RUECKWAERTS, BTN_RUECKWAERTS, &m_queue)
|
|
||||||
, m_anlagenzustand(AnlagenZustand::AUS)
|
|
||||||
, m_fahrtrichtung(FahrtRichtung::HALT)
|
|
||||||
, m_vorherigeRichtung(FahrtRichtung::HALT)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// setup(): einmalig beim Start aufrufen
|
|
||||||
// ============================================================
|
|
||||||
void CMainController::setup()
|
|
||||||
{
|
|
||||||
// Jeden Button mit setup() initialisieren (setzt pinMode für Taster + LED)
|
|
||||||
m_btnAnlageEinAus.setup();
|
|
||||||
m_btnStation.setup();
|
|
||||||
m_btnServicebetrieb.setup();
|
|
||||||
m_btnFahrgastbetrieb.setup();
|
|
||||||
m_btnQuitBetrieb.setup();
|
|
||||||
m_btnStart.setup();
|
|
||||||
m_btnHalt.setup();
|
|
||||||
m_btnNothalt.setup();
|
|
||||||
m_btnVorwaerts.setup();
|
|
||||||
m_btnRueckwaerts.setup();
|
|
||||||
|
|
||||||
// Die drei Ereignis-LEDs haben keinen Button → direkt hier initialisieren
|
|
||||||
pinMode(PIN_LED_ROT_EREIGNISANZEIGE, OUTPUT);
|
|
||||||
pinMode(PIN_LED_GELB_EREIGNISANZEIGE, OUTPUT);
|
|
||||||
pinMode(PIN_LED_GRUEN_EREIGNISANZEIGE, OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// work(): jeden Loop-Durchlauf aufrufen
|
|
||||||
// ============================================================
|
|
||||||
void CMainController::work()
|
|
||||||
{
|
|
||||||
pollButtons(); // 1. Buttons abfragen → Events landen in der Queue
|
|
||||||
processEvents(); // 2. Events verarbeiten → Zustand ändern
|
|
||||||
updateLEDs(); // 3. LEDs anhand des neuen Zustands setzen
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// pollButtons(): work() aller Buttons aufrufen
|
|
||||||
// ============================================================
|
|
||||||
void CMainController::pollButtons()
|
|
||||||
{
|
|
||||||
// Welche Buttons abgefragt werden, hängt vom aktuellen Anlagenzustand ab.
|
|
||||||
// So können z.B. im AUS-Zustand nur relevante Buttons Events erzeugen.
|
|
||||||
switch (m_anlagenzustand)
|
|
||||||
{
|
|
||||||
case AnlagenZustand::AUS:
|
|
||||||
m_btnAnlageEinAus.work();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AnlagenZustand::SERVICE_QUITTIEREN:
|
|
||||||
case AnlagenZustand::FAHRGAST_QUITTIEREN:
|
|
||||||
m_btnAnlageEinAus.work();
|
|
||||||
m_btnQuitBetrieb.work();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AnlagenZustand::SERVICE:
|
|
||||||
m_btnAnlageEinAus.work();
|
|
||||||
m_btnFahrgastbetrieb.work();
|
|
||||||
m_btnQuitBetrieb.work();
|
|
||||||
m_btnStart.work();
|
|
||||||
m_btnHalt.work();
|
|
||||||
m_btnNothalt.work();
|
|
||||||
m_btnVorwaerts.work();
|
|
||||||
m_btnRueckwaerts.work();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AnlagenZustand::FAHRGAST:
|
|
||||||
m_btnAnlageEinAus.work();
|
|
||||||
m_btnServicebetrieb.work();
|
|
||||||
m_btnQuitBetrieb.work();
|
|
||||||
m_btnStart.work();
|
|
||||||
m_btnHalt.work();
|
|
||||||
m_btnNothalt.work();
|
|
||||||
m_btnVorwaerts.work();
|
|
||||||
m_btnRueckwaerts.work();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// processEvents(): alle Events in der Queue verarbeiten
|
|
||||||
// ============================================================
|
|
||||||
void CMainController::processEvents()
|
|
||||||
{
|
|
||||||
bool valid;
|
|
||||||
SEvent ev = m_queue.popEvent(&valid);
|
|
||||||
|
|
||||||
while (valid)
|
|
||||||
{
|
|
||||||
switch (m_anlagenzustand)
|
|
||||||
{
|
|
||||||
// ==================== AUS ====================
|
|
||||||
case AnlagenZustand::AUS:
|
|
||||||
if (ev.m_eventType == BTN_ANLAGE_EIN_AUS)
|
|
||||||
m_anlagenzustand = AnlagenZustand::SERVICE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ==================== SERVICE_QUITTIEREN ====================
|
|
||||||
// Zustandswechsel nach SERVICE oder FAHRGAST wurde ausgelöst,
|
|
||||||
// Nutzer muss erst quittieren bevor es weitergeht.
|
|
||||||
case AnlagenZustand::SERVICE_QUITTIEREN:
|
|
||||||
if (ev.m_eventType == BTN_ANLAGE_EIN_AUS)
|
|
||||||
m_anlagenzustand = AnlagenZustand::AUS;
|
|
||||||
else if (ev.m_eventType == BTN_QUIT)
|
|
||||||
m_anlagenzustand = AnlagenZustand::SERVICE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ==================== SERVICE ====================
|
|
||||||
case AnlagenZustand::SERVICE:
|
|
||||||
if (ev.m_eventType == BTN_ANLAGE_EIN_AUS)
|
|
||||||
m_anlagenzustand = AnlagenZustand::AUS;
|
|
||||||
else if (ev.m_eventType == BTN_FAHRGAST)
|
|
||||||
m_anlagenzustand = AnlagenZustand::FAHRGAST_QUITTIEREN;
|
|
||||||
else
|
|
||||||
processFahrtrichtungEvent(ev); // Fahrtrichtungs-Events weiterleiten
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ==================== FAHRGAST_QUITTIEREN ====================
|
|
||||||
case AnlagenZustand::FAHRGAST_QUITTIEREN:
|
|
||||||
if (ev.m_eventType == BTN_ANLAGE_EIN_AUS)
|
|
||||||
m_anlagenzustand = AnlagenZustand::AUS;
|
|
||||||
else if (ev.m_eventType == BTN_QUIT)
|
|
||||||
m_anlagenzustand = AnlagenZustand::FAHRGAST;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ==================== FAHRGAST ====================
|
|
||||||
case AnlagenZustand::FAHRGAST:
|
|
||||||
if (ev.m_eventType == BTN_ANLAGE_EIN_AUS)
|
|
||||||
m_anlagenzustand = AnlagenZustand::AUS;
|
|
||||||
else if (ev.m_eventType == BTN_SERVICE)
|
|
||||||
m_anlagenzustand = AnlagenZustand::SERVICE_QUITTIEREN;
|
|
||||||
else
|
|
||||||
processFahrtrichtungEvent(ev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ev = m_queue.popEvent(&valid); // nächstes Event holen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// processFahrtrichtungEvent(): Fahrtrichtungs-Statemachine
|
|
||||||
// Wird von processEvents() aufgerufen wenn der Anlagenzustand
|
|
||||||
// SERVICE oder FAHRGAST ist und kein Anlagen-Event vorliegt.
|
|
||||||
// ============================================================
|
|
||||||
void CMainController::processFahrtrichtungEvent(SEvent ev)
|
|
||||||
{
|
|
||||||
switch (m_fahrtrichtung)
|
|
||||||
{
|
|
||||||
// ===== Anlage steht (normal oder Nothalt) =====
|
|
||||||
case FahrtRichtung::HALT:
|
|
||||||
case FahrtRichtung::NOTHALT:
|
|
||||||
if (ev.m_eventType == BTN_QUIT)
|
|
||||||
{
|
|
||||||
// Richtung von vor dem Halt wiederherstellen
|
|
||||||
if (m_vorherigeRichtung == FahrtRichtung::RUECKWAERTS)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::WARTE_START_RUECKWAERTS;
|
|
||||||
else
|
|
||||||
m_fahrtrichtung = FahrtRichtung::WARTE_START_VORWAERTS;
|
|
||||||
}
|
|
||||||
else if (ev.m_eventType == BTN_VORWAERTS)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::VORWAERTS_QUITTIEREN;
|
|
||||||
else if (ev.m_eventType == BTN_RUECKWAERTS)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::RUECKWAERTS_QUITTIEREN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ===== Vorwärts gewählt, wartet auf Quittieren =====
|
|
||||||
case FahrtRichtung::VORWAERTS_QUITTIEREN:
|
|
||||||
if (ev.m_eventType == BTN_QUIT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::WARTE_START_VORWAERTS;
|
|
||||||
else if (ev.m_eventType == BTN_HALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::HALT;
|
|
||||||
else if (ev.m_eventType == BTN_NOTHALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::NOTHALT;
|
|
||||||
else if (ev.m_eventType == BTN_RUECKWAERTS)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::RUECKWAERTS_QUITTIEREN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ===== Quittiert, wartet auf Start =====
|
|
||||||
case FahrtRichtung::WARTE_START_VORWAERTS:
|
|
||||||
if (ev.m_eventType == BTN_START)
|
|
||||||
{
|
|
||||||
m_fahrtrichtung = FahrtRichtung::VORWAERTS;
|
|
||||||
m_vorherigeRichtung = FahrtRichtung::VORWAERTS;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ===== Anlage fährt vorwärts =====
|
|
||||||
case FahrtRichtung::VORWAERTS:
|
|
||||||
if (ev.m_eventType == BTN_HALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::HALT;
|
|
||||||
else if (ev.m_eventType == BTN_NOTHALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::NOTHALT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ===== Rückwärts gewählt, wartet auf Quittieren =====
|
|
||||||
case FahrtRichtung::RUECKWAERTS_QUITTIEREN:
|
|
||||||
if (ev.m_eventType == BTN_QUIT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::WARTE_START_RUECKWAERTS;
|
|
||||||
else if (ev.m_eventType == BTN_HALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::HALT;
|
|
||||||
else if (ev.m_eventType == BTN_NOTHALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::NOTHALT;
|
|
||||||
else if (ev.m_eventType == BTN_VORWAERTS)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::VORWAERTS_QUITTIEREN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ===== Quittiert, wartet auf Start =====
|
|
||||||
case FahrtRichtung::WARTE_START_RUECKWAERTS:
|
|
||||||
if (ev.m_eventType == BTN_START)
|
|
||||||
{
|
|
||||||
m_fahrtrichtung = FahrtRichtung::RUECKWAERTS;
|
|
||||||
m_vorherigeRichtung = FahrtRichtung::RUECKWAERTS;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// ===== Anlage fährt rückwärts =====
|
|
||||||
case FahrtRichtung::RUECKWAERTS:
|
|
||||||
if (ev.m_eventType == BTN_HALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::HALT;
|
|
||||||
else if (ev.m_eventType == BTN_NOTHALT)
|
|
||||||
m_fahrtrichtung = FahrtRichtung::NOTHALT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// updateLEDs(): alle LEDs anhand des aktuellen Zustands setzen
|
|
||||||
// Wird jedes Loop aufgerufen → LEDs sind immer konsistent.
|
|
||||||
// ============================================================
|
|
||||||
void CMainController::updateLEDs()
|
|
||||||
{
|
|
||||||
// ===== Anlage Ein/Aus =====
|
|
||||||
// LED leuchtet solange die Anlage eingeschaltet ist
|
|
||||||
if (m_anlagenzustand != AnlagenZustand::AUS)
|
|
||||||
m_btnAnlageEinAus.setLEDMode(LEDMode::ON);
|
|
||||||
else
|
|
||||||
m_btnAnlageEinAus.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// ===== Station Besetzt/Unbesetzt =====
|
|
||||||
// LED leuchtet solange die Anlage eingeschaltet ist
|
|
||||||
if (m_anlagenzustand != AnlagenZustand::AUS)
|
|
||||||
m_btnStation.setLEDMode(LEDMode::ON);
|
|
||||||
else
|
|
||||||
m_btnStation.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// ===== Servicebetrieb =====
|
|
||||||
// LED leuchtet im Servicezustand (auch während Quittieren)
|
|
||||||
if (m_anlagenzustand == AnlagenZustand::SERVICE
|
|
||||||
|| m_anlagenzustand == AnlagenZustand::SERVICE_QUITTIEREN)
|
|
||||||
m_btnServicebetrieb.setLEDMode(LEDMode::ON);
|
|
||||||
else
|
|
||||||
m_btnServicebetrieb.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// ===== Fahrgastbetrieb =====
|
|
||||||
// LED leuchtet im Fahrgastzustand (auch während Quittieren)
|
|
||||||
if (m_anlagenzustand == AnlagenZustand::FAHRGAST
|
|
||||||
|| m_anlagenzustand == AnlagenZustand::FAHRGAST_QUITTIEREN)
|
|
||||||
m_btnFahrgastbetrieb.setLEDMode(LEDMode::ON);
|
|
||||||
else
|
|
||||||
m_btnFahrgastbetrieb.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// ===== Quittieren =====
|
|
||||||
// LED blinkt wenn ein Zustandswechsel auf Quittierung wartet
|
|
||||||
if (m_anlagenzustand == AnlagenZustand::SERVICE_QUITTIEREN
|
|
||||||
|| m_anlagenzustand == AnlagenZustand::FAHRGAST_QUITTIEREN)
|
|
||||||
m_btnQuitBetrieb.setLEDMode(LEDMode::BLINK);
|
|
||||||
else
|
|
||||||
m_btnQuitBetrieb.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// ===== Ereignisanzeige (3-farbig) =====
|
|
||||||
// Keine Buttons → direkt per digitalWrite gesetzt
|
|
||||||
// Rot: Servicebetrieb aktiv
|
|
||||||
if (m_anlagenzustand == AnlagenZustand::SERVICE)
|
|
||||||
digitalWrite(PIN_LED_ROT_EREIGNISANZEIGE, HIGH);
|
|
||||||
else
|
|
||||||
digitalWrite(PIN_LED_ROT_EREIGNISANZEIGE, LOW);
|
|
||||||
|
|
||||||
// Gelb: Zustandswechsel wartet auf Quittierung
|
|
||||||
if (m_anlagenzustand == AnlagenZustand::SERVICE_QUITTIEREN
|
|
||||||
|| m_anlagenzustand == AnlagenZustand::FAHRGAST_QUITTIEREN)
|
|
||||||
digitalWrite(PIN_LED_GELB_EREIGNISANZEIGE, HIGH);
|
|
||||||
else
|
|
||||||
digitalWrite(PIN_LED_GELB_EREIGNISANZEIGE, LOW);
|
|
||||||
|
|
||||||
// Grün: Fahrgastbetrieb aktiv
|
|
||||||
if (m_anlagenzustand == AnlagenZustand::FAHRGAST)
|
|
||||||
digitalWrite(PIN_LED_GRUEN_EREIGNISANZEIGE, HIGH);
|
|
||||||
else
|
|
||||||
digitalWrite(PIN_LED_GRUEN_EREIGNISANZEIGE, LOW);
|
|
||||||
|
|
||||||
// ===== Fahrtrichtungs-LEDs =====
|
|
||||||
// Nur relevant wenn die Anlage eingeschaltet ist
|
|
||||||
|
|
||||||
// Halt: leuchtet wenn Anlage steht (normaler Halt)
|
|
||||||
if (m_anlagenzustand != AnlagenZustand::AUS && m_fahrtrichtung == FahrtRichtung::HALT)
|
|
||||||
m_btnHalt.setLEDMode(LEDMode::ON);
|
|
||||||
else
|
|
||||||
m_btnHalt.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// Nothalt: leuchtet wenn Nothalt aktiv
|
|
||||||
if (m_anlagenzustand != AnlagenZustand::AUS && m_fahrtrichtung == FahrtRichtung::NOTHALT)
|
|
||||||
m_btnNothalt.setLEDMode(LEDMode::ON);
|
|
||||||
else
|
|
||||||
m_btnNothalt.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// Start: blinkt wenn quittiert wurde und auf Start gewartet wird
|
|
||||||
if (m_anlagenzustand != AnlagenZustand::AUS &&
|
|
||||||
(m_fahrtrichtung == FahrtRichtung::WARTE_START_VORWAERTS || m_fahrtrichtung == FahrtRichtung::WARTE_START_RUECKWAERTS) )
|
|
||||||
m_btnStart.setLEDMode(LEDMode::BLINK);
|
|
||||||
else
|
|
||||||
m_btnStart.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// Vorwärts: leuchtet dauerhaft nur wenn Anlage tatsächlich vorwärts fährt,
|
|
||||||
// blinkt während Quittieren und Warten auf Start
|
|
||||||
if (m_anlagenzustand != AnlagenZustand::AUS && m_fahrtrichtung == FahrtRichtung::VORWAERTS)
|
|
||||||
m_btnVorwaerts.setLEDMode(LEDMode::ON);
|
|
||||||
else if (m_anlagenzustand != AnlagenZustand::AUS &&
|
|
||||||
(m_fahrtrichtung == FahrtRichtung::VORWAERTS_QUITTIEREN || m_fahrtrichtung == FahrtRichtung::WARTE_START_VORWAERTS))
|
|
||||||
m_btnVorwaerts.setLEDMode(LEDMode::BLINK);
|
|
||||||
else
|
|
||||||
m_btnVorwaerts.setLEDMode(LEDMode::OFF);
|
|
||||||
|
|
||||||
// Rückwärts: leuchtet dauerhaft nur wenn Anlage tatsächlich rückwärts fährt,
|
|
||||||
// blinkt während Quittieren und Warten auf Start
|
|
||||||
if (m_anlagenzustand != AnlagenZustand::AUS && m_fahrtrichtung == FahrtRichtung::RUECKWAERTS)
|
|
||||||
m_btnRueckwaerts.setLEDMode(LEDMode::ON);
|
|
||||||
else if (m_anlagenzustand != AnlagenZustand::AUS &&
|
|
||||||
(m_fahrtrichtung == FahrtRichtung::RUECKWAERTS_QUITTIEREN || m_fahrtrichtung == FahrtRichtung::WARTE_START_RUECKWAERTS))
|
|
||||||
m_btnRueckwaerts.setLEDMode(LEDMode::BLINK);
|
|
||||||
else
|
|
||||||
m_btnRueckwaerts.setLEDMode(LEDMode::OFF);
|
|
||||||
}
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
#ifndef CSEILMAINCONTROLLER_H_
|
|
||||||
#define CSEILMAINCONTROLLER_H_
|
|
||||||
|
|
||||||
#include "CButton.h"
|
|
||||||
#include "CEventQueue.h"
|
|
||||||
#include "SEvent.h"
|
|
||||||
|
|
||||||
// enum class = scoped enum → Werte sind nicht global sichtbar, sondern nur als
|
|
||||||
// AnlagenZustand::AUS, AnlagenZustand::SERVICE etc.
|
|
||||||
// Das verhindert Namenskonflikte mit den gleichnamigen Werten in main.cpp.
|
|
||||||
enum class AnlagenZustand
|
|
||||||
{
|
|
||||||
AUS,
|
|
||||||
SERVICE_QUITTIEREN,
|
|
||||||
SERVICE,
|
|
||||||
FAHRGAST_QUITTIEREN,
|
|
||||||
FAHRGAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FahrtRichtung
|
|
||||||
{
|
|
||||||
HALT,
|
|
||||||
NOTHALT,
|
|
||||||
VORWAERTS_QUITTIEREN,
|
|
||||||
WARTE_START_VORWAERTS,
|
|
||||||
VORWAERTS,
|
|
||||||
RUECKWAERTS_QUITTIEREN,
|
|
||||||
WARTE_START_RUECKWAERTS,
|
|
||||||
RUECKWAERTS,
|
|
||||||
};
|
|
||||||
|
|
||||||
class CMainController
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CMainController();
|
|
||||||
void setup(); // pinMode aller Buttons und LEDs setzen
|
|
||||||
void work(); // Buttons abfragen, Events verarbeiten, LEDs aktualisieren
|
|
||||||
|
|
||||||
private:
|
|
||||||
// ===== Pin-Definitionen =====
|
|
||||||
static const short PIN_LED_ANLAGE_EIN_AUS = 2;
|
|
||||||
static const short PIN_KNOPF_ANLAGE_EIN_AUS = 3;
|
|
||||||
static const short PIN_LED_STATION = 4;
|
|
||||||
static const short PIN_KNOPF_STATION = 5;
|
|
||||||
static const short PIN_LED_SERVICEBETRIEB = 6;
|
|
||||||
static const short PIN_KNOPF_SERVICEBETRIEB = 7;
|
|
||||||
static const short PIN_LED_FAHRGASTBETRIEB = 22;
|
|
||||||
static const short PIN_KNOPF_FAHRGASTBETRIEB = 23;
|
|
||||||
static const short PIN_LED_ROT_EREIGNISANZEIGE = 13;
|
|
||||||
static const short PIN_LED_GELB_EREIGNISANZEIGE = 12;
|
|
||||||
static const short PIN_LED_GRUEN_EREIGNISANZEIGE = 11;
|
|
||||||
static const short PIN_LED_QUIT_BETRIEB = 9;
|
|
||||||
static const short PIN_KNOPF_QUIT_BETRIEB = 10;
|
|
||||||
static const short PIN_LED_START_BETRIEB = 36;
|
|
||||||
static const short PIN_KNOPF_START_BETRIEB = 37;
|
|
||||||
static const short PIN_LED_HALT = 38;
|
|
||||||
static const short PIN_KNOPF_HALT = 39;
|
|
||||||
static const short PIN_LED_NOTHALT = 40;
|
|
||||||
static const short PIN_KNOPF_NOTHALT = 41;
|
|
||||||
static const short PIN_LED_VORWAERTS = 30;
|
|
||||||
static const short PIN_KNOPF_VORWAERTS = 31;
|
|
||||||
static const short PIN_LED_RUECKWAERTS = 32;
|
|
||||||
static const short PIN_KNOPF_RUECKWAERTS = 33;
|
|
||||||
|
|
||||||
// ===== EventQueue =====
|
|
||||||
// Muss VOR den Buttons deklariert sein! Member werden in Deklarationsreihenfolge
|
|
||||||
// initialisiert — die Buttons bekommen einen Zeiger auf diese Queue.
|
|
||||||
CEventQueue m_queue;
|
|
||||||
|
|
||||||
// ===== Buttons =====
|
|
||||||
CButton m_btnAnlageEinAus;
|
|
||||||
CButton m_btnStation;
|
|
||||||
CButton m_btnServicebetrieb;
|
|
||||||
CButton m_btnFahrgastbetrieb;
|
|
||||||
CButton m_btnQuitBetrieb;
|
|
||||||
CButton m_btnStart;
|
|
||||||
CButton m_btnHalt;
|
|
||||||
CButton m_btnNothalt;
|
|
||||||
CButton m_btnVorwaerts;
|
|
||||||
CButton m_btnRueckwaerts;
|
|
||||||
|
|
||||||
// ===== Zustandsvariablen =====
|
|
||||||
AnlagenZustand m_anlagenzustand;
|
|
||||||
FahrtRichtung m_fahrtrichtung;
|
|
||||||
FahrtRichtung m_vorherigeRichtung; // Merkt sich die letzte Fahrtrichtung für Quittieren nach HALT/NOTHALT
|
|
||||||
|
|
||||||
// ===== Private Hilfsmethoden =====
|
|
||||||
void pollButtons(); // Alle work()-Methoden der Buttons aufrufen
|
|
||||||
void processEvents(); // Events aus der Queue lesen und Zustand ändern
|
|
||||||
void processFahrtrichtungEvent(SEvent ev); // Fahrtrichtungs-Statemachine
|
|
||||||
void updateLEDs(); // Alle LEDs anhand des aktuellen Zustands setzen
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CMAINCONTROLLER_H_ */
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
#include "SEvent.h"
|
|
||||||
|
|
||||||
const char* evToStr(SEvent ev)
|
|
||||||
{
|
|
||||||
switch(ev.m_eventType)
|
|
||||||
{
|
|
||||||
case BTN_ANLAGE_EIN_AUS: return "BTN_ANLAGE_EIN_AUS";
|
|
||||||
case BTN_STATION: return "BTN_STATION";
|
|
||||||
case BTN_SERVICE: return "BTN_SERVICE";
|
|
||||||
case BTN_FAHRGAST: return "BTN_FAHRGAST";
|
|
||||||
case BTN_QUIT: return "BTN_QUIT";
|
|
||||||
case BTN_START: return "BTN_START";
|
|
||||||
case BTN_HALT: return "BTN_HALT";
|
|
||||||
case BTN_NOTHALT: return "BTN_NOTHALT";
|
|
||||||
case BTN_VORWAERTS: return "BTN_VORWAERTS";
|
|
||||||
case BTN_RUECKWAERTS: return "BTN_RUECKWAERTS";
|
|
||||||
default: return "UNDEFINED";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printEvent(SEvent event, void* who)
|
|
||||||
{
|
|
||||||
// TBD if needed
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
#ifndef SEVENT_H_
|
|
||||||
#define SEVENT_H_
|
|
||||||
|
|
||||||
enum EVENT_TYPE
|
|
||||||
{
|
|
||||||
BTN_ANLAGE_EIN_AUS, // Button Anlage Ein/Aus wurde gedrückt
|
|
||||||
BTN_STATION, // Button Station Besetzt/Unbesetzt wurde gedrückt
|
|
||||||
BTN_SERVICE, // Button Servicebetrieb wurde gedrückt
|
|
||||||
BTN_FAHRGAST, // Button Fahrgastbetrieb wurde gedrückt
|
|
||||||
BTN_QUIT, // Button Quittieren wurde gedrückt
|
|
||||||
BTN_START, // Button Start wurde gedrückt
|
|
||||||
BTN_HALT, // Button Halt wurde gedrückt
|
|
||||||
BTN_NOTHALT, // Button Nothalt wurde gedrückt
|
|
||||||
BTN_VORWAERTS, // Button Vorwaerts wurde gedrückt
|
|
||||||
BTN_RUECKWAERTS, // Button Rueckwaerts wurde gedrückt
|
|
||||||
UNDEFINED=999,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SEvent
|
|
||||||
{
|
|
||||||
EVENT_TYPE m_eventType;
|
|
||||||
unsigned int m_additionalInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* evToStr(SEvent ev);
|
|
||||||
void printEvent(SEvent event, void* who);
|
|
||||||
|
|
||||||
#endif /* SEVENT_H_ */
|
|
||||||
Loading…
x
Reference in New Issue
Block a user