ich habe vor, folgendes in einem Projekt zu realisieren:
Um einen Ausgang auf HIGH zu setzen, muss ein Taster mindestens 5 Sekungen lang gedrückt werden.
Der Ausgang soll auch dann nach 5 Sekunden HIGH gehen, wenn der Taster noch nicht losgelassen wurde.
Es soll ein Sicherheitsmechanismus werden, der vorraussetzt, dass die Eingabe quasi für 5 Sekunden bestätigt wird.
Wenn nur 4 Sekunden bestätigt wurde, soll das Programm nicht ausgeführt werden (Ausgang bleibt LOW).
Kann mir jemand bei der Sache Hilfe leisten?
Kennt ihr eine Lib oder habt ihr eine Idee, wie genau ich das programmieren kann?
Das ist recht simpel. Du fragst erst einen Statuswechsel am Taster ab und setzt eine Zeitmarke wenn ein Wechsel erfolgt ist. Dann vergleichts du die aktuellen millis() mit der Differenz zu deiner Zeitmarke und den Tasterstatus. Ist die Zeit überschritten und der Taster high läßt du deine Aktion starten.
Im Prinzip ist das sehr einfach. Du sorgst dafür, dass oldmillis stehen bleibt, sobald die Taste gedrückt ist. Wird sie losgelassen, nimmt oldmillis wieder den Wert von millis() an.
Wenn Taste nicht gedrückt, dann oldmillis=millis()
Wenn millis()-oldmillis>5000ms dann Setze Pin auf High
Das muss wie bei Blink without Delay bei jedem Loop-Durchlauf ausgeführt werden.
if ( Taster != High ) //Ersetzen ob high oder low gedrücktem Taster entspricht
{ Zeitmarke = millis(); }
if ( Zeitmarke - millis() >= 5000 )
{ Aktion; }
Jetzt habe ich nochmal geschraubt und einen "Else > LED LOW befehl gebaut.
Die LED bleibt aus, geht aber an sobald ich den Taster drücke und bleibt auch nur so lange an.
int ledPin = 12;
int tastPin = 3;
unsigned long Zeitmarke = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(tastPin, INPUT);
digitalWrite(ledPin, LOW);
}
void loop() {
if ( digitalRead(tastPin) != HIGH ) //Ersetzen ob high oder low gedrücktem Taster entspricht
{ Zeitmarke = millis(); }
if ( Zeitmarke - millis() >= 5000 )
{ digitalWrite(ledPin, HIGH);
}
else
{ digitalWrite(ledPin, LOW);
}
}
edit: Posts haben sich überschnitten, manches ist bereits behoben
naja, da sind einige Fehler drin.
Tip zur Fehlersuche: aktiviere den Seriellen Monitor (Seriell.begin(9600); ins Setup)
dann kannst du dir in dein Programm an verschiedenen Stellen die Variablen ausgeben lassen oder ob er einen Zweig durchläuft mit Serial.print(Zeitmarke) oder Serial.print("LED Einschalten");
Vorneweg: dass er die LED nie wieder ausschaltet, liegt daran, dass du nie definiert hast (auch nicht uns gegenüber) wann sie wieder ausgehen soll.
Aber zum code:
if (tastPin != HIGH) fragt ab, ob der Wert in der Variablen tastPin ungleich dem Wert HIGH ist.
wenn du den Pinstatus selbst abfragen willst, mußt du den Pin vorher lesen.
if (digitalRead(testPin) != HIGH){
Zeitmarke = millis();
jedes Mal, wenn der PIN als HIGH gelesen wird, setzt du eine neue Zeitmarke.
ich schlage vor, führe eine weitere Variable "gedrueckt" ein, die beim ersten Tastendruck gesetzt wird. Und nur beim ersten wird auch Zeitmarke geschrieben.
if ( Zeitmarke - millis() >= 5000 )
Fehler1: rechne doch mal selber nach, was bei der Rechnung rauskommt!
Fehler2: Immer wenn die 5000ms erreicht sind, wird die LED geschalten. Auch wenn der Taster garnicht gedrückt wurde. (Wenn Fehler 1 behoben passiert das nach 5 sek, weil Zeitmarke beim Start 0 ist.)
Hier fehlt noch eine Abfrage, ob der Taster auch noch gedrückt ist.
Und, welch Glück, wir haben oben da so eine Status Variable (gedrueckt) eingeführt!
Das ganze könnte dann so aussehen:
if ( millis() - Zeitmarke >= 5000 && gedrueckt) // 5sek nach Tastendruck
{ digitalWrite(ledPin, HIGH); // LED einschalten
Serial.println("LED AN");
}
Wenn die LED noch eine Zeit X anbleiben soll, schaffst du das ja jetzt sicher Du mußt dir da nur Gedanken machen, ab wann die Zeit zählen soll, bis die LED wieder aus geht...
Astrojens:
Habe das vor Jahren mal in einer Modellraketen Startprozedur mit eingebaut. Bin gerade durch Zufall drauf gestoßen.
Es funktioniert einwandfrei
Da finde ich deinen Code aus #11 um Längen eleganter.
Theseus:
Da finde ich deinen Code aus #11 um Längen eleganter.
Ja, auf jeden Fall!
Aber wichtig ist richtig zu rechnen. Ich denke, das wird nicht so gut funktionieren:
if ( Zeitmarke - millis() >= 5000 )
...
(vor allem auch) weil Zeitmarke und millis unsigned long sind.
Da wird von der kleineren Zahl die größere abgezogen. Das gibt dann einen Überlauf und eine "ziemlich große" Zahl, die wohl immer größer als 5000 ist.
Aber so funktioniert es besser:
Dein Code macht trotzdem noch nicht das, was du willst:
Astrojens: muss ein Taster mindestens 5 Sekungen lang gedrückt werden.
Du musst noch eine Zeile einfügen, in der der Zähler _ABVAR_1_Counter auf Null gesetzt wird, wenn der Taster nicht gedrückt wird.
Aber ansonsten: Wenn du für dich eine funktionierende Lösung gefunden hast, ist es gut.
Es gibt immer jemanden, der meint eine andere Lösung sei besser.
Laß dich nicht irritieren.