LED LEuchtdauer

Hallo zusammen
Bin relativ kurz erst dabei mich mit dem Thema zu beschäftigen. Bin aber permanent dabei mich zu informieren und am herum testen.
Jetzt steh ich allerdings vor einer Aufgabe die ich absolut nicht meistern kann obwohl ich diese Funktion x-fach auf meiner Modelbahnanlage brauchen würde.
Ich habe mein Board bestückt zum testen mit Taster und LED. Wenn ich den Taster drücke leuchtet sie und wenn ich den Taster loslasse geht sie aus ganz klar.
Jetzt hätt ich aber gerne das wenn ich den Taster betätige die LED zb für sagen wir mal 60 Sek leuchtet und dann wieder ausgeht. Ich hab mich jetzt schon eingehend mit millis beschäftigt aber das will einfach nicht in meinen Kopf rein. Mein momentaner Sketch sieht folgendermaßen aus.

const int buttonPin = 12;
const int ledPin = 2;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}

void loop() {
if (digitalRead(buttonPin) == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
}

Ich finde weder den passenden Befehl für diese Aktion noch würde ich dann wissen wo dieser in meinem Sketch einzufügen wäre.
Könnte mir bitte jemand unter die Arme greifen?

LG Odi77

Du könntest es mal mit den MobaTools probieren. Da ist ein Beispiel drin, das genau das macht, was Du willst.

(deleted)

odi77:
Jetzt hätt ich aber gerne das wenn ich den Taster betätige die LED zb für sagen wir mal 60 Sek leuchtet und dann wieder ausgeht. Ich hab mich jetzt schon eingehend mit millis beschäftigt aber das will einfach nicht in meinen Kopf rein.

Die einfachste Variante wäre, ein delay(60*1000); nach dem Einschalten einzufügen.

Wenn Du mit millis() arbeiten möchtest, musst Du Dir merken, wann gedrückt wurde, z.B. in einer Variablen vom Typ long. In weiteren loop()-Durchläufen testest Du dann, ob diese Variable um 60000 größer als der aktuelle Wert ist, den millis() zurückgibt:

if(millis() - millisMem > 60000)
{ digitalWrite(LEDPIN, LOW); }

Die nächste Überlegung wäre, ob der 60-Sekunden-Intervall bei jedem Tastendruck neu gestartet wird und ob die LED ausgehen soll, obwohl der Taster immer noch gedrückt ist.

Guck z.B. hier.

Gewöhne Dir außerdem an, grundsätzlich und vom Start weg „schönen“ Code zu schreiben. Das hilft Dir und anderen, den Überblick zu behalten/zu bekommen.

Gruß

Gregor

@MicroBahner

Danke für den link aber das funktioniert nicht, hab gesucht an was es liegt aber wird nicht fündig.

@Peter CAD-HST

Hab ich mir geladen aber komm nicht weiter, bin nicht ganz sicher wo ich welche Werte einsetzen soll/muss

@gregorss

Es müssen nicht unbedingt millis sein, das war nur der einzige Weg bzw Anwendung die ich dafür gefunden habe ohne aber zu wissen wie es funktioniert. Die LED soll definitiv nach den zb 60 Sekunden ausgehen. Sind kleine Aktionen auf meiner Modellbahnanlage zb Tastendruck 60 Sekunden Lagerfeuer später auch zb Rauchgenerator oder Servo der nen KRan bewegt etc.

Weitegekommen bin ich jetzt noch nicht. Aber schon mal vielen lieben Dank für euer Bemühen.

in anderen Worten:
millis() ist sozusagen deine System-Uhrzeit.
in previousMillis merkst du dir wann du die LED eingeschalten hast.

wenn die aktuelle Uhrzeit [wieder aus millis()] minus der gemerkten Einschaltuhrzeit größer ist als deine Wunschlaufzeit, dann schaltest die LED wieder ab.

Damit der zweite If nicht immer erfüllt ist und permanent die LED abgeschaltet wird, prüfst du einfach auch ab ob die LED überhaupt noch läuft.

Und vorsicht, previousMillis sollte unsigned sein, millis() hat keine Vorzeichen

kompiliert, aber ungeprüft:

const int buttonPin = 12;
const int ledPin = 2;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() {
  static uint32_t previousMillis = 0;  // du brauchst eine unsigned integer Variable mit 32bit/4Byte, weil millis() auch so groß werden kann.
  if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);
    previousMillis = millis();   // Einschaltzeit "merken"
  }

  if (millis() - previousMillis > 60 * 1000UL && digitalRead(ledPin) == HIGH)  // wenn Zeit abgelaufen und die LED leuchtet
  {
    digitalWrite(ledPin, LOW);
  }
}

wenn das klappt, gibst bescheid, dann bauen wir das noch leicht um, sodass du mit den anderen Sachen nicht Troubles bekommst.

odi77:
@MicroBahner

Danke für den link aber das funktioniert nicht, hab gesucht an was es liegt aber wird nicht fündig.

Was funktioniert denn nicht? ( Du musst die MobaTools natürlich auch installieren - das geht direkt im Bibliotheksmanager der IDE )

odi77:
@gregorss
...

Danke für das Feedback!

Sieh Dir unbedingt das Modell des Endlichen Automaten an! Und die MobaTools sind für Modellbaukram eine echt nette Sammlung nützlicher Tools.

Gruß

Gregor

@ noiasca

Dankeschön das war ja schon Zuviel des guten, das funktioniert genau so wie ich es wollte.

@ MicroBahner

Da muss ich zu meiner Schande gestehen das ich noch nicht weiß wie das funktioniert. Hab schon davon gelesen das es sowas gibt aber noch keine Zeit gefunden mich damit zu befassen. Klingt aber gut das es das gibt wenn es auf der Seite mehrere brauchbare Sachen gibt.

@ gregorss

Mobatools werden umgehend gesichtet und gelernt wie man sie richtig verwendet. So wie ich es Microbahner schon geschrieben habe.

... und verstanden auch? Oder gibts noch Fragen?

odi77:
@ MicroBahner

Da muss ich zu meiner Schande gestehen das ich noch nicht weiß wie das funktioniert.

Bibliotheksmanager öffnen ( mit ctrl-shift-I oder Werkzeuge->Bibliotheken verwalten... ). Dann im Suchfeld oben rechts 'mobatools' eingeben ( groß/Kleinschreibung ist egal ) . Rechts unten auf 'installieren' drücken - fertig.
Dann findest Du unter Datei->Beispiele->MobaTools->Zeitgeber_02 auch das Beispiel.

@noiasca

Nein nicht ganz. Da steht bei dem einen Punkt ( Einschaltzeit merken ). Warum ? Ist die Einschaltzeit nicht die Zeit wo ich den Taster betätige ?

@MicroBahner

Gesagt getan, hab sie jetzt drinnen. Nur bei dem 02 kenn ich mich gar nicht aus wüsste nicht wo ich da Parameter ändern muss das ich da was zum laufen bekomme.

Ich kann mich nur wiederholen, vielen lieben Dank

ja schon, aber du kannst bildlich gesprochen in eine Zeile nur eine Anweisung schreiben.
Also schaltest erst den Pin ein, und dann merkst dir Zeit wann du es gemachst hast. Das ist halt ein paar Microsekunden später, mit dieser "Ungenauigkeit" musst halt leben.

@noiasca

Muss ich die Microsekunden denn irgendwo angeben ? sehen tu ich nix. Oder ist das einfach der normale Vorgang weil ja klar , erst Schalter dann LED.

Es gibt verschiedene Möglichkeiten, die Sache anzugehen...
Auch diese Variante nutzt intern das "BlinkWithoutDelay" Konzept.

#include <CombiePin.h>
#include <CombieTimer.h>
#include <CombieTypeMangling.h>

using namespace Combie::Millis;

//Combie::Pin::TasterGND<2> taster; // mit pullup, invertierend
Combie::Pin::InputPin<2> taster;    // mit pulldown
Combie::Pin::OutputPin<13> led;
Combie::Timer::FallingEdgeTimer fallingEdge(6_sec);// Nachleuchtdauer

void setup()
{
  //taster.initPullup();// mit pullup
  taster.init();// mit pulldown
  led.init();
}

void loop()
{
  led = fallingEdge = taster;
}

Die nötigen Libraries findest du hier

möglicherweise reden wir aneinander vorbei.

im Code steht:

digitalWrite(ledPin, HIGH);
previousMillis = millis(); // Einschaltzeit "merken"

du fragtest

Warum ? Ist die Einschaltzeit nicht die Zeit wo ich den Taster betätige ?

die blaue Zeile schaltet den Taster ein.
die rote Zeile merkt sich unmittelbar danach die Zeit.
Das sind zwei Anweisungen.
Gleichzeitig, oder "auf einmal" geht nicht.
Die blaue Zeile merkt sich keine Zeit.
Daher brauchst du die rote auch.
Verständlich?

odi77:
Nur bei dem 02 kenn ich mich gar nicht aus wüsste nicht wo ich da Parameter ändern muss das ich da was zum laufen bekomme.

Eigentlich musst Du nur die Pinnummern am Amfang anpassen. Aber ich habe gesehen, dass Du nicht den eingebauten PullUp Widerstand verwendest, sondern mit einem externen PullDown arbeitest.

Aber im Prinzip ist es dasselbe wie der Sketch von noiasca, nur dass man sich nicht direkt mit millis() rumschlagen muss:

#include <MobaTools.h>

const int buttonPin = 12;
const int ledPin = 2;

MoToTimer Blinkzeit1;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop() {
  if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);
    Blinkzeit1.setTime( 60000L );
  }

  if ( Blinkzeit1.expired() ) 
  {
    digitalWrite(ledPin, LOW);
  }
}

@ noiasca

Sie merkt sich die Zeit wann ich den Schalter betätigt habe und ab da läuft dann die vorgegebene Zeit ? Ist die vorgegebene Zeit die Zeit die es sich merkt oder um welche Zeit geht's da ?Ich glaub da blick ich nicht ganz durch mehr, war jetzt alles schon bissi viel. Entschuldigung...

@Microbahner

Soweit so gut, funktioniert auch problemlos. Was ich nicht verstehe ist allerdings warum es mit Blinkzeit angegeben ist, es blinkt ja nix.

Eine Frage hab ich jetzt zusätzlich noch. Wenn jetzt zb was schief läuft sagen wir mal mit einem Servo das wo was hängt oder so. Kann ich den Taster auch ZUSÄTZLICH damit belegen das er bei neuer Betätigung das Zeitprogramm unterbricht ?

jein.

geh den Code Schrittweise durch, der Controller machts auch nicht anders.

der loop läuft
if (digitalRead(buttonPin) == HIGH) {

ist der erste if true, werden die blaue und rote Zeile ausgeführt.

millis sagen wir hat zu dem Zeitpunkt den wert 2000 also steht in previousMillis auch 2000.

Dann komm es zum zweiten if

millis wird vieleicht schon auf 2002 stehen,

if (millis() - previousMillis > 60 * 1000UL && digitalRead(ledPin) == HIGH) // wenn Zeit abgelaufen und die

(2002 - 2000 > 60 * 1000UL)

also
(2 > 60000)
nein ist nicht. Daher wird der if nicht ausgeführt.

Wir kommen ans ende von loop.
Daher beginnt es wieder von vorne:

erster grüner If ... der Taster ist nicht gedrückt, der Controller geht also drüber
zweiter if

millis hat jetzt etwa 2015
also

if (2015-2000 > 60000)

nein ist immer noch nicht erfüllt.
Zum Ende von loop.
Wieder an den Anfang von loop.
erster If
Zweiter if
etc

Das passiert viele tausende male.
Bis millis mindestens 62.001 ist

ab dann wird diese Bedinung true:
if (62001- 2000 > 60000)

ausrechnen:
60001 > 60000
Bingo! der if ist erfüllt.
JETZT nach 60001 Millisekunden, gehen wir in den zweiten If und schalten die LED aus.
"Systemzeit" ist also 62001, eingeschaltet haben wir um 2000. Also passt. Nach einer Wartezeit von 60 Sekunden haben wir die LED ausgeschaltet.

So, jetzt erfindest einen neuen Zeitstempel wann du die Taste drückst und spielst es selber 60TSD mal durch

odi77:
Was ich nicht verstehe ist allerdings warum es mit Blinkzeit angegeben ist, es blinkt ja nix.

Namen sind Schall und Rauch :wink: . Wenn Du immer wieder den Taster drückst blinkt es ja 8) .
Du kannst es ja einfach anders benennen.

odi77:
Eine Frage hab ich jetzt zusätzlich noch. Wenn jetzt zb was schief läuft sagen wir mal mit einem Servo das wo was hängt oder so. Kann ich den Taster auch ZUSÄTZLICH damit belegen das er bei neuer Betätigung das Zeitprogramm unterbricht ?

Du meinst, wenn Du drückst während die Zeit läuft, dass dann die Led vorzeitig ausgeht?