Forum: Mikrocontroller und Digitale Elektronik Taster und Blinklicht an/aus


von Alexander H. (agentsmith1612)


Lesenswert?

Hallo liebe Mikrocontroller Gemeinde,

ich habe mir einen Arduino gekauft und einiges darüber gelesen und auch 
ausprobiert.
Ich möchte gerne ein Blinklicht bauen mit einem Taster, das wenn ich 
diesen Drücke das Bliniklicht im 750ms Takt leuchtet und wenn ich 
nochmnal drücke es ausgeht.

Ganz klassisch hatte ich ein Blinklicht mit "delay(375)" programmiert. 
Dazu habe ich jetzt gelesen, dass delay im Falle eines Tasters nicht 
optimal ist, da in dem Fall wenn das Loop gerade im Delay ist der Taster 
nicht registriert wird.
Daher habe ich mittels "Mills" die Blinklichter umprogrammiert, mit dem 
weiteren Vorteil dass ich nur eine Parameter habe wo ich die Zeit ändern 
muss und nicht bei jedem Delay bzw. Ausgang. Wirklich verstanden habe 
ich den Code für Mills aber nicht.
Das fängt schon bei "unsigned long previousMillis an, ich verstehe 
einfach nicht was dieser Befehl an dieser Stelle macht. Im Prinzip hab 
ich das ganze mit CurrentMills und previoius Mills und den Abgleich 
unten nicht verstanden.

Aber ist auch nicht ganz so wichtig. Wichtig wäre mir wie ich jetzt den 
Schalter darin bekomme.
Ich hatte mal was drin mit einem Schalter, da reagierte das System dann 
aber so, dass wenn ich den Schalter gedrückt hielt alles blinkte wie es 
sollte, sobaldich loßließ das das Loop aber in dem gerade Zustand 
verblieben ist, also entweder aus blieb oder an blieb.

Das liegt sicher auch an meinem Millis Konstrukt.

Ich möchte nämlich als "Fernziel" ein LED Leiste bauen wo man per Taster 
die Modi wechseln kann, sprich, vom ausgeschaltete Zustand --> Drücken 
--> An --> Drücken --> blinken--> Drücken --> Lauflicht --> Drücken --> 
Pulsieren--> Drücken-- aus

Hier mal mein Code.
Ich wäre sehr dankbar wenn mir jemand ein klein wenig auf die Sprünge 
helfen könnte.


const int led1 = 2;
const int led2 = 3;
const int led3 = 4;
const int Piep = 5;

int ledState = LOW;

unsigned long previousMillis = 0;

const long interval = 375;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
}
void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {

    previousMillis = currentMillis;

 if (ledState == LOW)
    {
      ledState = HIGH;
    } else
    {
      ledState = LOW;
    }


  digitalWrite(led1, ledState);
  digitalWrite(led2, ledState);
  digitalWrite(led3, ledState);
  digitalWrite(Piep, ledState);

}
}

von Thomas E. (thomase)


Lesenswert?

Alexander H. schrieb:
> Das fängt schon bei "unsigned long previousMillis an, ich verstehe
> einfach nicht was dieser Befehl an dieser Stelle macht. Im Prinzip hab
> ich das ganze mit CurrentMills und previoius Mills und den Abgleich
> unten nicht verstanden.

Das ist ja auch kein Befehl, sondern eine Variable.

Hast du schon mal Eier gekocht?

Du setzt irgendwann die Eier auf:  previousUhrzeit
Du guckst laufend auf die Uhr:     currentUhrzeit
Wann sind die Eier fertig?
Wenn currentUhrzeit - previousUhrzeit = 5min.

Genauso macht der Controller das auch. Nur eben mit Millisekunden.

Zum Taster:

Ein Taster prellt. Guck dir den Artikel an, da steht alles Wissenswerte 
drin:

https://www.mikrocontroller.net/articles/Entprellung

Wenn du das durch hast, suchst mal nach Arduino und Entprellung bzw. 
englisch nach Debounce. Da wirst du bestimmt was finden. Die 
Arduino-Gemeinde benutzt ja schliesslich auch Taster.

von Alexander H. (agentsmith1612)


Lesenswert?

Vielen Dank Thomas für deine Hilfe nun bin ich etwas weiter gekommen.

Um das vielleicht etwas zusammenzufassen ob ich das richtig verstanden 
habe.
Ich fing an mit "unsigned long previousMillis = 0;" das heißt dann fange 
beim 0 Uhr an im Prinzip.
Warum da jetzut unsigned steht und was long bedeutet zumal bei manchen 
"Anleitungen" mit unsigned gearbeitet wird und bei manchen nicht.

Dann kommt mit "long" das Interval.

dann kommt unsigned long currentMillis = millis(); also die aktuelle 
Zeit wird dann nur noch Zeit?

Prüfe ob der jetzige Augenblick größer ist als das Intervall, wenn ja 
dann wenn die Lampe an ist auschalten wenn nein dann aus lassen bzw, an 
lassen.

und dann wieder previousMillis = currentMillis;   Alte Zeit wird neue?


Das Schalter "bouncen" habe ich schon mal gehört, aber ich wage mich da 
noch nicht ran wenn ich noch nicht einmal millis richtig verstanden 
habe.

Tut mir Leid, dass ist sicher gar nicht so schwer nur werde ich mit den 
Abstrakten Erklärungen nicht schlau.
Das mit den Eiern das war schon sehr anschaulich und praxisnah.

Besten Dank schonmal.

von Manfred (Gast)


Lesenswert?

Alexander H. schrieb:
> if (ledState == LOW)
>     {
>       ledState = HIGH;
>     } else
>     {
>       ledState = LOW;
>     }

Anstatt if-else kann man auch den Istzustand der LED lesen und 
invertiert (umgedreht) wieder ausgeben:
digitalWrite (LED1, !digitalRead(LED1));

--------

Für den Taster würde ich eine weitere Variable erzeugen, z.B.
LED_ein = 0

Taster abfragen, wenn Taster gedrückt, dann LED_ein = !LED_ein - also 
die Variable umdrehen. Um Deine Blinkschleife legst Du ein If herum: If 
LED_ein==0 dann return (direkt raus) else Blinken ausführen.

Jetzt bleibt noch zu klären, in welchem Zustand die LEDs verbleiben, 
wenn umgeschaltet wird - sie sind zufällig entweder an oder aus.

Ich spreche das nicht so fließend, dass ich Dir hier frei aus dem Kopf 
spielfähigen Code schreiben kann, von daher nur die prinzipielle 
Erläuterung, wie ich es angehen würde. Real auf dem Tisch habe ich schon 
komplexere Dinge gelöst.

von Manfred (Gast)


Lesenswert?

Alexander H. schrieb:
> Warum da jetzt unsigned steht und was long bedeutet
Variablentypen wurden erfunden, um den Bastler zu ärgern! Nimm einfach 
mal das "long" und "unsigned" raus und wundere Dich, dass Deine LEDs 
nach 32 Sekunden dummes Zeug machen. Dann nur "unsigned" hinzu, müsste 
nach 65 Sekunden Dummfug passieren.

Eine Variable ist 16 Bit lang, das ergibt 65535 (Millisekunden). Man 
möchte aber auch gerne mit negativen Zahlen rechnen, also definiert man 
das höchste Bit als Vorzeichen - damit geht die 16bit-Variable von 
-32768 bis +32768.

Die Bezeichnung ist "sign", also sagt "unsigned", dass man das 
Vorzeichen nicht will und der Wert nur positiv von 0 bis 65535 gehen 
soll.

Da 65535 Millisekunden nicht wirklich viel sind, wäre es nett, mehr zu 
haben - also "long", dann wird das ein Wert mit 32 Bit entsprechend 
maximal 4294967296 - das sind 49,7 Tage, bis der dann überläuft, also 
von 4294967296 nach 0 wechselt.

49,7 Tage, grins, schonmal gehört? Das war die maximale Zeit 
Dauerbetrieb, bevor Windows98 auf die Fresse gefallen ist.

von LostInMusic (Gast)


Lesenswert?

>also definiert man das höchste Bit als Vorzeichen

Nein, auch wenn es auf den ersten Blick so aussehen mag.

- damit geht die >16bit-Variable von -32768 bis +32768.

Die geht von -32768 bis +32767.

https://de.wikipedia.org/wiki/Zweierkomplement

von Thomas E. (picalic)


Lesenswert?

Manfred schrieb:
> dann wird das ein Wert mit 32 Bit entsprechend
> maximal 4294967296

[Korinthenkacker]der mit 32 Bit maximal darstellbare Wert ist aber nur 
4294967295[/Korinthenkacker]

Mit etwas Geschick kann man aber auch den Fehler nach 49,7 Tagen 
vermeiden und braucht obendrein dafür nur 16 Bit Variablen, und bei < 
128 ms Zeitintervallen würden sogar durchgängig 8 Bit reichen (obwohl 
millis() mehr Bits zurückgibt). Um bei dem Beispiel zum Eierkochen zu 
bleiben: was interessiert mich da der Stundenzeiger, und wenn man die 
Eier um 23:59 aufsetzt wird auch kein Mensch durch die Zeitablesung die 
Eier plötzlich 23 Stunden und 55 Minuten kochen.

: Bearbeitet durch User
von Alexander H. (agentsmith1612)


Lesenswert?

Vielen Dank an alle Beteiligten.

Ich habe mich zunächst weiter mit dem Blinklicht ohne Delay beschäftigt 
und habe jetzt endlich verstanden was der Code da genau macht.
Ich musste Gedanklich erstmal über den Punkt hinaus kommen das das Loop 
ja mehrfach pro Sekunden durchläuft und der Code sogesehen erst 
ausgeführt wird wenn die erst Millisekunde des Intervalls anliegt.

Soweit also das Blinklicht mit Millis verstanden.

Bezüglich unsigned und long, heißt das überall wo ich Zeiten messe mit 
millis sollte ich unsigned long davor verwenden?

Ich habe mit Tastern weiter gemacht die ich als Pull Up Widerstand 
verbaut habe.

Folgenden Code habe ich dann dazu geschrieben:

//LEDS beschreiben:
int rot = 2;
int gelb = 3;
int gruen = 4;

//Taster beschreiben:
int tasterrot = 8;
int tastergelb = 9;
int tastergruen = 10;

//LED Anfangsstatus beschreiben:
int rotState = LOW;
int gelbState = LOW;
int gruenState = LOW;

//Taster Anfangsstatus beschreiben:
int readingtasterrot;
int readingtastergelb;
int readingtastergruen;

//vorherigen Tasterstatus beschreiben:
int previoustasterrot = LOW;
int previoustastergelb = LOW;
int previoustastergruen = LOW;



unsigned long timerot = 0;
unsigned long timegelb = 0;
unsigned long timegruen = 0;
unsigned long debounce = 200;


void setup()
{
  pinMode(tasterrot, INPUT);
  pinMode(tastergelb, INPUT);
  pinMode(tastergruen, INPUT);
  pinMode(rot, OUTPUT);
  pinMode(gelb, OUTPUT);
  pinMode(gruen, OUTPUT);
}

void loop()
{
  readingtasterrot = digitalRead(tasterrot);
  readingtastergelb = digitalRead(tastergelb);
  readingtastergruen = digitalRead(tastergruen);

  if (readingtasterrot == HIGH && previoustasterrot == LOW && millis() - 
timerot > debounce) {
    if (rotState == HIGH)
      rotState = LOW;
    else
      rotState = HIGH;

    timerot = millis();
  }
  if (readingtastergelb == HIGH && previoustastergelb == LOW && millis() 
- timegelb > debounce) {
    if (gelbState == HIGH)
      gelbState = LOW;
    else
      gelbState = HIGH;

    timegelb = millis();
  }
    if (readingtastergruen == HIGH && previoustastergruen == LOW && 
millis() - timegelb > debounce) {
    if (gruenState == HIGH)
      gruenState = LOW;
    else
      gruenState = HIGH;

    timegruen = millis();
  }

  digitalWrite(rot, rotState);
  digitalWrite(gelb, gelbState);
  digitalWrite(gruen, gruenState);

  previoustasterrot = readingtasterrot;
  previoustastergelb = readingtastergelb;
  previoustastergruen = readingtastergruen;
}


Hier jetzt die Frage wo sollte bezüglich Millis noch ein unsigned long 
hin?
Ich habe noch das Problem dass man manchmal nicht wirklich richtig gut 
schalten kann die LED geht aus aber direkt wieder an oder umgekehrt, das 
liegt wohlam Bouncen oder?

von Hubert G. (hubertg)


Lesenswert?

Alexander H. schrieb:
> Ich habe mit Tastern weiter gemacht die ich als Pull Up Widerstand
> verbaut habe.

PullDown Widerstände auch dazu verbaut?

von Alexander H. (agentsmith1612)


Lesenswert?

Sorry ich hab mich verschrieben.
Ich habe den Taster als Pulldown gebaut.
Sprich
5v --> Taster ------> Pinkontakt am Arduino
      ---> Wiederstand 1k Ohm --> GND

Strom fließt also beim drücken zum Pin und ansonsten von + über den 
Widerstand nach Ground.

So hab ichs gebaut: http://rn-wissen.de/wiki/images/7/79/Pulldown.gif

Oder heißt das, dass ich den Taster mit der Methode gar nicht entprellt 
habe?

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.