Tastereingabe mit Wartezeit/Verzögerung

Guten Morgen,

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?

Danke vorweg und liebe Grüße

Jens

Verwende millis(). siehe blinkwithoutdelay Beispiel.

Grüße Uwe

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.

mal ins Unreine getippt...:

if ( Taster != Tasteralt )
   { Tasteralt = Taster;
      Zeitmarke = millis(); }

if ( ( Zeitmarke - millis() >= 5000 ) && Taster == 1 )
   { Aktion; }

MaHa76:
mal ins Unreine getippt...:

Es geht noch einfacher:

if ( Taster != High )  //Ersetzen ob high oder low gedrücktem Taster entspricht
   { Zeitmarke = millis(); }

if ( Zeitmarke - millis() >= 5000 ) 
   { Aktion; }

sicher? für mein Verständnis setzt du so sie Zeitnarke imner wieder zurück und erreichst nie die Bedingung für die Aktion.

Edit: Achso, ja, du fragst ja ab ob er nicht gedrückt ust.

Ja geil,

danke erstmal für eure Antworten :o :slight_smile:
Bin sehr begeistert und werde das im Tagesverlauf mal durchprobieren.

Mit diesen zeitbasierten Sachen (abgesehen vom Delay) hab ich immer meine Schwierigkeiten.

Liebe Grüße

Jens

Habs mal probiert.

Irgendwie läuft es nicht. Die LED ist dauer-HIGH.

Wahrscheinlich hab ich irgendwas vergessen oder falsch verstanden. :confused:

int ledPin = 12;
int tastPin = 3;


unsigned long Zeitmarke = 0;

void setup() {

pinMode(ledPin, OUTPUT);
pinMode(tastPin, INPUT);
digitalWrite(ledPin, LOW);

}

void loop() {
 
  if ( tastPin != HIGH )  //Ersetzen ob high oder low gedrücktem Taster entspricht
   { Zeitmarke = millis(); }

if ( Zeitmarke - millis() >= 5000 )
   { digitalWrite(ledPin, HIGH);
 }
}

Weil du den Pin nie wieder ausschaltest

Es fehlt die Abfrage des Tastpins. Also in der Loop

if ( digitalRead(tastPin) != HIGH )//Ersetzen ob high oder low gedrücktem Taster entspricht
   { Zeitmarke = millis(); }

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");
  }
1 Like

Wenn die LED noch eine Zeit X anbleiben soll, schaffst du das ja jetzt sicher :wink: Du mußt dir da nur Gedanken machen, ab wann die Zeit zählen soll, bis die LED wieder aus geht...

Hab das Problem auf andere Art gelöst !

int _ABVAR_1_Counter = 0 ;        // Zähler für die Zeit des Tastendrucks

void setup()
{
  pinMode( 3 , INPUT);            // Taster
  pinMode( 12 , OUTPUT);          // LED
  pinMode( 5 , OUTPUT);          // Relais
}

void loop()
{
  while ( ( ( digitalRead(3) ) == ( HIGH ) ) )    // Wird der Taster gedrückt... 
  {
    _ABVAR_1_Counter = ( _ABVAR_1_Counter + 1 ) ;  // ... erhöhe den Zähler pro 100ms um 1
    delay( 100 );                                  // warte 100ms (Zählintervall)
    if (( ( _ABVAR_1_Counter ) >= ( 30 ) ))        // solange ich drücke, teste ob der Zähler über 3 sec liegt
    {
      digitalWrite( 5 , HIGH );                    // Falls ja, lass die LED aufleuchten
      break;
    }
  }

  if (( ( _ABVAR_1_Counter ) >= ( 50 ) ))          // Wenn der Taster 5 sekunden gedrückt wurde, lass das Relais kurz anziehen.
  {
    digitalWrite( 12 , LOW );
    delay( 50 );
    digitalWrite( 12 , HIGH );
    delay( 1000 );
    digitalWrite( 12 , LOW );
    delay( 1000 );
    _ABVAR_1_Counter = 0 ;                        // Danach setze den Counter zurück
  }
}

In der While-Schleife wird alle 100ms ein Zähler erhöht, der mir dann bei erreichen von 5000ms ein Relais anzieht.

Habe das vor Jahren mal in einer Modellraketen Startprozedur mit eingebaut. Bin gerade durch Zufall drauf gestoßen.
Es funktioniert einwandfrei :slight_smile:

Vielen Dank trotzdem nochmal für eure Hilfe.

Schönen Sonntag noch

Wieso nimmst Du einen Zähler und nicht den Millisekundenzähler millis() den wir Dir vorschlagen?
Grüße Uwe

Astrojens:
Habe das vor Jahren mal in einer Modellraketen Startprozedur mit eingebaut. Bin gerade durch Zufall drauf gestoßen.
Es funktioniert einwandfrei :slight_smile:

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:

if ( millis() - Zeitmarke >= 5000 )
...

Die kleiner von der größeren Zahl abziehen.
:slight_smile:

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.

Viel Spaß noch

Gunther

[ironie an]Und es ist immer vorteilhaft und ratsam, in einen Sketch delays und Schleifen einzubauen.[/ironie aus]