Sie sind nicht angemeldet.

Lieber Besucher, herzlich willkommen bei: We-Mod-It | Das Forum von Moddern für Modder. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

Scynd

1. Platz Enermax Casecon Contest

  • »Scynd« ist der Autor dieses Themas

Beiträge: 924

Registrierungsdatum: 12. März 2012

Wohnort: München

Beruf: Maschinenbautechniker

Danksagungen: 74

  • Nachricht senden

1

Samstag, 5. September 2015, 22:20

Arduino Tutorial 1.2 - Taster entprellen








Ein Taster ist die einfachste Art um mit dem Arduino zu interagieren und gleichzeitig auch ein schönes Einstiegsbeispiel um in die Welt des Arduinos hinein zu schnuppern.
Das betätigen eines Tasters kann auch so seine Probleme mit sich bringen. Genau gesagt, das schnelle mehrfache schalten des Tasters bei einem einzigen Druck darauf. Dieses Phänomen ist mechanischer Natur und wird Prellen oder Nachprellen genannt.

Ich versuche euch das mal mit einem Beispiel zu erklären.
Wenn man mit dem Arduino z.B. die Variable "Druckzähler" erstellt, die bei 0 startet und bei jedem druck auf den Taster um +1 addiert werden soll, wird das mit einem einfachen Taster Code nicht funktionieren. Der Arduino fragt den Tasterstatus (High oder Low) zig mal pro Sekunde ab und da sich der Status des Tasters durch einfaches Betätigen mehrfach ändert, wird die Variable nicht nur um +1 hochgesetzt, sondern z.B. von 0 auf 6. Jetzt haben wir das Problem, das unser Zähler nicht funktioniert.


Dieses Problem spielt bei einfachen Aufgaben wie eine LED leuchten lassen meistens keine Rolle, deshalb ist das entprellen auch nicht immer nötig.




Auf diesem Oszilloskop sieht man das Prellen des Tasters bei einem einzelnen Druck sehr gut.



Quelle: Wikipedia




Im Normalfall kann man dieses Problem durch das einfügen eines kurzen delays nach der Abfrage des Tasterstatus umgangen werden.

Quellcode

1
2
3
4
5
if (tasterStatus == HIGH) 
 {    
  druckZaehler++;
  delay(300); 
 }


Allerdings funktioniert das bei zeitkritischen Funktionen oder parallelen Abfragen nicht, da so der komplette Ablauf des Programms um z.B. 300ms gestoppt wird und so alle Eingaben oder Ereignisse in dieser Zeit ignoriert werden. Für solche Anwendungsfälle ist dieses Beispiel gedacht.




Teileliste




Anschlussplan







Code

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* 
Arduino Tutorial 1.2 - Taster entprellen

Wenn der Taster gedrückt wird, schalten verschiedene Beleuchtungsmodi durch. 
1. Normales Blinken mit 1000ms delay.
2. Schnellerses Blinken mit 500ms delay.
3. Schnelles Blinken mit 250ms delay.
4. Durchgehendes Leuchten.
5. LED aus.
 

by Scynd 2015
http://www.scynd.de/tutorials/arduino-tutorials.html
*/

// Konstanten
const int tasterPin = 2;      	// Pin Nummer des Tasters
const int ledPin =  3;        	// Pin Nummer der LED des Arduinos

// Variablen
int tasterStatus = LOW;       	// aktuelles Signal vom Eingangspin
int tasterGedrueckt = 0;      	// abfragen ob Taster gedrückt war
int lichtmodus = 0;           	// festlegen der verschiedenen Lichtprogramme
int ledStatus = LOW;          	// aktueller Zusatnd der LED
int entprellZeit = 200;       	// Zeit für Entprellung, anpassen!

unsigned long tasterZeit = 0; 	// Zeit beim drücken des Tasters
unsigned long ledMillis = 0;  	// Zeit für den Blinkrythmus der LED


void setup()
{
  pinMode(ledPin, OUTPUT);  	// LED Pin wird als Ausgang gesetzt
  pinMode(tasterPin, INPUT);	// Taster Pin wird als Eingang gesetzt
}


void loop()
{
  // Lesen des tasterPin
  tasterStatus = digitalRead(tasterPin);

  // Wenn der Taster gedrückt ist...
  if (tasterStatus == HIGH) 
  {
	tasterZeit = millis();  	// aktualisiere tasterZeit
	tasterGedrueckt = 1;    	// speichert, dass Taster gedrückt wurde
  } 

  // Wenn die gewählte entprellZeit vergangen ist und der Taster gedrückt war...
  if ((millis() - tasterZeit > entprellZeit) && tasterGedrueckt == 1)
	{
  	lichtmodus++;         	// lichtmodus wird um +1 erhöht
  	tasterGedrueckt = 0;  	// setzt gedrückten Taster zurück
	}
 
  
  //*************************************Leuchtprogramme**************************************
  
  // Wenn Lichtmodus 0 ist, blinke im 1000ms Rythmus
  if (lichtmodus == 0)
  {
	// Wenn 1000ms vergangen sind...
	if (millis() - ledMillis > 1000)
	{
  	ledStatus = !ledStatus;         	// kehre den letzten LED Zustand um (z.B LOW -> HIGH)
  	digitalWrite(ledPin, ledStatus);	// Ausgabe am LED Pin
  	ledMillis = millis();           	// beginne die Zeitzählung von vorne
	}
  }

  // Wenn Lichtmodus 1 ist, blinke im 500ms Rythmus
  else if (lichtmodus == 1)
  {
	// Wenn 500ms vergangen sind...
	if (millis() - ledMillis > 500)
	{
  	ledStatus = !ledStatus;         	// kehre den letzten LED Zustand um (z.B LOW -> HIGH)
  	digitalWrite(ledPin, ledStatus);	// Ausgabe am LED Pin
  	ledMillis = millis();           	// beginne die Zeitzählung von vorne
	}
  }

  // Wenn Lichtmodus 2 ist, blinke im 250ms Rythmus
  else if (lichtmodus == 2)
  {
	// Wenn 250ms vergangen sind...
	if (millis() - ledMillis > 250)
	{
  	ledStatus = !ledStatus;         	// kehre den letzten LED Zustand um (z.B LOW -> HIGH)
  	digitalWrite(ledPin, ledStatus);	// Ausgabe am LED Pin
  	ledMillis = millis();           	// beginne die Zeitzählung von vorne
	}
  }

  // Wenn Lichtmodus 3 ist, leuchte durchgehend
  else if (lichtmodus == 3)
  {
	digitalWrite(ledPin, HIGH);       	// LED leuchtet
  }
  
  // Wenn Lichtmodus 4 ist, LED aus
  else if (lichtmodus == 4)
  {
	digitalWrite(ledPin, LOW);        	// LED ist aus
  }

  // Wenn der Lichtmodus auf 5 sprngt, setzte ihn wieder zurück auf 0 um von vorne zu beginnen
  else
  {
	lichtmodus = 0;
  }
}



Nach dem setzen der Konstanten und Variablen werden im setup noch die Ein- und Ausgänge deklariert.
Im loop angekommen wird als erstes der tasterPin ausgelesen, und das Ergebnis in der Variable tasterStatus gespeichert. Als nächstes wir mit einer if Abfrage geprüft, ob der Taster gedrückt wurde. Wenn ja, wird die aktuelle Zeit in der Variable tasterZeit gespeichert und die Variable tasterGedrueckt wird auf 1 gesetzt um zu registrieren, dass der Taster gerade gedrückt wurde.
In der nächsten if Abfrage, müssen zwei Bedingungen erfüllt sein, um die Aktion auszulösen. Erstens millis() - tasterZeit muss größer als 200 sein und ( && ) die Variable tasterGedrueckt muss 1 sein. Ist das der Falle, wird lichtmodus um +1 hochgezählt und tasterGedrueckt wieder auf 0 zurückgesetzt, damit die aktuelle if Abfrage erst wieder ausgeköst werden kann, wenn der Taster gedrückt wurde (die erste Bedingung bleibt ja weiterhin wahr). Damit wäre schon einmal der Teil des entprellens erklärt, fehlen nur noch die Lichtmodi.
Nun werden der lichtmodus, den wir vorher gewählt haben abgefragt.
Wenn lichtmodus 0 ist, wird mit if abgefragt ob 1000ms vergangen sind. Wenn ja wird zuerst der letzte Zustand der LED (LOW oder HIGH) umgekehrt um ein blinken der LED zu ermöglichen. Dann muss dieser Zustand per digitalWrite an die LED ausgegeben werden. Zuguter letzt wird die aktuelle Zeit in die Variable ledMillis gespeichert, um den nächsten Blinkzyklus zu ermöglichen.
Wenn lichtmodus 1 oder 2 ist, läuft es genauso wie gerade eben, nur das der Blinkzyklus 500ms bzw. 250ms sind.
Wenn lichtmodus 3 ist, leuchtet die LED per digitalWrite HIGH Befehl die LED durchgehend und bei lichtmodus 4 ist die LED aus.
Zu Schluss muss noch dafür gesorgt werden, dass der lichtmodus wieder auf 0 zurückspringt wenn er 5 oder größer wird, damit man die Leuchtprogramme wieder von vorne durchschalten kann.



Das war es auch schon











Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von »Scynd« (12. Februar 2016, 07:34)