Go Down

Topic: Tastereingabe mit Wartezeit/Verzögerung (Read 2220 times) previous topic - next topic

Astrojens

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

uwefed

Verwende millis(). siehe blinkwithoutdelay Beispiel.
https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
Grüße Uwe

MaHa76

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.

Theseus

#3
Oct 09, 2016, 09:18 am Last Edit: Oct 09, 2016, 09:18 am by Theseus
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.

MaHa76

mal ins Unreine getippt...:

Code: [Select]

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

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

Theseus

mal ins Unreine getippt...:
Es geht noch einfacher:

Code: [Select]

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

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

MaHa76

#6
Oct 09, 2016, 10:04 am Last Edit: Oct 09, 2016, 10:05 am by MaHa76
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.

Astrojens

Ja geil,

danke erstmal für eure Antworten  :o  :)
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

Astrojens

Habs mal probiert.

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

Wahrscheinlich hab ich irgendwas vergessen oder falsch verstanden.  :smiley-confuse:


Code: [Select]
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);
 }
}

Scherheinz

Weil du den Pin nie wieder ausschaltest
Hier könnte ihre Werbung stehen

Theseus

#10
Oct 09, 2016, 11:30 am Last Edit: Oct 09, 2016, 11:31 am by Theseus
Es fehlt die Abfrage des Tastpins. Also in der Loop
Code: [Select]
if ( digitalRead(tastPin) != HIGH )//Ersetzen ob high oder low gedrücktem Taster entspricht
   { Zeitmarke = millis(); }

Astrojens

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.



Code: [Select]
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);
 }
}


guntherb

#12
Oct 09, 2016, 12:32 pm Last Edit: Oct 09, 2016, 12:33 pm by guntherb
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:
Code: [Select]
if ( millis() - Zeitmarke  >= 5000 && gedrueckt) // 5sek nach Tastendruck
  { digitalWrite(ledPin, HIGH);                    // LED einschalten
    Serial.println("LED AN");
  }
Grüße
Gunther

MaHa76

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

Hab das Problem auf andere Art gelöst !


Code: [Select]
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  :)

Vielen Dank trotzdem nochmal für eure Hilfe.


Schönen Sonntag noch

Go Up