/* Torsteuerung mit Arduino UNO
# Relais schalten nur mit kurzen Tastendruck
langer Tastendruck wird ignoriert
# Laufzeit kann frei programmiert werden
Programm-Taste 5s lang drücken,
LED signalisiert den Programm-Modus
Mit AUF-STOP-ZU Taste gedrückt halten
neue Laufzeit einstellen.
*/
#include <EEPROM.h>
// Pinzuweisungen
const int RELAIS_AUF = 3;
const int RELAIS_ZU = 4;
const int TASTER_TOGGLE = 7; // Taste für Auf-Stop-Zu
const int TASTER_PROGRAMM = 8; // Taste für Programmierung der On-Zeit
const int LED = 13;
// Statusvariablen
int status = 0; // 0: Stop/Ausgangsstatus, 1: Zielstatus erreicht
unsigned long onZeit = 3000; // Standardzeit: 30 Sekunden
unsigned long startMillis = 0; // Startzeit für Relaisaktivierung
bool relaisAktiv = false; // Gibt an, ob ein Relais aktuell aktiv ist
bool programmModus = false; // Ist der Programmiermodus aktiv?
unsigned long programmStartMillis = 0;
unsigned long toggleStartMillis = 0;
bool toggleTasteGehalten = false;
// Entprellung und kurzer/langer Tastendruck
unsigned long lastToggleMillis = 0; // Zeit der letzten Aktion
unsigned long lastProgrammMillis = 0;
const int debounceDelay = 100; // Entprellzeit
const int longPressThreshold = 1000; // Grenze für langen Tastendruck
bool tasteWurdeGedrueckt = false; // Speichert, ob die Taste gedrückt wurde
// EEPROM-Adressen
const int EEPROM_STATUS_ADDR = 0;
const int EEPROM_ONZEIT_ADDR = 4;
void setup() {
// Relais als Ausgang
pinMode(RELAIS_AUF, OUTPUT);
pinMode(RELAIS_ZU, OUTPUT);
digitalWrite(RELAIS_AUF, LOW);
digitalWrite(RELAIS_ZU, LOW);
// Taster als Eingang
pinMode(TASTER_TOGGLE, INPUT_PULLUP); // Interner Pull-Up
pinMode(TASTER_PROGRAMM, INPUT_PULLUP); // Interner Pull-Up
// LED als Ausgang
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
// Daten aus EEPROM laden
status = EEPROM.read(EEPROM_STATUS_ADDR);
if (status != 0 && status != 1) {
status = 0; // Standardwert, wenn ungültig
}
EEPROM.get(EEPROM_ONZEIT_ADDR, onZeit);
if (onZeit < 1000 || onZeit > 240000) {
onZeit = 3000; // Standardwert, wenn ungültig
}
}
void loop() {
// Taster einlesen
bool toggleGedrueckt = !digitalRead(TASTER_TOGGLE);
bool programmGedrueckt = !digitalRead(TASTER_PROGRAMM);
// Zeitprogrammierung starten, wenn Taste 5 Sekunden lang gedrückt gehalten wird
if (programmGedrueckt && !programmModus) {
if (programmStartMillis == 0) programmStartMillis = millis();
if (millis() - programmStartMillis >= 5000) {
programmModus = true; // Programmiermodus aktivieren
digitalWrite(LED, LOW); // LED an, um Programmiermodus zu signalisieren
}
} else if (!programmGedrueckt) {
programmStartMillis = 0; // Reset, wenn die Taste losgelassen wird
}
// Verhalten im Programmiermodus
if (programmModus) {
handleProgrammModus(toggleGedrueckt);
return; // Restliche Steuerung pausieren, solange im Programmiermodus
}
// Behandlung von kurzem und langem Tastendruck
if (toggleGedrueckt) {
if (!tasteWurdeGedrueckt) {
lastToggleMillis = millis(); // Zeitpunkt des Drückens speichern
tasteWurdeGedrueckt = true; // Merken, dass die Taste gedrückt wurde
}
} else if (tasteWurdeGedrueckt) {
// Taste wurde losgelassen, unterscheide kurzen/langen Tastendruck
unsigned long druckDauer = millis() - lastToggleMillis;
if (druckDauer >= debounceDelay && druckDauer < longPressThreshold) {
handleToggleTaste(); // Kurzer Tastendruck, Aktion ausführen
}
// Zurücksetzen, unabhängig von der Dauer
tasteWurdeGedrueckt = false;
}
// Automatische Abschaltung, wenn Zeit abgelaufen ist
if (relaisAktiv && (millis() - startMillis >= onZeit)) {
relaisAktiv = false;
digitalWrite(RELAIS_AUF, LOW);
digitalWrite(RELAIS_ZU, LOW);
// Status nach Ablauf der On-Zeit ändern
status = !status;
// Status in EEPROM speichern
EEPROM.write(EEPROM_STATUS_ADDR, status);
}
}
// Funktion zur Steuerung der Taste
void handleToggleTaste() {
if (relaisAktiv) {
// Wenn Relais aktiv ist, stoppen und Status ändern
relaisAktiv = false;
digitalWrite(RELAIS_AUF, LOW);
digitalWrite(RELAIS_ZU, LOW);
// Status ändern
status = !status;
} else {
// Wenn Relais nicht aktiv ist, Bewegung starten
if (status == 0) {
// Status 0: Auf fahren
digitalWrite(RELAIS_AUF, HIGH);
digitalWrite(RELAIS_ZU, LOW);
} else if (status == 1) {
// Status 1: Zu fahren
digitalWrite(RELAIS_ZU, HIGH);
digitalWrite(RELAIS_AUF, LOW);
}
relaisAktiv = true;
startMillis = millis(); // Zeit für die Bewegung speichern
}
}
// Funktion zum Blinken der LED
void blinkLED(int anzahl) {
for (int i = 0; i < anzahl; i++) {
digitalWrite(LED, LOW);
delay(200);
digitalWrite(LED, HIGH);
delay(200);
}
}
// Funktion für den Programmiermodus
void handleProgrammModus(bool toggleGedrueckt) {
static unsigned long toggleStartMillis = 0;
static bool toggleTasteGehalten = false;
if (toggleGedrueckt) {
if (!toggleTasteGehalten) {
toggleStartMillis = millis(); // Zeit des Druckens speichern
toggleTasteGehalten = true;
// Bewegung starten
if (status == 0) {
digitalWrite(RELAIS_AUF, HIGH);
} else {
digitalWrite(RELAIS_ZU, HIGH);
}
}
} else if (toggleTasteGehalten) {
// Bewegung stoppen und neue Zeit speichern
unsigned long gedrueckteZeit = millis() - toggleStartMillis;
if (gedrueckteZeit >= 1000 && gedrueckteZeit <= 90000) {
onZeit = gedrueckteZeit;
EEPROM.put(EEPROM_ONZEIT_ADDR, onZeit); // On-Zeit speichern
}
// Bewegung stoppen
digitalWrite(RELAIS_AUF, LOW);
digitalWrite(RELAIS_ZU, LOW);
// Status ändern
status = !status;
// Status in EEPROM speichern
EEPROM.write(EEPROM_STATUS_ADDR, status);
// Programmiermodus beenden
programmModus = false;
digitalWrite(LED, HIGH); // LED aus
toggleTasteGehalten = false;
blinkLED(3); // LED 3 mal blinken
}
}