diff --git a/main.ino b/main.ino index ac03901..8ba71d6 100644 --- a/main.ino +++ b/main.ino @@ -1,22 +1,95 @@ #include #include +#include +#include + +const char* ssid = "DEIN_WLAN_NAME"; +const char* password = "DEIN_PASSWORT"; + +// NTP-Server & Zeitzone für Deutschland +const char* ntpServer = "pool.ntp.org"; +const char* tzInfo = "CET-1CEST,M3.5.0,M10.5.0/3"; FastAccelStepperEngine engine = FastAccelStepperEngine(); FastAccelStepper *stepper = NULL; +// Pins #define dirPinStepper D5 #define enablePinStepper D6 #define stepPinStepper D9 -#define speedUp D8 -#define speedDown D7 +#define buttonPlus D8 +#define buttonMinus D7 +#define buttonStop D10 -const int32_t ACCEL_RATE = 2000; +#define senTemp + +// ################ Variabeln ################ const uint32_t MAX_SPEED_HZ = 106000; +bool clickPlus = 0; +bool clickMinus = 0; +bool clickStop = 0; +bool holdPlus = 0; +bool holdMinus = 0; +bool holdStop = 0; + int32_t lastControl = 0; uint32_t lastPlotTime = 0; +uint32_t lastDispTime = 0; +bool stop = false; +bool bSettings = false; +uint32_t curTemp = 0; + +struct tm timeinfo; + +struct settings{ + int settingIdx = 0; + int startHour = 0; + int startMin = 0; + int endHour = 0; + int endMin = 0; + bool timerEnabled = false; + bool editMaxTemp = false; + int maxTemp = 50; //in °C + bool editAcc = false; + int32_t accelRate = 2000; +} + +enum TimeEditStep { + EDIT_NONE = 0, // Normales Menü (Navigation) + EDIT_START_HOUR, // 1. Start-Stunde einstellen (0-23) + EDIT_START_MIN, // 2. Start-Minute einstellen (0-59) + EDIT_END_HOUR, // 3. End-Stunde einstellen (0-23) + EDIT_END_MIN // 4. End-Minute einstellen (0-59) +}; + +TimeEditStep timeEditStep = EDIT_NONE; + +// Überladung des Präfix-Operators (++timeEditStep) +TimeEditStep& operator++(TimeEditStep& step) { + step = (step == EDIT_END_MIN) ? EDIT_NONE : static_cast(step + 1); + return step; +} + +void initWiFiAndTime() { + WiFi.begin(ssid, password); + + // Zeitzone und NTP-Server setzen + configTzTime(tzInfo, ntpServer); + + // Warten auf Verbindung (optional mit Timeout) + int retries = 0; + while (WiFi.status() != WL_CONNECTED && retries < 20) { + delay(500); + retries++; + } +} + +//####################################################### +//####################### Setup ######################### +//####################################################### void setup() { Serial.begin(115200); delay(1000); // Zeit für USB-CDC-Verbindung geben @@ -31,57 +104,259 @@ void setup() { stepper->setSpeedInHz(MAX_SPEED_HZ); } - pinMode(speedUp, INPUT_PULLUP); - pinMode(speedDown, INPUT_PULLUP); + // Pin Config + pinMode(buttonPlus, INPUT_PULLUP); + pinMode(buttonMinus, INPUT_PULLUP); + pinMode(buttonStop, INPUT_PULLUP); + + initWiFiAndTime() + + // Start Animation } +bool getCurrentTime(int &hour, int &minute, int &second) { + if (!getLocalTime(&timeinfo, 50)) { // 50ms Timeout + return false; // Noch keine NTP-Zeit synchronisiert + } + hour = timeinfo.tm_hour; + minute = timeinfo.tm_min; + second = timeinfo.tm_sec; + return true; +} + +// Rückgabe von Flanken (Klick) und Pegel (Halten) +void getInputs(bool &clickPlus, bool &clickMinus, bool &clickStop, + bool &holdPlus, bool &holdMinus, bool &holdStop) { + + // Physische Pegel einlesen (Active-Low) + bool curPlus = (digitalRead(buttonPlus) == LOW); + bool curMinus = (digitalRead(buttonMinus) == LOW); + bool curStop = (digitalRead(buttonStop) == LOW); + + // Speicher für vorherigen Durchlauf + static bool lastPlus = false; + static bool lastMinus = false; + static bool lastStop = false; + + // Nur bei Veränderung true (Sperre) + clickPlus = (curPlus && !lastPlus); + clickMinus = (curMinus && !lastMinus); + clickStop = (curStop && !lastStop); + + // Dauerzustand (für Stepper-Handbetrieb) + holdPlus = curPlus; + holdMinus = curMinus; + holdStop = curStop; + + // Zustand für nächsten Durchlauf merken + lastPlus = curPlus; + lastMinus = curMinus; + lastStop = curStop; +} + +// Liefert die Aktuelle Temperatur in °C +int getTempInC(uint8_t senTemp){ + int milliVolt = analogReadMilliVolts(senTemp); + return ((milliVolt - 500)/10) +} + +// Die Funktion behandelt das gesammte Einstellungs menu +void setting(){ + //######### Timer Edit ######### + if (timeEditStep != EDIT_NONE) { + //PLUS GEDRÜCKT: Wert erhöhen + if (clickPlus || holdPlus) { + switch (timeEditStep) { + case EDIT_START_HOUR: + settings.startHour = (settings.startHour + 1) % 24; + break; + case EDIT_START_MIN: + settings.startMin = (settings.startMin + 5) % 60; + break; + case EDIT_END_HOUR: + settings.endHour = (settings.endHour + 1) % 24; + break; + case EDIT_END_MIN: + settings.endMin = (settings.endMin + 5) % 60; + break; + default: break; + } + } + + // MINUS GEDRÜCKT: Wert verringern + if (clickMinus) { + switch (timeEditStep) { + case EDIT_START_HOUR: + settings.startHour = (settings.startHour == 0) ? 23 : settings.startHour - 1; + break; + case EDIT_START_MIN: + settings.startMin = (settings.startMin == 0) ? 59 : settings.startMin -5; + break; + case EDIT_END_HOUR: + settings.endHour = (settings.endHour == 0) ? 23 : settings.endHour - 1; + break; + case EDIT_END_MIN: + settings.endMin = (settings.endMin == 0) ? 59 : settings.endMin - 5; + break; + default: break; + } + } + + // STOP GEDRÜCKT: Zum nächsten Wert springen + if (clickStop) { + ++timeEditStep; + } + + return; // Wichtig: Rest der Funktion überspringen, solange editiert wird! + } + + //######### Max Temp Edit ######### + if(settings.editMaxTemp){ + if(clickPlus){ + settings.maxTemp = (settings.maxTemp + 5) % 140; + } + if(clickPlus){ + settings.maxTemp = (settings.maxTemp == 0) ? -20 : settings.maxTemp - 5; + } + if(clickStop){ + settings.editMaxTemp = false; + } + return; // Wichtig: Rest der Funktion überspringen, solange editiert wird! + } + + //######### Beschleunigung Edit ######### + if(settings.editAcc){ + if(clickPlus){ + settings.accelRate = (settings.accelRate + 1000) % 20000; + } + if(clickPlus){ + settings.accelRate = (settings.accelRate == 0) ? 0 : settings.accelRate - 1000; + } + if(clickStop){ + settings.editAcc = false; + } + return; // Wichtig: Rest der Funktion überspringen, solange editiert wird! + } + + + //######### Menü ######### + // Menü bewegen + if(clickPlus){ + if(settings.settingIdx <= 2){ + settings.settingIdx++; + } + } + if(clickMinus){ + if(settings.settingIdx >=1){ + settings.settingIdx--; + } + } + + // Stop zum bestätigen + if (clickStop) { + if (settings.settingIdx == 0) { + // Zeitschaltuhr-Einstellung starten + timeEditStep = EDIT_START_HOUR; + } + else if (settings.settingIdx == 1) { + // Zeitschaltuhr ON/OFF + settings.timerEnabled = !settings.timerEnabled; + }else if (settings.settingIdx == 2) { + // Temperatur Grenze einstellen + settings.editMaxTemp = true; + }else if (settings.settingIdx == 3) { + // Beschleunigung + settings.editAcc = true; + }else if (settings.settingIdx == 4) { + // Menü verlassen + bSettings = false; + } + } +} + +void updateDisplay(){ + if (millis() - lastDispTime >= 50) { + lastDispTime = millis(); + int32_t currentSpeed = stepper->getCurrentSpeedInUs() == 0 ? 0 : (1000000 / stepper->getCurrentSpeedInUs()); + + // einstellungs fenster + if(bSettings){ + // Mein Menu + + // Uhrzeit + + // Cursor mit settingIdx + //EDIT_START_HOUR + //EDIT_START_MIN + //EDIT_END_HOUR + //EDIT_END_MIN + + } +} + +void printStatus(FastAccelStepper *stepper, int speed, int clickPlus, int clickMinus){ + // Plotter-Ausgabe alle 50 ms (überflutet den Bus nicht) + if (millis() - lastPlotTime >= 50) { + lastPlotTime = millis(); + + int32_t currentSpeed = stepper->getCurrentSpeedInUs() == 0 ? 0 : (1000000 / stepper->getCurrentSpeedInUs()); + + // Format kompatibel für den Arduino Serial Plotter + Serial.print("Current_Speed_U/Min:"); + Serial.print((60*currentSpeed)/3200); + Serial.print(" Accel_Control:"); + Serial.print(speed); + Serial.print(" Btn_Up:"); + Serial.print(clickPlus ? 5000 : 0); + Serial.print(" Btn_Down:"); + Serial.print(clickMinus ? -5000 : 0); + Serial.println(); + } +} + +//############################################################# +//#################### MAIN ################################### +//############################################################# void loop() { + int32_t speed = 0; + if (!stepper) { Serial.println("[HALT] Kein Stepper-Objekt aktiv."); delay(1000); return; } - // Bei INPUT_PULLUP: gedrückt = LOW (true) - bool btnUpPressed = (digitalRead(speedUp) == LOW); - bool btnDownPressed = (digitalRead(speedDown) == LOW); + // Inputs + getInputs(clickPlus, clickMinus, clickStop, holdPlus, holdMinus, holdStop); + curTemp = getTempInC(senTemp); - int32_t control = 0; - - if (btnUpPressed && btnDownPressed) { + // Main Control + if(bSettings){ + settings() + }else if(clickStop || stop){ stepper->stopMove(); - control = 0; - } - else if (btnUpPressed) { - control = ACCEL_RATE; - } - else if (btnDownPressed) { - control = -ACCEL_RATE; - } - else { - control = 0; + speed = 0; + if(clickPlus){ + bSettings = true; + settings(); + } + }else if(holdPlus){ + speed = accelRate; + }else if(holdMinus){ + speed = -accelRate; + }else{ + speed = 0; } - if (control != lastControl) { - stepper->moveByAcceleration(control, true); - lastControl = control; + // Action + if (speed != lastSpeed) { + stepper->moveByAcceleration(speed, true); + lastSpeed = speed; } - // Plotter-Ausgabe alle 50 ms (überflutet den Bus nicht) - if (millis() - lastPlotTime >= 50) { - lastPlotTime = millis(); - - int32_t currentSpeed = stepper->getCurrentSpeedInUs() == 0 ? 0 : (1000000 / stepper->getCurrentSpeedInUs()); - - // Format kompatibel für den Arduino Serial Plotter - Serial.print("Current_Speed_Hz:"); - Serial.print((60*currentSpeed)/3200); - Serial.print(" Accel_Control:"); - Serial.print(control); - Serial.print(" Btn_Up:"); - Serial.print(btnUpPressed ? 5000 : 0); - Serial.print(" Btn_Down:"); - Serial.print(btnDownPressed ? -5000 : 0); - Serial.println(); + updateDisplay() + + // Status ausgabe auf Terminal + printStatus(stepper, speed, clickPlus, clickMinus); } } \ No newline at end of file