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
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!
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
Nicht die Supa-Dupa Methode aber möglicherweise reicht sie bei dir http://shelvin.de/eine-taste-per-interrupt-einlesen-und-entprellen/
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
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] |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.