Hallo,
ich habe das Problem, dass sich der Status über die Leds nicht ändert.
Sobald das Programm startet, werden die Ausgänge der Leds HIGH gesetzt
und danach bleiben diese unverändert. Sie reagieren nicht auf die
Tastendrücke.
Die Taster sind als Low-Active angeschlossen
1
T
2
___ ---
3
VCC ----------|___|--o----o o---------- GND
4
10k |
5
'----------- INPUT MCU
6
7
___ LED
8
OUTPUT MCU ---|___|-------->|- -------- GND
9
680
10
(created by AACircuit v1.28.6 beta 04/19/05 www.tech-chat.de)
Also an den Leds liegt es nicht, habe die nun anders getestet. Die
Taster machen jedoch immer noch nicht, was ich von Ihnen möchte.
Habe diese ohne Entprellen getestet und es ging.
Ich persönlich hab noch nie ganz verstanden warum so oft so großer
proceduraler Aufwand betrieben wird um softwaremässig zu entprellen. Ein
Kondensator und ein Wiederstand mehr reichen und man muss nichts in der
SW entprellen. Eine ISR dafür zu nehmen ist eh übertrieben und schade um
den INtrrupt.
Warum probierst du nicht einfach _delay_ms(50);
if(taste high)
{_delay_ms(x);
led ein;
}
X durch probiern auswaehlen..
Mach ich bei Matrixtastatur etc. immer so und hab noch keinen Nachteil
festgestellt.
Undja das ist nicht ideal aber fuer ne led find ich eine ISR
uebertrieben ;)
@Thomas Holmes:
Sicherlich ist es meist auch ausreichend mit einem Kondensator sowie
Widerstand an dem Taster. Habe das auch bereits ein paar mal zu
testzwecken gemacht. Geht an sich auch immer ganz gut. Es sind aber
somit auch 2 Bauteile mehr. Im Tutorial wird darauf hingewiesen, dass es
kaum noch einen Sinn macht, da die Software das auch auswerten kann. Das
soll keine Diskussion über den Sinn nun geben ;)
@michi:
Solche Sachen mit den delays versuche ich wenn möglich immer zu
vermeiden, auch wenn das hier natürlich kaum ins Gewicht fällt.
Ich habe einen ähnlichen Code vor ein paar Wochen geschrieben. (Der
Atmega328P 16MHz diente lediglich zum kurzen Testen). Das ganze wurde
mit einem Attiny85 betrieben. Der Code gibt nicht alles wieder. Die
ganzen anderen Bibiotheken werden über die main.h einbezogen.
Ich habe vom Prellen nichts mitbekommen bei dieser Methode. Ich habe
hier bereits einen Timer im Einsatz für die Zeit-funktion. In der habe
ich ich Millisekunden, Sekunden, Minuten und Stunden, die über einem
Interupt-Overflow gezählt werden. Basierend auf dem millis Zähler werden
auch diverse Frequenzen zur Verfügung gestellt. U.a. 50Hz. Ich habe hier
keinerlei Probleme mit dem Entprellen feststellen können. Nichts wurde
doppelt gezählt.
Gäbe es ansonsten Anregungen, wie ich ggf. falsche Rückgabewerte
vermeiden kann in diesem Beispiel? Für die fertige Version plane ich mit
http://www.mikrocontroller.net/wikifiles/f/f8/RC_debouncer.png Die
Schmitt-Trigger ICs stehen jedoch derzeit erst einmal nur auf der
Möchte-Haben-Liste und sind noch nicht bestellt.
1
/*
2
ATtiny85_Equinox.c
3
Created: 31.07.2014 16:16:07
4
Author: sschultewolter
5
6
(PCINT5/!RESET/ADC0/dW) PB5 1 | AT | 8 VCC
7
(PCINT3/XTAL1/CLKI/!OC1B/ADC3) PB3 2 | TI | 7 PB2 (SCK/USCK/SCL/ADC/T0/INT0/PCINT2)
8
(PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 3 | NY | 6 PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1)
Stefan S. schrieb:> icherlich ist es meist auch ausreichend mit einem Kondensator sowie> Widerstand an dem Taster. Habe das auch bereits ein paar mal zu> testzwecken gemacht. Geht an sich auch immer ganz gut. Es sind aber> somit auch 2 Bauteile mehr. Im Tutorial wird darauf hingewiesen, dass es> kaum noch einen Sinn macht, da die Software das auch auswerten kann. Das> soll keine Diskussion über den Sinn nun geben ;)
Hallo, nein diskutieren will ich auch nicht. Schließlich ist weder das
was im Tutorial steht, noch meine persönliche Meinung ein Gesetz. Jeder
hat so seine Strategie. Meine ist es immer den geringsten
dimensionierten Controller einzusetzen (größte Kosten) und der
Performance des Codes die höchste Priorität einzuräumen. Timer und ISR's
halte ich für Aufgaben frei die anders nicht zu lösen sind. Auch wenn
der Algorithmus von Herrn Dannegger programmiertechnisch exzellent ist,
so geht SW Entprellen, auch wesentlich weniger codeintensiv und auch
ohne Timer.
Was aber gar nicht in meinen Kopf hinein will, ist dass Du auf der einen
Seite ein Kondensator und einen Wiederstand als zuviel zusätzliche
Hardware ansiehst aber dann planst einen völlig Überflüssigen
Schmitt-Trigger (AVR µC haben einen Schmitt-Trigger intern an den
Eingängen) nebst drei weiteren passiven Bauelementen zu Planen.
Du führst ja deine eigenen Argumente ad absurdum.
Stefan S. schrieb:> if( get_key_short( 1<<KEY0 ))> LED_PORT ^= 1<<LED0;>> if( get_key_long( 1<<KEY1 ))
get_key_short() und get_key_long() müssen immer je Taste aufgerufen
werden.
Wenn man die Drückdauer unterscheidet, macht man das ja, um auch beide
Ereignisse zu benutzen.
Die HW-Entprell-Päbste können das natürlich nicht erkennen und müssen
ihren falschen Senf dazugeben.
Bastler schrieb:> @michi: wo wird da entprellt?>>> Warum probierst du nicht einfach _delay_ms(50);>>>> if(taste high)>>{_delay_ms(x);>> led_ein;>>}
Es funktioniert, weil das Prellen innerhalb von 50ms meistens
abgeklungen ist. Das Programm macht in dem Zeitraum nichts und bekommt
das Prellen nicht mit.
Peter Dannegger schrieb:> Stefan S. schrieb:>> if( get_key_short( 1<<KEY0 ))>> LED_PORT ^= 1<<LED0;>>>> if( get_key_long( 1<<KEY1 ))>> get_key_short() und get_key_long() müssen immer je Taste aufgerufen> werden.> Wenn man die Drückdauer unterscheidet, macht man das ja, um auch beide> Ereignisse zu benutzen.> Die HW-Entprell-Päbste können das natürlich nicht erkennen und müssen> ihren falschen Senf dazugeben.
Richtig, aber dann müsste auch folgendes funktionieren
1
while(1)
2
{
3
if( get_key_short( 1<<KEY0 ))
4
LED_PORT ^= 1<<LED0;
5
}
Ich werde aber gleich mal versuchen es mit UART zu debuggen. Ob es
verschwendung ist, einen Timer zu nehmen, oder nicht, hängt immer von
der verwendeten Hardware ab. Ich brauche für das Projekt eine gewissen
Menge an Flash des Attinys. 4KB wird hier für den Flash sehr sehr knapp.
Daraufhin habe ich mich für einen Attiny85 entschieden (eigentlich
sollte es ein AT841 werden, jedoch macht mir Farnell einen Strich durch
die Rechnung).
Ich brauche keine große Anzahl an Timern. Lediglich diesen zum
Entprellen, sowie den für die Zeit selber. Diesen könnte man sogar
notfalls kombinieren da die doch ähnlich aufgebaut sind.
>@michi: wo wird da entprellt?>> Warum probierst du nicht einfach _delay_ms(50);>>>> if(taste high)>>{_delay_ms(x);>> led_ein;>>}> Es funktioniert ....
Entprellen bedeutet aber nicht beim ersten Muckser am Pin 50ms zu
warten, sondern sicherzustellen, daß dies der Beginn eines "Gedrückt"
war. Es fehlt da die erneute/wiederholt Abfrage des Eingangs. Einfach
mal Dr. Google nach "Prellen Schalter" fragen, um zu erfahren was das
identisch ist oder einfach hier den passenden Grundlagenartikel lesen.
Bastler schrieb:> Entprellen bedeutet aber nicht beim ersten Muckser am Pin 50ms zu> warten, sondern sicherzustellen, daß dies der Beginn eines "Gedrückt"> war.
Kann man machen, muss man aber nicht.
Wenn man's nicht braucht und keine größeren Störungen hat o. befürchten
muss, kann man das getrost auch weglassen.
Teo Derix schrieb:> Bastler schrieb:>> Entprellen bedeutet aber nicht beim ersten Muckser am Pin 50ms zu>> warten, sondern sicherzustellen, daß dies der Beginn eines "Gedrückt">> war.>> Kann man machen, muss man aber nicht.> Wenn man's nicht braucht und keine größeren Störungen hat o. befürchten> muss, kann man das getrost auch weglassen.
Dann wurde aber im restlichen Code meist schon unnötig viele delays
genutzt.
Nicht prellende Taster im Low-Budget Bereich sind mir nicht bekannt.
Peter Dannegger schrieb:> Die HW-Entprell-Päbste können das natürlich nicht erkennen und müssen> ihren falschen Senf dazugeben.
Selbstverständlich kann man auch noch von HW entprellten
Eingangssignalen die Signalzeit bestimmen...Es gibt keinen falschen
Senf, nur anderen...
Wäre schön, wenn wir zum eigentlichen Thema noch einmal zurückkommen
könnten.
Habe mir in der Zwischenzeit den Schaltung auf eine kleine
Streifenrasterplatine aufgebaut, da die Taster nicht immer optimal im
Steckbrett halten.
1
5V
2
.-----------------------o---------o
3
| |
4
.-. .-.
5
4k7| | PINB0 PINB1 | |4k7
6
| | o o | |
7
'-' | | '-'
8
PIND2 | | | | PIND3
9
o--------o | | o---------o
10
| | | |
11
| | | |
12
T | | | | T
13
--- | | | | ---
14
.-o o-' | | '-o o--.
15
| | | |
16
| ___ LED| | LED ___ |
17
o-|___|----|<-' '->|-----|___|--o
18
| 680 680 |
19
| |GND
20
'------------------------------------o--o
21
(created by AACircuit v1.28.6 beta 04/19/05 www.tech-chat.de)
TIP:
Wen Du schon solche Schwierigkeiten mit fremd Code hast, dann
programmiere es halt selbst.
Der Lerneffekt ist unübertrefflich, wenn man was selber macht :)
du hast nirgends geschrieben, welchen Controller du benutzt (aber
irgendwas von Arduino, also vermute ich Atmega328).
Ich habe das gerade kurz getestet auf einem Mega88 - die Timer-ISR wird
garnicht aufgerufen. (einfach festzustellen mittels LED in der ISR
anschalten).
Der Blick ins Datenblatt verrät auch sofort warum:
Der Prescaler wird beim Mega88 / 328 nicht in TCCR0A eingestellt,
sondern in TCCR0B.
Dein Timer läuft also nicht.
nächstes Problem: du fragst "get_key_long(1<<KEY0)" ab. Um lange
Tastendrücke feststellen zu können, muss KEY0 in der REPEAT_MASK
eingetragen werden.
Nach diesen beiden Änderungen funktioniert der Code einwandfrei:
Ja, das sehe ich auch so. Für Anfänger ist es einfacher und lehrreicher,
keinen fremden Code einzusetzen.
Fremden Code zu analysieren (wenn er mal nicht wie erwartet
funktioniert) ist erheblich schwieriger und eher etwas für
Fortgeschrittene.
Nachtrag:
auf neueren AVRs (wie z.B. Mega88 / 328) kann man direkt Ausgangspins
togglen, indem man ins PINx-Register schreibt. Das hat den Vorteil, dass
es zum einen schneller geht und weniger Code erzeugt, zum anderen ist es
aber auch atomar! D.h. es gibt keine Probleme, auch wenn du in
Interrupts auf den gleichen Port schreibst.
Das sieht dann so aus:
Einen eigenen Code habe ich bereits geschrieben, irgendwo oben, der auch
soweit funktionierte.
Das es sich um einen Atmega328P handelt, bzw. Pro Mini, habe ich oben
bereits geschrieben bzw. es im Code hinterlegt.
Nun geht es soweit, der einzige Fehler, den ich mehr oder weniger
gemacht habe ist, dass ich hätte das B-Register wählen müssen anstatt
des A-Registers.
Werde es nun wieder auf den Attiny85 portieren.
> Fremden Code zu analysieren (wenn er mal nicht wie erwartet> funktioniert) ist erheblich schwieriger und eher etwas für> Fortgeschrittene.
Aber man kann eben auch was dabei lernen ;-)
Fehler gezielt zu suchen (und dann auch zu beheben), ist das
Eigentliche, was man können muß. Und da hilft nur Training!