Hi,
ich habe ein kleines Problem mit meinem Code. Er funktioniert eigentlich perfekt, aber der millis()-Überlauf macht mir Probleme. Mir ist klar, wie ich das Problem umgehe, wenn ich ein konstantes Intervall, bei dem etwas passieren soll, habe, aber was mache ich, wenn ich wie in meinem Fall die millis()-Funktion mit einem sich ändernden Wert vergleiche und ich kein Intervall habe? Mein Code würde nach dem Überlauf das Relais dauerhaft einschalten, was er natürlich nicht soll.
Hier ist mein kompletter Code. In Zeile 32 und 41 liegt das Problem.
LG
const byte LED = 4;
const byte RELAIS = 5;
const byte BUTTON = 13;
bool ledstate = HIGH; //reversed
bool relaisstate = LOW;
bool buttonstate = HIGH;
bool lastbuttonstate = HIGH;
unsigned long lastmillis = 0;
const int second = 1000;
unsigned long lastdebouncetime = 0;
const int debouncedelay = 25;
unsigned long timer = 0;
const unsigned long addtime = 60000; // 1 Minute
void setup() {
pinMode(LED, OUTPUT);
pinMode(RELAIS, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
digitalWrite(LED, ledstate);
digitalWrite(RELAIS, relaisstate);
}
void loop() {
buttonstate = digitalRead(BUTTON);
if (millis() - lastdebouncetime >= debouncedelay) {
lastdebouncetime = millis();
if (buttonstate != lastbuttonstate) {
lastbuttonstate = buttonstate;
if (buttonstate == LOW) {
if (millis() <= timer) {
timer += addtime;
} else {
timer = millis() + addtime;
lastmillis = millis();
}
}
}
}
if (millis() <= timer) {
relaisstate = HIGH;
if (millis() - lastmillis >= second) {
lastmillis = millis();
ledstate = !ledstate;
}
} else {
relaisstate = LOW;
ledstate = HIGH;
}
digitalWrite(LED, ledstate);
digitalWrite(RELAIS, relaisstate);
}
Wenn Du immer mit aktuellenMillis - letztenMillis >= Zeitabstand arbeitest, hast Du keine Probleme.
Deine addTime/time-Konstruktion verstehe ich nicht.
Erkläre mal bitte, was die bewirken soll.
Gruß Tommy
Hi
Warum machst Du Das nicht genau so, wie Du Das schon beim Entprellen des Taster machst?
IMMER
millis()-Startzeit>=Wartezeit
... DANN tue etwas
Das läuft zwar auch über, aber dieser Überlauf rechnet Sich bei dem millis()-Startzeit wieder raus.
Anstatt also 'timer' die Endzeit aufzubrummen, berechnest Du darin NUR die Laufzeit - der aktuelle millis()-Wert ist uninteressant dafür.
Wenn Du 'timer' einen sinnvollen Namen gegeben hättest - wie wäre Es mit wartezeit?
Bastel die millis()-Abfrage 'in Normal um', dann sollte Dein Problem bereits Geschichte sein.
mfG
Der Code sollte wie eine Art Eieruhr funktionieren. Wenn man den Knopf das erste mal drückt, wird das Relais eingeschaltet und ein einminütiger Countdown beginnt. Drückt man den Knopf öfters, kann man den Countdown um je eine Minute aufstocken. Wenn der Countdown abgelaufen ist, wird das Relais ausgeschaltet.
buttonstate = digitalRead(BUTTON);
if (millis() - lastdebouncetime >= debouncedelay) {
lastdebouncetime = millis();
if (buttonstate != lastbuttonstate) {
lastbuttonstate = buttonstate;
if (buttonstate == LOW) {
... das registriert den Knopfdruck und kümmert sich um den Debounce.
if (millis() <= timer) {
timer += addtime;
... wenn der Countdown schon läuft, wird um eine Minute aufgestockt.
} else {
timer = millis() + addtime;
... wenn der Countdown noch nicht läuft, dann wird "timer" als millis() plus eine Minute definiert.
if (millis() <= timer) {
relaisstate = HIGH;
if (millis() - lastmillis >= second) {
lastmillis = millis();
ledstate = !ledstate;
}
} else {
relaisstate = LOW;
ledstate = HIGH;
}
... und das schaltet letztendlich das Relais ein oder aus (und lässt noch eine LED blinken). Ist "timer" größer als millis() ist das Relais ein, sonst halt aus.
Wenn ich das jetzt auf "aktuellenMillis - letztenMillis >= Zeitabstand" umbauen müsste, dann müsste ich doch den Zeitabstand ständig ändern oder?
Hallo,
das was du mit dem Taster einstellen möchtest, wende das auf die Vergleichsvariable Zeitabstand an.
millis bzw. aktuelleMillis und letzteMillis lässt du in Ruhe. Du musst nur das zu prüfende "Intervall" per Taster ändern.
Wenn du unterscheidest zwischen dem ersten Tastendruck (Startzeit = millis(), Dauer = 1 Minute)
und Folgenden (Dauer += 1 Minute), kannst du immer den überlaufsicheren Ausdruck
if (millis() - Startzeit >= Dauer) { // abgelaufen ...
verwenden.
Eventuell willst du auch die int Restzeit = (Startzeit - millis() + Dauer)/1000;
für eine Anzeige oder so verwenden.
Oder du willst einen langen Tastendruck auswerten und z.B. jede Sekunde die Dauer
um 1 Minute erhöhen.
Hi,
vielen Dank für die ganzen Antworten. Das hat mir wirklich geholfen. Ich habe jetzt den Coundown in dieses "aktuellenMillis - letztenMillis >= Zeitabstand" Schema gebracht und jetzt funktioniert alles. Danke!
LG