Forum: Mikrocontroller und Digitale Elektronik Interrupt Entprellung


von Anfänger (Gast)


Lesenswert?

Liebe Community,

ich habe folgendes Problem:

ich habe an meinen Arduino einige LEDs angeschlossen, welche über die 
PWM-Ausgänge eine bestimmte "Licht-Routine" durchlaufen, also in einer 
bestimmten Reihenfolge ein- bzw. ausgedimmt werden.

Nun habe ich noch einen Taster an den Interrupt-Port angeschlossen, mit 
welchem das "Lichtspiel" gestartet bzw. beendet werden soll. Dazu ändert 
der Interrupt immer den Wert einer boolschen Variable.

In der Lichtspiel-Methode wird mittels mehrerer Schleifen immer das 
Licht auf- bzw. abgedimmt. Als Schleifenbedingung habe ich mit 
reingeschrieben, dass die boolsche Variable auf true gesetzt sein muss. 
Also so:

for(blue = 0; blue <= 255 && play; blue++) {
// Boolsche Variable play == true, if lights should be on
    analogWrite(bluePin, blue);
    delay(del);
  }

Diese Schleifen kommen nun mehrfach nacheinander für die einzelnen 
Lichter. Am Ende folgt eine Abschaltung aller eventuell noch leuchtender 
LEDs falls die play-Variable FALSE ist, das Lichtspiel also aus sein 
soll.

Allerdings prellt der Taster (habe einen 22nF Kondensator als 
Hardware-Entprellung angeschlossen) immer noch relativ häufig nach und 
stellt somit die play-Variable z.B. auf FALSE (Schleife wird verlassen) 
und gleich wieder auf TRUE (nächste Schleife wird sofort wieder 
betreten, obwohl ja eigentlich das Lichtspiel ausgeschaltet werden 
soll).

Ich habe auch schon versucht in der Interrupt-Methode einen delay 
einzubauen, damit die Interrupt-Methode die gesamte Prelldauer 
überdeckt. Jedoch habe ich das Gefühl, dass einfach während die 
Interrupt-Methode ausgeführt wird, durch das Prellen sofort wieder ein 
Interrupt ausgelöst wird, also der Delay keine Auswirkung hat.

Habt ihr einen Vorschlag für mich, wie ich das lösen kann? Bin absoluter 
Anfänger.

Oder allgemeiner formuliert: Wie kann ich eine längere Routine (hier das 
Lichtspiel) durch einen Tastendruck sofort unterbrechen (hier der 
Interrupt) und bei erneutem Druck von vorne starten lassen.

Vielen lieben Dank,
Ein Anfänger

von Eric B. (beric)


Lesenswert?


von m.n. (Gast)


Lesenswert?

Hier hast Du eun Beispiel, wie es gemacht werden kann: 
http://www.mino-elektronik.de/power_at90s/powerat90s.htm

Als Anfänger wirst Du es vermutlich nicht verstehen und alle Anderen 
hier werden Dir sagen, das ist Murks, das darf man nicht.
Mach etwas daraus!

von Max B. (theeye)


Lesenswert?

Hast du dir die Mühe gemacht a) die Suche zu verwenden und/oder b) mal 
zu googeln? Das Thema ist hier schon im Detail behandelt worden und sehr 
gut zusammengefasst in einem Artikel nachzulesen.

Eric B. schrieb:
> http://www.mikrocontroller.net/articles/Entprellung

Eric hat dich schon auf den richtigen Weg gebracht.

Hättest du die Suche verwendet, hättest du diesen Thread (von vor 10 
Tagen!) gefunden Beitrag "Tastenentprellen während externen Interrupt - ATmega16". Dort 
hat jemand genau das selbe Problem (Taster am Interrupt entprellen). 
Hilft vielleicht noch mehr zum Verstehen.

Nicht entmutigen lassen und dran bleiben :-)

Gruß Max

von noma (Gast)


Lesenswert?

Nicht die Supa-Dupa Methode aber möglicherweise reicht sie bei dir
http://shelvin.de/eine-taste-per-interrupt-einlesen-und-entprellen/

von Anfänger (Gast)


Lesenswert?

Ich habe jetzt versucht den Interrupt zu umgehen und einfach mittels 
Timer und regelmäßige Polling einen Tastendruck zu erkennen. Allerdings 
scheint dass ein Problem zu verursachen.

Ich bin folgendermaßen vorgegangen:
Der Timer löst alle 10ms eine Methode aus, welche guckt ob die Taste 
gedrückt worden ist. Wenn das 5x hintereinander der Fall ist (also 50ms 
lang) dann wird das als Tastendruck interpretiert und eine boolsche 
Variable auf true gesetzt.

Ansonsten habe ich meine "Lichtspiel"-Methode identisch gelassen. Doch 
leider funktioniert es immer noch nicht.

Hier ein vereinfachtes Code-Beispiel:
1
#include <TimerOne.h>
2
3
int redPin = 9, bluePin = 10, greenPin = 11; // PWM-Pins für zu dimmende LEDs
4
int button = 8; // Pin für Taster
5
int red = 0, blue = 0, green = 0;
6
int del = 10; // delay time
7
double tc = 10000; // 10ms timer
8
volatile boolean play = false; // on-off-switch variable
9
volatile int counter = 0;
10
volatile int state = LOW;
11
12
void setup() {
13
  Serial.begin(9600);
14
  pinMode(redPin, OUTPUT);
15
  pinMode(bluePin, OUTPUT);
16
  pinMode(greenPin, OUTPUT);
17
  pinMode(button, INPUT);
18
  digitalWrite(button, HIGH);
19
  Timer1.initialize(tc);
20
  Timer1.attachInterrupt(buttonPolling);
21
}
22
23
void buttonPolling() {
24
  if(digitalRead(button) == LOW) counter++;
25
  if(counter > 4) {
26
    Serial.print("Before - Play: "); // Debug info
27
    Serial.println(play);
28
    play = !play;
29
    counter = 0;
30
    Serial.print("After - Play: "); // Debug info
31
    Serial.println(play);
32
  }
33
}
34
35
void loop() {
36
  for(red = 0; red <= 255 && play; red++) {
37
    analogWrite(redPin, red);
38
    delay(del); 
39
  }
40
  for(blue = 0; blue <= 255 && play; blue++) {
41
    analogWrite(bluePin, blue);
42
    delay(del); 
43
  }
44
  for(green = 0; green <= 255 && play; green++) {
45
    analogWrite(greenPin, green);
46
    delay(del); 
47
  }
48
  for(blue = 255; blue >= 0 && play; blue--) {
49
    analogWrite(bluePin, blue);
50
    delay(del); 
51
  }
52
  for(red = 255; red >= 0 && play; red--) {
53
    analogWrite(redPin, red);
54
    delay(del); 
55
  }
56
  for(green = 255; green >= 0 && play; green--) {
57
    analogWrite(greenPin, green);
58
    delay(del); 
59
  }
60
  if(!play) { // Lichter ausschalten falls Ausschalten gedrückt wurde
61
    analogWrite(redPin, 0);
62
    analogWrite(bluePin, 0);
63
    analogWrite(greenPin, 0);
64
  }
65
  Serial.print("Play: "); // Debug info
66
  Serial.println(play);
67
}
Meiner Ansicht nach müssten jetzt beim Start alle Lichter aus sein, da 
play = false ist und somit alle Lichter aus bleiben. Mit dem ersten 
Knopfdruck wird die Play-Variable auf true gesetzt und dadurch werden 
die Schleifen durchlaufen. Somit sollten die Lichter nacheinander 
eingedimmt und schließlich wieder ausgedimmt werden usw.

Bei erneutem Tastendruck, müsste play dann wieder auf false gesetzt 
werden und damit die Schleifen alle nicht mehr betreten werden und die 
Lichter ausgeschalten werden.

Leider passiert aber gar nichts davon. In der Realität beginnen die LEDs 
sich stockend ein- und auszuschalten (nicht-fließender Übergang) und 
manche Tastendrucke werden einfach, andere mehrfach registriert. 
Außerdem kommt es zu diesen komischen Ereignissen:

// Debug info
Play: 0
Play: 0
Play: 0
PBay: 1 // play wird vor dem Änderungsbefehl schon auf true gesetzt!?
Before - Play: 1
After - Play: 0
Play: 0
Play: 0
Play: 0

Obwohl die Variable play sich nur in der buttonPolling()-Methode 
verändern kann, scheint sie sich schon kurz vor dem play = !play zu 
ändern und wird dann durch den eigentlichen Änderungsbefehl wieder 
zurück auf den ursprünglichen Wert gesetzt, denn play vor dem Polling 
hatte...

Ohne den Timer und das Polling funktioniert die LED-Abfolge aber 
einwandfrei. Lichter werden langsam aus und wieder ein gedimmt.

Kann mir jemand weiterhelfen? Gerne auch mit einem komplett anderen Weg 
dieses Problem zu lösen.

Verstehe einfach nicht woran das liegen könnte..

Vielen Dank schon mal im Voraus!

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Was meinst du wohl, wie lange eine serielle Schnittstelle mit 9600 Baud 
zum Senden eines einzelnen Zeichens brauchen könnte? Und wie viele 
versendest du? Wie lange dauert also dieser kurze Interrupt (Interrupt = 
Unterbrechung der "normalen" Arbeit!!!).
Für jede Hausfrau ist klar: wenn der Postbote klingelt und du 
vertratscht dich mit dem für eine halbe Stunde an der Tür, dann ist es 
kein Wunder, wenn die Milch überkocht...
Die Milch ist deine Hauptschleife, der Postbote die Unterbrechung.

Du solltest im Interrupt nur ein Flag setzen, und das in der 
Haupschleife auswerten. Kann natürlich sein, dass du dann deine 
Hauptschleife ein wenig umbauen musst...


BTW: bitte verwende die C-Tags um deinen Quelltext.
1
[c]
2
   C-Code
3
[/c]

von Peter D. (peda)


Lesenswert?

Das Entprellen ist nur die halbe Miete. Du mußt noch den Flankenwechsel 
von losgelassen nach gedrückt erkennen.
Außerdem ist es zuverlässiger, auch das Loslassen zu entprellen, also 
beide Flanken.

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.