Hallo!
Ich besitze ein RN-Control 1.4 Board mit Atmega32.
Dort sind 5 Tasten über einen Spg.-Teiler am ADC angeschlossen. (siehe
Schaltplan). Ich habe zusätzlich den Pin PA7 mit 100k gegen GND gezogen,
damit der ADC nicht in der Luft hängt.
Als Anfänger schlage ich mich gerade herum, diese Tasten anständig
auszulesen. Es gibt zwar ein Demoprogramm in C, aber dieses beinhaltet
nichts brauchbares dazu.
Ich weiß, daß es eine Komfort-Routine und das Bsp. mit der
Matrixtastatur am ADC von Peter Dannegger dazu gibt, aber leider ist mir
das als Anfänger etwas zu hoch....
Meine Idee:
Da ich sowieso zur Erzeugung eines Sekundentaktes (Programm von Peter
Dannegger) eine ISR habe die alle 4msec abläuft, benutze ich gleich
diese, um alle 8msec eine ADC-Wandlung zu starten. Wird 2mal
hintereinander die gleiche Taste detektiert, so wird was gemacht,
ansonsten nichts.
Der Vergleich in MAIN:
1
if(button_read_puls==2)// 8msec vergangen
2
button1=read_button();// Tasten auslesen
3
4
if(button_read_puls==4)// weitere 8msec vergangen
5
button2=read_button();// Tasten auslesen
6
7
8
9
10
if(button1==button2)// Nach 8msec noch selbe Taste?
11
{
12
switch(button2)// Handlung zuweisen
Die Funktion read_button:
1
uint8_tread_button(void)
2
{
3
4
uint8_tbutton=0;
5
6
adc_value_button=adc_read_avg(7,4);
7
//ADC-Wert für Tasten auslesen, Channel 7 / 4 Messungen
8
9
// Wertebereich für AREF = 2,13V !!
10
11
if((adc_value_button>=0)&&(adc_value_button<=10))button=0;// keine Taste gedrückt
Korrektur:
Aref passt natürlich, aber die Werte sind soweit ich das auf die
schnelle gerechnet hab nicht ganz korrekt.
Du musst den 100k gegen Masse in den Spannungsteiler auch einrechnen.
Die Werte passen. Sowohl rechnerisch, als auch angezeigt per LCD.
Rechnung:
Versorgungsspannung der Tasten gemessen: 4,93V
Referenzspannung am ADC gemessen: 2,13V
ADC-Wert = (R_taster / R_ges) * (U_ges / AREF) * 1024
zu beachten ist, daß es sich jeweils um eine Parallelschaltung von (1
bis 5k) und 100k handelt.
So ergebne sich für die einzelnen Tasten folgende Widerstanswerte:
Taster1: 4,76k
Taster2: 3,846k
Taster3: 2,913k
Taster4: 1,961k
Taster1: 990 Ohm
Somit ergeben sich folgende ADC-Werte:
Taster1: berechnet 156 // real 154
Taster2: berechnet 310 // real 307
Taster3: berechnet 460 // real 459
Taster4: berechnet 608 // real 609
Taster1: berechnet 752 // real 760
Gruß Rick
Ok, ok :)
Oben steht 5V (und nicht 4,xx) und damit fallen die Werte rechnerisch
nun mal aus deinem jeweiligen Wertebereich.
Aber wenn du die Werte auch per Messung kontrolliert hast ist ja sowieso
alles in Ordnung.
Dann kontrollier' die Werte doch einfach mal an verschiedenen Stellen um
herauzufinden wo es hakt.
Bekommst du denn die richtige Tastennummer zurückgegeben wenn du die
Funktion read_butten in der main einfach mal aufrufst?
(Mal von Hand per wait-Befehl alle paar ms aufrufen und den Rückgabewert
auf dem LCD ausgeben).
Die Variable "button_read_puls" wird in der Timer-ISR hochgezählt, ja?
Ist die auch als "volatile" deklariert?
Entschuldige, war mein Fehler, da ich die reale Spannung am
Spannungteiler nicht angegeben habe.
Die realen Werte hab ich per LCD ermittelt, wenn ich die Tasten schön
lange gedrückt halte.
Aber ich glaube durch die Tastenprellung bekomme ich bei der Mittelung
der ADC-Werte nur Mist raus. Da müsste ich warscheinlich jeweils den
größten und kleinsten Ausreisser wegschmeissen?
Hier die Fkt. adc_read_avg:
also ganz langsam:
angenommen bei R3-GND liegen 4,93 V an.....
somit ergibt sich für mich:
R4: 1,643V
R5: 1,314V
R6: 0,986V
R7: 0,657V
R8: 0,328V
d.h: Bei AREF: 2,13V
-->1V = 480,75
Berechnung:
R4: 1,643*480,75= 789,87 (790)
R5: 631,705 (632)
R6: 474,01 (474)
R7: 315,85 (316)
R8: 157,68 (158)
lg
Nein, am Schaltplan nicht, daß hab ich dazugeschieben und auch anhand
meines Rechenbeispieles nochmal gezeigt.
hier
Rick M. schrieb:> Ich besitze ein RN-Control 1.4 Board mit Atmega32.> Dort sind 5 Tasten über einen Spg.-Teiler am ADC angeschlossen. (siehe> Schaltplan). Ich habe zusätzlich den Pin PA7 mit 100k gegen GND gezogen,> damit der ADC nicht in der Luft hängt.
und hier
Rick M. schrieb:> zu beachten ist, daß es sich jeweils um eine Parallelschaltung von (1> bis 5k) und 100k handelt.> So ergebne sich für die einzelnen Tasten folgende Widerstanswerte:>> Taster1: 4,76k>> Taster2: 3,846k>> Taster3: 2,913k>> Taster4: 1,961k>> Taster1: 990 Ohm
Ich habe jetzt herausgefunden, daß die Fkt. "read_button" nur die
richtige Tastennummer zurückgibt, wenn man die Taste länger gedrückt
hält.
Ansonsten wird keine Taste erkannt.
Ich rufe die Funktion "read_butten" alle 10msec (_delay_ms(10)) auf und
werte den Rückgabewert per switch-Fkt. aus.
Anscheinend messe ich durch die Prellerei nur blödsinn??
Gruß Rick
Rick M. schrieb:> Aber ich glaube durch die Tastenprellung bekomme ich bei der Mittelung> der ADC-Werte nur Mist raus. Da müsste ich warscheinlich jeweils den> größten und kleinsten Ausreisser wegschmeissen?
Ich mittle da überhaupt nix. Ich lese in regelmäßigen Intervallen den
ADC ein, extrahiere anhand einer LUT die Tasten-Nummer und entprelle die
Taste, indem ich die Tastennummer mit der Nummer der letzten Abfrage
vergleiche. Bei Gleichheit wird der Prellzähler erhöht (und auf einen
Max-Wert begrenzt), bei Ungleichheit wird der Prellzähler ausgewertet
und danach gelöscht.
War der Prellzähler über der Lang/kurz-Schwelle, dann ist es ein langer
Tastendruck, war er unter der Prellschwelle, dann war der Tastendruck
ungültig. War der Prellzähler zwischen Prellschwelle und
Lang/kurz-Schwelle, dann war es ein kurzer Tastendruck.
War der Tastendruck gültig und der Tastenwert nicht 0 (0 = keine Taste
gedrückt), so wird dem Hauptprogramm die Tasten-Nummer übergeben
(globale Variable). Das Hauptprogramm verzweigt nun anhand der
Tastennummer zur gewünschten Aktion und diese löscht dabei die
Tastennummer.
Das funktioniert bei mir in verschiedenen Varianten (Timer-Interrupt,
ADC-Interrupt) mit bis zu 16 Tasten (mehr müsste auch gehen, habe ich
aber noch nicht probiert) ohne Probleme. Allerdings in ASM.
...
Hannes Lux schrieb:> Ich lese in regelmäßigen Intervallen den> ADC ein, extrahiere anhand einer LUT die Tasten-Nummer und entprelle die> Taste, indem ich die Tastennummer mit der Nummer der letzten Abfrage> vergleiche.
LUT?
Hannes Lux schrieb:> bei Ungleichheit wird der Prellzähler ausgewertet> und danach gelöscht.
Wieso bei Ungleichheit auswerten? Dann war doch die Erkennung ungültig,
oder?
Rick M. schrieb:> Versorgungsspannung der Tasten gemessen: 4,93V> Referenzspannung am ADC gemessen: 2,13V
Für die Tastenerkennung wäre es wesentlich sicherer, eine ratiometrische
Meßmethode zu verwenden, d.h. sowohl für den Spannungsteiler als auch
für den ADC die selbe Bezugsspannung zu verwenden, z.B. AVCC.
Mit dem Teiler an VCC und der internen Referenz für den ADC gibt es
immer eine üble Eierei der Entscheidungsschwellen (besonders bei den
oberen Tasten), sobald VCC schwankt.
Gruß
Matthias
Auch ohne Mittelung bekomme ich erst nachdem ich die Taste länger
gedrückt halte, die richtige Tastennummer zurück.
Das Prellen kann doch keine Sekunde dauern?
Matthias schrieb:> Rick M. schrieb:>> Versorgungsspannung der Tasten gemessen: 4,93V>> Referenzspannung am ADC gemessen: 2,13V>> Für die Tastenerkennung wäre es wesentlich sicherer, eine ratiometrische> Meßmethode zu verwenden, d.h. sowohl für den Spannungsteiler als auch> für den ADC die selbe Bezugsspannung zu verwenden, z.B. AVCC.> Mit dem Teiler an VCC und der internen Referenz für den ADC gibt es> immer eine üble Eierei der Entscheidungsschwellen (besonders bei den> oberen Tasten), sobald VCC schwankt.> Gruß> Matthias
Leider muß ich auch noch Spannung und Strom am ADC messen und sehe dafür
eine Referenzspannung von 2,56V per LM336-2,5 vor.
Leider ist auf dem Board auch der AD-Wandler nicht von der
Versorgungsspannung entkoppelt.
Rick M. schrieb:> Hannes Lux schrieb:>> Ich lese in regelmäßigen Intervallen den>> ADC ein, extrahiere anhand einer LUT die Tasten-Nummer und entprelle die>> Taste, indem ich die Tastennummer mit der Nummer der letzten Abfrage>> vergleiche.>> LUT?
Lookuptable
>>> Hannes Lux schrieb:>> bei Ungleichheit wird der Prellzähler ausgewertet>> und danach gelöscht.>> Wieso bei Ungleichheit auswerten?
Weil erst dann der Tastendruck zu Ende ist.
> Dann war doch die Erkennung ungültig,> oder?
Die war ungültig, wenn der Prellzähler die Prellschwelle nicht
überschreiten konnte.
Jede Änderung an der Tastatur (drücken, loslassen) ergibt eine Änderung
des zyklisch eingelesenen ADC-Wertes. Da dieser etwas streuen kann, wird
daraus erstmal die unter Einhaltung der Toleranzen Tasten-Nummer
ermittelt. Nummer 0 entspricht unbetätigte Tastatur, die anderen Nummern
entsprechen den Tasten.
Solange immer dieselbe Tasten-Nummer ermittelt wird, ist der Zustand der
Tastatur unverändert (also unbetätigt oder eine Taste betätigt).
Betätigt man eine Taste, endet erstmal der "Tastendruck 0", der dem
Hauptprogramm nicht übergeben wird.
Nun zählt der Prellzähler, wie lange der neue Zustand anhält, also wie
oft die neue Taste aus dem ADC-Wert ermittelt wird. Natürlich könnte man
bei Erreichen der Prellschwelle sofort den Tastenwert an das
Hauptprogramm übergeben, aber dann wird die Aktion ja bereits ausgelöst,
ehe man weiß, ob es nicht doch noch ein langer Tastendruck (mit anderer
Funktion) werden könnte. Also wertet man den (vor Überlauf geschützen)
Prellzähler erst aus, wenn die Taste wieder losgelassen wurde. Und das
ist nunmal die Ungleichheit (alt war Nummer der gedrückten Taste, neu
ist 0, also unbetätigt). Natürlich muss man "alt" noch temporär sichern,
um es dem Hauptprogramm übergeben zu können, falls der Tastendruck
gültig war.
Gültig war der Tastendruck, wenn der gesicherte Alt-Wert nicht 0 war und
der Prellzähler die Prellschwelle überschritten hat. Doch vor dem
Übergeben des Tastenwertes an das Hauptprogramm prüft man noch den
Prellzähler auf Überschreiten der zweiten Schwelle, die den "langen
Tastendruck" definiert. Ist diese überschritten, wird ein oberes Bit in
der Tastennummer gesetzt, an dem das Hauptprogramm erkennt, dass es sich
um einen langen Tastendruck handelt, der anders behandelt werden muss.
Das alles erfolgt in einer ISR, entweder im ADC-Interrupt, oder nebenbei
im Timer-Interrupt, der noch andere Dinge zu erledigen hat. Das kostet
also nur minimale Rechenzeit und läuft quasi im Hintergrund ab.
Das Hauptprogramm (oder eine Funktion davon) fragt dann (bei
Gelegenheit) die übergebene Tasten-Nummer ab, reagiert darauf und löscht
(entwertet) sie. Die übergebene Tasten-Nummer ist also eine Art
Jobauftrag, der nach der Abarbeitung entwertet wird.
Das alles ist sehr ressourcenschonend, denn es verwendet keine
rechenzeitvernichtenden Warteschleifen.
...
Matthias schrieb:> d.h. sowohl für den Spannungsteiler als auch> für den ADC die selbe Bezugsspannung zu verwenden, z.B. AVCC.
Das sollte eine Selbstverständlichkeit sein.
Rick M. schrieb:> Leider muß ich auch noch Spannung und Strom am ADC messen und sehe dafür> eine Referenzspannung von 2,56V per LM336-2,5 vor.
Dann solltest Du den Tasten-Spannungsteiler auch an die Referenz
anschließen.
Bei Verwenden der internen Referenz kann man auch die Referenz von
Messung zu Messung umschalten.
Sind mehrere ADC-Eingänge zu messen, so bietet sich auch der
ADC-Interrupt an. Dann wird eben mit einem "Mess-Stellen-Zähler"
gearbeitet, der als Index auf ein Array mit ADMUX-Werten, ein Array mit
Ergebnissen und als "Zeitscheibe" fungiert, anhand der die ISR bei
Tastenabfrage in die richtige Routine verzweigt. Läuft auch im
Hintergrund und frisst keine unnötige Rechenzeit.
...
Rick M. schrieb:> Auch ohne Mittelung bekomme ich erst nachdem ich die Taste länger> gedrückt halte, die richtige Tastennummer zurück.
Dann machst Du mit dem ADC etwas Anderes falsch...
> Das Prellen kann doch keine Sekunde dauern?
Nein.
...
Hannes Lux schrieb:> Dann machst Du mit dem ADC etwas Anderes falsch...
Im Prinzip halte ich mich beim Auslesevorgang an das Tutorial "AVR-GCC":
XX Kanal wählen
XX Eine Wandlung anstoßen (sigle shot)
XX Warten bis Wandlung abgeschlossen
XX Ergebnis auslesen und verwerfen
XX Neue Wandlung und Ergebnis verwerten
Mein Code:
1
uint8_tread_button(void)
2
{
3
4
uint8_tbutton=0;
5
6
7
8
ADMUX=((ADMUX&~(0x1F))|(7&0x1F));
9
// Kanal 7 wählen, ohne andere Bits zu verändern
10
11
ADCSRA|=(1<<ADSC);// ADSC=1 Wandlung starten
12
13
while(ADCSRA&(1<<ADSC)){}
14
//Solange ADSC = 1 ist, ist die Wandlung noch nicht abgeschlossen
15
16
17
adc_value_button=ADCW;
18
19
adc_value_button=0;// Ergebnis verwerfen
20
21
ADCSRA|=(1<<ADSC);// ADSC=1 Wandlung starten
22
23
while(ADCSRA&(1<<ADSC)){}
24
//Solange ADSC = 1 ist, ist die Wandlung noch nicht abgeschlossen
Wenn keine Taste gedrückt wird, ergibt das momentan immer einen
Fehlercode.
Damit wird mir der ADC-Wert im Display angezeigt.
Normalerweise hab ich noch ein Fenster für "keine Taste gedrückt", was
den Wert 0 zurückgibt.
Ich kann hier keinen Fehler erkennen.
Hannes Lux schrieb:> Dann solltest Du den Tasten-Spannungsteiler auch an die Referenz> anschließen.
Was ja momentan der Fall ist.
In der Praxis erzeugt mir das aber dann Spannungsschwankungen in der
Referenzspannung, was zu Messungenauigkeiten führt.
Hannes Lux schrieb:> Sind mehrere ADC-Eingänge zu messen, so bietet sich auch der> ADC-Interrupt an. Dann wird eben mit einem "Mess-Stellen-Zähler"> gearbeitet, der als Index auf ein Array mit ADMUX-Werten, ein Array mit> Ergebnissen und als "Zeitscheibe" fungiert, anhand der die ISR bei> Tastenabfrage in die richtige Routine verzweigt. Läuft auch im> Hintergrund und frisst keine unnötige Rechenzeit.
Hatte ich schon erwähnt, daß ich Anfänger bin ;-)
Du mußt debuggen, also die Aufgaben unterteilen und einzeln testen.
Gib doch erstmal die ADC-Ergebnisse auf LCD oder UART aus und schau sie
Dir an.
Peter
Mache ich bereits, leider liefert meine Fkt. read_button nur die
gedrückte Taste zurück, wenn ich sie lange gedrückt halte und ich weiß
einfach nicht, was ich beim lesen des ADC und der Tasenzuweisung falsch
mache.
Hier nochmal meine Fkt. als Anhang.
Gruß Rick
Rick M. schrieb:> Im Prinzip halte ich mich beim Auslesevorgang an das Tutorial "AVR-GCC":>> XX Kanal wählen>> XX Eine Wandlung anstoßen (sigle shot)>> XX Warten bis Wandlung abgeschlossen>> XX Ergebnis auslesen und verwerfen>> XX Neue Wandlung und Ergebnis verwerten
Diese Vorgehensweise ist akzeptabel, wenn man den ADC mal testen will
oder erklären/demonstrieren will, wie der ADC funktioniert. Ernsthaft zu
Gebrauchen ist dies aber nicht, da es blockierend arbeitet. Denn der ADC
braucht Zeit zum Wandeln, wer ihm den Kanal mitteilt und dann auf das
Ergebnis "wartet", der vertrödelt unnötig Rechenzeit. Ich mach' das
deshalb anders:
XX Ergebnis auslesen und über den Index in ein Array werfen
XX Index erhöhen und auf Anzahl der Mess-Eingänge begrenzen
XX Bitmuster für ADMUX für die nächste Messung aus einem anderen Array
holen und in ADMUX schreiben
XX ADC starten
Das alles erfolgt in einem Interrupt. Entweder nebenher in einem
Timer-Interrupt, der z.B. die genaue Millisekunde als Basis für eine Uhr
bereitstellt, oder eben im Interrupt des ADC. Somit gibt es nirgendwo
die Notwendigkeit, auf das Fertigwerden des ADC zu warten. Wenn der
nächste Interrupt fällig wird, ist der ADC mit Sicherheit fertig. Und in
der Zwischenzeit kann das Programm andere Dinge erledigen.
>> Mein Code:
Ich kann kein C.
Rick M. schrieb:> Hatte ich schon erwähnt, daß ich Anfänger bin ;-)
Waren wir alle mal. Betreffs C bin ich sogar weniger als ein Anfänger,
nämlich ein Ignorant. Aber meine Basteleien sind meist so klein und
überschaubar, dass ich sie in ASM erschlagen kann und ohne C auskomme.
Andererseits hat auch ein Anfänger das Recht, Fortschritte zu machen und
ungünstige Algorithmen zu meiden.
Rick M. schrieb:> Hannes Lux schrieb:>> Dann machst Du mit dem ADC etwas Anderes falsch...
Damit meinte ich z.B. auch das Einhalten der Vorgaben betreffs ADC-Takt
(50..200 kHz) sowie sinnvolle Hardware-Beschaltung.
Dein Spannungsteiler hat einen ständigen Querstrom. Ich mach' das
anders:
Die Widerstandskette geht von GND zum ADC-Eingang. Die Taster schalten
zum Widerstand, der nach + führt. Somit liegt bei unbetätigten Tastern
der ADC über die Widerstände an GND. Wird ein Taster betätigt, dann
bildet sich ein Spannungsteiler aus der Anzahl der unteren Widerstände
(von GND bis zum Taster) und dem Widerstand nach Plus. Die restlichen
Widerstände der Kette liegen zwischen Taster und ADC und sind im
Verhältnis zum Eingangswiderstand des ADC sehr niederohmig, verfälschen
also das Ergebnis nicht.
Damit belastest Du AREF nur solange eine Taste betätigt ist.
...
Hi
>Mache ich bereits, leider liefert meine Fkt. read_button nur die>gedrückte Taste zurück, wenn ich sie lange gedrückt halte und ich weiß>einfach nicht, was ich beim lesen des ADC und der Tasenzuweisung falsch>mache.
Wieso versteifst du dich darauf, das das an dieser Funktion liegt?
Du wartest z.B. nach 99 im Hauptprogramm eine Sekunde. Vielleicht stimmt
auch dein angenommener Controllertakt nicht.
MfG Spess
Das was Du hier schilderst fällt bei mir unter Programmoptimierung.
Daß ich Zeit vertrödle, indem ich auf das Wandlungsende warte, ist mir
klar, hindert die Funktion aber nicht daran korrekt zu arbeiten.
Jedenfalls soweit mein derzeitiges Wissen reicht.
Daß ich den Spannungsteiler selber nicht so machen würde, ist mir auch
klar, aber wie ich ganz am Anfang schon beschrieben habe, habe ich ein
fertig aufgebautes Testboard (RN-Control 1.4) und das hat nunmal eben
dieses layout.
Deswegen hau ich das Board jetzt nicht in die Tonne.
Das dieses Enwicklungsboard nicht gerade der Hammer ist, wird mir jetzt
auch immer mehr klar.
Das Board hat einen 16MHz Quarz, daher muß ich den Prescaler auf 128
setzen.
Der ADC läuft also mit einer Frequenz von 125kHz.
Gruß Rick
Hi
>Das Board hat einen 16MHz Quarz, daher muß ich den Prescaler auf 128>setzen.
Bist du 100%-ig sicher, das der Controller auch mit dem Quarz läuft?
MfG Spess
spess53 schrieb:> Wieso versteifst du dich darauf, das das an dieser Funktion liegt?>> Du wartest z.B. nach 99 im Hauptprogramm eine Sekunde.
Danke für den Tipp. Das habe ich total übersehen und war ein Denkfehler.
Das kann natürlich nicht funktionieren.
Hi
>Ja, das Board wurde mit dem Quarz ausgeliefert und der ATmega32 geht bis>16MHz.
Hast du auch die Fuses auf den Quarz eingestellt. Ein fabrikneuer AVR
läuft mit 1MHz. Auch wenn ein 16MHz-Quarz angeschlossen ist.
MfG Spess
spess53 schrieb:> Hast du auch die Fuses auf den Quarz eingestellt. Ein fabrikneuer AVR> läuft mit 1MHz. Auch wenn ein 16MHz-Quarz angeschlossen ist.
Aua, jetzt wird vermutlich wieder ein AVR verfust, bevor das erste
Programm so richtig drauf gelaufen ist...
...
Hi!
Die Fuses waren schon voreingestellt.
Ich toggle eine LED per Timer1-ISR im Sekundentakt.
Wenn mein MC nur mit 1MHz laufen würde, wäre der Takt 16sec lang und
nicht 1sec.
Gruß Rick
so etwas habe ich auch schon mal gemacht
wichtig ist nicht eine einzelne messung auszuwerten sonder mindestens 3
auffeinanderfolgende messungen sollten innerhalb eines fensters liegen
bevor die eingabe als gültig gilt.
ich suche das mal raus hatte eine ganze handytastatur drann und hat
zuverlässig funktioniert
Die Tasten werden jetzt korrekt am LCD ausgegeben.
Ich habe jeder Tase eine LED zugeteilt, daran merke ich, da ich die LEDs
bei jedem Tastendruck toggle, daß der Ausgang pro Tastendruck mehrfach
ein und ausgeschaltet wird.
Bei den Tasten 3-5 funktioniert nichtmal das?
Auch kann es vorkommen, wenn eine Taste gedrückt wird, daß die LED7,
welche im Sekundentakt blikt, nicht mehr vollkommen ausgeht, obwohl ich
den Ausgang nirgedswo anders schalte?
Kann es sein, daß mir die ISR von Timer1 den Code unbrauchbar macht.
Die Interrupts muß man doch nur temporär deaktivieren, wenn z.B in der
ISR Register verändert werden, die auch im Hauptprogramm verändert
werden, oder Variablen die größer 1Byte sind?
Gruß Rick
PC2 bis PC5 funktioniert nicht als Ausgang. Da dies die
JTAG-Schnittstelle ist, hab ich probeweise, das JTAG-Fuse mal mit Pony
Prog gesetzt. Keine Änderung??
Die Pins sind immer auf 3,74V ??
Danke für den Code.
Is mir aber n bisserl zu hoch. Was machst Du da in der Tabelle?
Zur Funktion meiner Auswertung
Die Matrix ist so aufgebaut, dass der Widerstandswert aus der Summe der
Spalten- und Zeilenwiderständen gebildet wird.
Die Summe der widerstände in einer Reihe muss kleiner sein als die
Differenz zwischen 2 Spalten.
das einer Messung startet die nächste Messung
im 1.Schritt wird gewartet bis eine minimale Spannung anliegt
im 2.Schritt wird gewartet bis eine schwelle unterschritten ist welche
deutlich über einem gültigen Tastenwert liegt andernfalls werden alle
Zwischenspeicher neu initialisiert.
Jetzt wird gesiebt (Schwellwertkette) bis der Wert der Taste ermittelt
ist.
Erst vier gleich Messungen werden gültig erkannt und ausgegeben.
Dann werden alle Zwischenspeicher reinitialisiert und die nächste
messung ausgelöst.
eine sichere Messung war so in etwa 0,2 sec möglich für eine Tastatur
ein angemessener Wert
Nnachteil gleichzeitige Tastdrücke werden nicht erkannt
Rick M. schrieb:> PC2 bis PC5 funktioniert nicht als Ausgang. Da dies die> JTAG-Schnittstelle ist, hab ich probeweise, das JTAG-Fuse mal mit Pony> Prog gesetzt. Keine Änderung??> Die Pins sind immer auf 3,74V ??>
die fuse musst du nicht ändern aber wärend des init in MCUCR das
jtagenablebit 2 mal binnen vier Takten disabeln.
> Danke für den Code.> Is mir aber n bisserl zu hoch. Was machst Du da in der Tabelle?
Winfried J. schrieb:> die fuse musst du nicht ändern aber wärend des init in MCUCR das> jtagenablebit 2 mal binnen vier Takten disabeln.
Im Datenblatt steht folgendes:
When the JTAG-Fuse is unprogrammed, these four TAP pins are normal port
pins.
unprogrammed ist 1, in Pony Prog also kein Häkchen. Trotzdem
funktionieren bei mir die 4 Pins nicht.
Weiters steht im Datenblatt zum MCUCSR-Register:
JTD-Bit: If this bit is one the JTAG interface is disabled. (write twice
within four cycles)
Hannes Lux schrieb:> XX Ergebnis auslesen und über den Index in ein Array werfen>> XX Index erhöhen und auf Anzahl der Mess-Eingänge begrenzen>> XX Bitmuster für ADMUX für die nächste Messung aus einem anderen Array> holen und in ADMUX schreiben>> XX ADC starten
Wenn ich das richtig verstanden habe:
Angenommen wir haben 3 Messeingänge für Spannung/Strom + 1 Eingang für
Tasten.
Das würde jetzt ein 16bit-Array mit 4 Stellen ergeben.
Ich nenns jetzt mal uint16_t adc_ergebnis[4];
und noch mal eins für die Adressen
uint8_t adc_adresse[] = {0 , 1 , 2 , 3 };
Das ginge glaub ich auch ohne Array
Wenn ich das in die ADC-ISR packen möchte, so muß der Anstoß zur
Wandlung aber von wo anders erfolgen, wenn ich den ADC nicht frei laufen
lassen möchte. Z.B. in meiner Timer1-ISR, alle 8msec? Von dort muß ich
aber auch dann die Kanäle wechslen und die Kanalnummer muß eine globale
Variable sein, damit ich in der ADC-ISR weiß, in welches Array ich das
Ergebnis schreiben muß.
Habe ich da richtig gedacht?
Gruß Rick
Rick M. schrieb:> JTD-Bit: If this bit is one the JTAG interface is disabled. (write twice> within four cycles)
muss in C So aussehehn
MCUCSR=0x80;
MCUCSR=0x80;//jtag off
Es kann zur Laufzeit genau so eingestellt werden.
pass aber auf das der Compiler die Dopplung der Sequenz nicht
wegoptimiert, sie soll ein versehentliches ausperren vehindern und ist
daher genau so auszuführen am besten während des PowerON
Das ist wollte ich hier sagen aber das Register war um eins daneben
richtig ist MCUCSR
Winfried J. schrieb:> die fuse musst du nicht ändern aber wärend des init in MCUCR das> jtagenablebit 2 mal binnen vier Takten disabeln.
Lass die Finger von den Fuse bits bis du die negative logik und den
Proggy gut beherscht!
Rick M. schrieb:> Hannes Lux schrieb:>> XX Ergebnis auslesen und über den Index in ein Array werfen>>>> XX Index erhöhen und auf Anzahl der Mess-Eingänge begrenzen>>>> XX Bitmuster für ADMUX für die nächste Messung aus einem anderen Array>> holen und in ADMUX schreiben>>>> XX ADC starten>> Wenn ich das richtig verstanden habe:>> Angenommen wir haben 3 Messeingänge für Spannung/Strom + 1 Eingang für> Tasten.>> Das würde jetzt ein 16bit-Array mit 4 Stellen ergeben.> Ich nenns jetzt mal uint16_t adc_ergebnis[4];>> und noch mal eins für die Adressen> uint8_t adc_adresse[] = {0 , 1 , 2 , 3 };> Das ginge glaub ich auch ohne Array
arry oder variablen das kannst du halten wie du willst
>> Wenn ich das in die ADC-ISR packen möchte, so muß der Anstoß zur> Wandlung aber von wo anders erfolgen, wenn ich den ADC nicht frei laufen> lassen möchte.
ja
>Z.B. in meiner Timer1-ISR, alle 8msec?
ja
>Von dort muß ich aber auch dann die Kanäle wechslen und die Kanalnummer> muß eine globale Variable sein, damit ich in der ADC-ISR weiß, in> welches Array ich das Ergebnis schreiben muß.
Ja, oder Parameter anfunktion und Returnwert übergeben dann passiert das
auf dem Stack.
wenn du genug RAM hast nimm globale Variablen das schont auch den
Stack(und die Nerven), weil du nicht tausend Parameter übergeben musst
profis nutzen lieber lokale variablen
Namaste
Hallo!
Der PORC funktioniert jetzt, warum das bei mir per Fuses nicht klappt
kann ich nicht sagen.
Deaktiviere JTAG jetzt so in der Init-Phase:
1
MCUCSR|=(1<<JTD);// JTAG aus
2
MCUCSR|=(1<<JTD);
Danke für den Tipp!
Ich habe versucht, Deine Vorgehensweise bezüglich der Tastenauswertung
umzusetzen. Leider erkennt mein Programm keine Tasten mehr, wenn ich in
den Vergleichen für den equal_counter (bei Dir Prellzähler) die
Bedingung button2 == 0 hinzufüge. Dieser zusätzliche Vergleich soll die
Erkennung bewerkstelligen, daß die Taste wiede losgelassen wurde.
1
if(button_read_puls==2)// 8msec vergangen
2
button1=read_button();// Tasten auslesen
3
4
if(button_read_puls==4)// weitere 8msec vergangen
5
{
6
button2=read_button();// Tasten auslesen
7
8
if(button1==button2)// wenn Tastennummer 1 = Tastennummer 2
9
if(++equal_counter==255)// Zählvariable für Übereinstimmung +1
10
equal_counter=0;// Schutz vor Überlauf
11
}
12
13
if((equal_counter>=10)&&(equal_counter<=50)&&(button2==0))// kurzer Tastendruck und Tastendruck vorbei
14
{
15
button=button1;// Tastennummer sichern
16
equal_counter=0;// Zähler zurücksetzen
17
}
18
19
if((equal_counter>=100)&&(equal_counter<=200)&&(button2==0))// langer Tastendruck und Tastendruck vorbei
20
{
21
button=button1+10;// neue Tastennummer für 2te Funktion
schick mir mal ne PN mit dem Ganzen Quellcode einschliesslich dem
nichtfunktionierenden vergleich (markieren)
ich bin für ne stunde einkaufen dann schau ichs mir mal an
so muss ich mehr raten als verstehen.
mein Test war damals nur für mich gedacht deshalb schwach kommentiert
aber das problem ist beim filtern die klar zuerkennen wann die taste
aufhört zu prellen und wann sich das Messergergebnis stabilisiert hat
und wann sie losgelassen wird. besonders bei autorepeat.
wichtig war auch die Fenstergrenzen für die Tasten zu optimieren
o. K. habe jetz gesehen was du machst
Ddu startest die messung und nach der messung versuchst du die Taste zu
zu ordnen.
Das ist leider Murks weil du keine Garantie hast das die Ttaste nicht
während der Messung prellt oder gedrückt oder losgelassen wird.
Ich habe auch so angefangen damals. Es kam nur murks herraus.
Genau deshalb habe ich meinen ADC frei laufen lassen. (ist natürlich
blöd für deine Sache, aber eins nach dem andern)
Ich schalte gegen Masse, du gegen Plus deshalb muss deine Strategie
entgegen meiner ein maximum suchen während meine das minimum suchte.
1
if (adc1<adc1_o)
2
{
3
adc1_o=adc1;
4
}
nur werte kleiner als der vorherige kamen zur auswertung
wurde losgelassen (wert größer 0x60)so wurde alles verworfen
1
if (adc1>=0x0060)
2
{
3
adc1_o=0x3ff;
4
t=0x00; t0=0x00; t1=0x00; t2=0x00;
5
}
müsste bei dir umgekehrt sein
jetzt erst folgte die siebkette
natürlich auch mit abfallenden Werten umgekehrt ist auch möglich (hat
nichts mehr mit der Polarität der schaltung zu tun)
so kann man die Fenstergrenzen maximieren und mit wenigen vergleichen
die Richtige von vielen tasten zuordnen
wo der wert nicht mehr durch geht wird der letze als gültig genommen
1
if (adc1_o <= 0x004C) {t = 0x33;}
2
if (adc1_o <= 0x0048) {t = 0x32;}
3
if (adc1_o <= 0x0045) {t = 0x31;}
4
if (adc1_o <= 0x0040) {t = 0x4c;} //left
5
if (adc1_o <= 0x0038) {t = 0x36;}
6
if (adc1_o <= 0x0035) {t = 0x35;}
7
if (adc1_o <= 0x0030) {t = 0x34;}
8
if (adc1_o <= 0x002D) {t = 0x55;} //up
9
if (adc1_o <= 0x0029) {t = 0x47;} //deal
10
if (adc1_o <= 0x0025) {t = 0x39;}
11
if (adc1_o <= 0x0021) {t = 0x38;}
12
if (adc1_o <= 0x001C) {t = 0x37;}
13
if (adc1_o <= 0x0019) {t = 0x44;} //down
14
if (adc1_o <= 0x0016) {t = 0x43;} //hang off
15
if (adc1_o <= 0x0010) {t = 0x23;}
16
if (adc1_o <= 0x000D) {t = 0x30;}
17
if (adc1_o <= 0x0009) {t = 0x2a;}
18
if (adc1_o <= 0x0004) {t = 0x52;} //right
erst jetzt werden 4 aueinanderfolgende Tastenergebnisse jeweils mit dem
vorherigen verglichen ungleiche setzen die Zählung zurück
1
if (t2==t1)
2
{
3
if (t1==t0)
4
{
5
if (t2==t)
6
{
7
PORTD=~t2; // nach 4 gleichen Mesunngen Ausgabe des Tastencodes PortD
8
//Signalinvertierung da LEDs über R-Netz an +5V geführt
9
werden.
10
// hier must du deinen gültige taste in den den rückgabewert schreiben. Der funktion schreiben.
11
}
12
}
13
}
14
15
t2=t1;
16
t1=t0;
17
t0=t;
jet müssen wir sehen wie das mit deinen anderen messungen zu
koordinieren ist.
Hallo!
Eine Frage:
Warum benutzt Du überall Zahlen im Hex-Format, das kann doch keiner
lesen?
Mann muß da alle Konstanten in Dezimal umrechnen, um sich etwas darunter
vorstellen zu können.
0x0060 = 96
adc1_o steht für? oben?
Gruß Rick
Am Besten triggerst du den ADC so oft bis du ein gültiges Tastenergebnis
(4 gleiche Tasten nacheinander) besitzt. 4*Keine Taste ist auch ein
gültiges Ergebnis und kehrst erst dann nach main zurück.
Nur der einsprung in die Messreihe sollte durch den Timer initialisiert
werden.
Namaste
weil ich in binär/hex denke jedes hexziffer steht für ein nibble aus 4
bit
wnn man das erst mal im hirn hat weis man erst was dez für eine Krücke
ist
ich sehe f und wis alle 4 bit des nibble sind gesetzt
sehe ich c weis ich die oberen beden nibble singesetzt
sehe ich eine ungerade hexziffer wis ich das unterste bit des nibbles
ist gesetzt
dazu muss man die 2er potenzen natürlich wie leuchtdioden vor sich sehen
Da rechne ich keine Sekunde, ich sehe es wie beim kleinen Einmaleins
Genauso beim Ascii. Kennst du dessen hexadezimale struktutur so kannst
du die tabelle im schlaf herbeten. Das mach mal in dec.
Rick M. schrieb:> Na erzähl das blos nicht einen Psychiater, der läßt dich nicht mehr raus> ;-)
to late
bin schon ewig wieder draußen
Mit dem Schaden muss ich weiterleben, übrigens der typische schaden von
Programierern meines Alters. Manche haben auch einen BCD- oder Grey-
star.
Aber mit so einem Spatz lebt sich leicht, so lange man keinen größeren
Vogel hat.
Irgendwelche Eulen sind nicht hier oder?
Namaste
Sorry, aber ich versteh Dein Denkschema einfach nicht.
Du hast in den if-Anweisungen Vergleiche z.B
wenn t1 gleich t2
wenn t1 gleich t0
wenn t0 gleich t
Die t´s sind Variablen für die Tastennummer?, die müssen ja vor den
if-Anweisungen Werte haben. Du weist ja nur zu den ADC-Werten die
Variable t zu.
Deshalb meine Frage: Wie bekommen die Variablen t0, t1, t2 ihre Werte?
Zuerst einen Vergleich machen und hinterher was zuweisen?
Sorry, blick da aber momentan einfach überhaupt nicht durch, was Du da
machst.
Vielleicht brauch ich ja einfach nur mal ne Pause und etwas Abstand....
In meinem Code weise ich die Tasten-Nr. ja so zu:
button1 = read_button();
warten
button2 = read_button();
button1 == button2 ?
wenn ja equal_counter +1
wieder von vorne beginnen
Gruß Rick
Winfried J. schrieb:> to late>> bin schon ewig wieder draußen>> Mit dem Schaden muss ich weiterleben, übrigens der typische schaden von> Programierern meines Alters. Manche haben auch einen BCD- oder Grey-> star.>> Aber mit so einem Spatz lebt sich leicht, so lange man keinen größeren> Vogel hat.>> Irgendwelche Eulen sind nicht hier oder?
Nee, die sind momentan alle bei mir und versuchen sich gerade häuslich
einzurichten......
Rick M. schrieb:> Sorry, aber ich versteh Dein Denkschema einfach nicht.>> Du hast in den if-Anweisungen Vergleiche z.B> wenn t1 gleich t2> wenn t1 gleich t0> wenn t0 gleich t>> Die t´s sind Variablen für die Tastennummer?, die müssen ja vor den> if-Anweisungen Werte haben. Du weist ja nur zu den ADC-Werten die> Variable t zu.>
t bekommt die tasten id aus der siebkette
in t0,t1,undt2 werden die tasten werte der letzten drei messungen
aufbewart
zuerst wird geschaut ob t2==t1
wen ja ob t1==t0
und zum schluss ob t0==t
dann wird augegeben
achtung das ist geschachtelt
[pre]
if (t2==t1)
{
if (t1==t0)
{
if (t2==t)
{
PORTD=~t2; // nach 4 gleichen Mesunngen Ausgabe des
Tastencodes PortD
//Signalinvertierung da LEDs über R-Netz an +5V geführt
werden.
// hier must du deinen gültige taste in den den
rückgabewert schreiben. Der funktion schreiben.
}
}
}
[/pr]]
nach diese auswertung
wird t1 nach t2 geschoben
t0 nach t1
und t nach t0
[/pr]
t2=t1; // Hier !!!
t1=t0; //
t0=t; //
[pre]
das heist die letzten 3 werte werden für den nächsten vergleich
vorbereitet
(um eine position im puffer verschoben) und gerettet
bevor in t der neu Tataturwert eingetragen wird.
das könnte man auch in einem array machen aber das macht es nur
komplizierte weil du dan die elemente des arrays auch scrolen musst.
bei vier elementen ist die zeigerverwaltung aufwendiger als die diskrete
umsetzung.und mehr ist hier nicht nötig wür eine Laufschrit bastelt mann
sich einen ringpuffer.
Wird die taste losgelassen werden alle t-speischer auf 0 gesetzt
> Deshalb meine Frage: Wie bekommen die Variablen t0, t1, t2 ihre Werte?>> Zuerst einen Vergleich machen und hinterher was zuweisen?>> Sorry, blick da aber momentan einfach überhaupt nicht durch, was Du da> machst.>> Vielleicht brauch ich ja einfach nur mal ne Pause und etwas Abstand....>
Sicher, sowas mache ich dann auch mal. Die Liebste schaen und Kaffee und
wenn nichts mehr geht mal die Festplatte formatieren lassen, ich hoffe
du weist wie das geht, danach ist man zwar nicht jungfräulich aber der
Geist wieder leer und fit für neuen müll.
>> In meinem Code weise ich die Tasten-Nr. ja so zu:>> button1 = read_button();> warten> button2 = read_button();>> button1 == button2 ?> wenn ja equal_counter +1>> wieder von vorne beginnen>> Gruß Rick
Du vergleichst nur Paare
Ich vergleiche vier aufeinanderfolgende.
und schiebe sie wie eine Laufschrift weiter
nur schiebe ich nichts im kreis,
sondern stehts vorn rein und hinten fällt das älteste raus (t2 wird
nicht gerettet sondern einfach überschrieben mit t1)..... zum schluss t0
mit t.
das heist ich verwerfe injedemschritt nur die älteste Messung.
Dann wird T mit einem neuen Messwert beschrieben und wieder auf vier
Gleiche getestet. Bis ich vier gleiche Tastaturwerte habe! Der wird dann
von meiner ISR als Ausgabewert an PORTD gebracht und könnte auch als
Returnwert zurück an die aufrufende Schicht übergeben werden, oder in
eine globale Variable geschrieben werden.
Namaste
Rick M. schrieb:> Sorry, aber ich versteh Dein Denkschema einfach nicht.>> Du hast in den if-Anweisungen Vergleiche z.B> wenn t1 gleich t2> wenn t1 gleich t0> wenn t0 gleich t>> Die t´s sind Variablen für die Tastennummer?, die müssen ja vor den> if-Anweisungen Werte haben. Du weist ja nur zu den ADC-Werten die> Variable t zu.>
t bekommt die TastenID aus der Siebkette
in t0,t1,undt2 werden die TtastenIDs der letzten drei Messungen
aufbewart
zuerst wird geschaut ob t2==t1
wen ja ob t1==t0
und zum Schluss ob t0==t
dann wird ausgegeben
Achtung das ist geschachtelt
1
if (t2==t1)
2
{
3
if (t1==t0)
4
{
5
if (t2==t)
6
{
7
PORTD=~t2; // nach 4 gleichen Mesunngen Ausgabe des Tastencodes PortD
8
//Signalinvertierung da LEDs über R-Netz an +5V geführt werden.
9
// hier must du deinen gültige Taste in den den Rückgabewert schreiben. Der funktion schreiben.
10
}
11
}
12
}
nach diese auswertung
wird t1 nach t2 geschoben
t0 nach t1
und t nach t0
1
t2=t1; // Hier !!!
2
t1=t0; //
3
t0=t; //
Das heist die letzten 3 werte werden für den nächsten Vergleich
vorbereitet
(um eine Position im Puffer verschoben) und gerettet,
bevor in t der neu Tastaturwert eingetragen wird.
Das könnte man auch in einem Array machen, aber das macht es nur
komplizierter, weil du dan die Elemente des arrays auch scrollen musst.
Bei vier Eelementen ist die Zeigerverwaltung aufwendiger als die
diskrete umsetzung. Und mehr ist hier nicht nötig. Würd man eine
Laufschriftt basteln, nähme einen Rringpuffer.
Wird die taste losgelassen werden alle t-speischer auf 0 gesetzt
> Deshalb meine Frage: Wie bekommen die Variablen t0, t1, t2 ihre Werte?>> Zuerst einen Vergleich machen und hinterher was zuweisen?>> Sorry, blick da aber momentan einfach überhaupt nicht durch, was Du da> machst.>> Vielleicht brauch ich ja einfach nur mal ne Pause und etwas Abstand....>
Sicher, sowas mache ich dann auch mal. Die Liebste schaen und Kaffee und
wenn nichts mehr geht mal die Festplatte formatieren lassen, ich hoffe
du weist wie das geht, danach ist man zwar nicht jungfräulich aber der
Geist wieder leer und fit für neuen müll.
>> In meinem Code weise ich die Tasten-Nr. ja so zu:>> button1 = read_button();> warten> button2 = read_button();>> button1 == button2 ?> wenn ja equal_counter +1>> wieder von vorne beginnen>> Gruß Rick
Du vergleichst nur Paare
Ich vergleiche vier aufeinanderfolgende.
Und schiebe sie wie eine Laufschrift weiter.
Nur schiebe ich nichts im Kreis,
sondern stehts vorn rein und hinten fällt das älteste raus (t2 wird
nicht gerettet, sondern einfach überschrieben mit t1)..... zum schluss
t0 mit t.
Das heist ich verwerfe in jedem Schritt nur den ältesten Tastenwert.
Dann wird T mit einem neuen Messwert beschrieben und wieder auf vier
Gleiche getestet. Bis ich vier gleiche Tastaturwerte habe! Der wird dann
von meiner ISR als Ausgabewert an PORTD gebracht und könnte auch als
Returnwert zurück an die aufrufende Schicht übergeben werden, oder in
eine globale Variable geschrieben werden.
Namaste
Rick M. schrieb:>> Irgendwelche Eulen sind nicht hier oder?>> Nee, die sind momentan alle bei mir und versuchen sich gerade häuslich> einzurichten......
Nein, er meint was Anderes. Diese Eulen und ihre Jäger sind aber eher im
Dummschwätzer-Teil dieses Forums zu finden... ;-)
Ich will Winfried nicht ins Handwerk pfuschen, aber trotzdem diese Frage
beantworten:
Rick M. schrieb:> Hannes Lux schrieb:>> XX Ergebnis auslesen und über den Index in ein Array werfen>>>> XX Index erhöhen und auf Anzahl der Mess-Eingänge begrenzen>>>> XX Bitmuster für ADMUX für die nächste Messung aus einem anderen Array>> holen und in ADMUX schreiben>>>> XX ADC starten>> Wenn ich das richtig verstanden habe:>> Angenommen wir haben 3 Messeingänge für Spannung/Strom + 1 Eingang für> Tasten.>> Das würde jetzt ein 16bit-Array mit 4 Stellen ergeben.> Ich nenns jetzt mal uint16_t adc_ergebnis[4];
Ja...
>> und noch mal eins für die Adressen> uint8_t adc_adresse[] = {0 , 1 , 2 , 3 };
Richtig, darin befinden sich dann die Werte für ADMUX, mit denen
Mess-Quelle und Referenz eingestellt wird, bei den meisten AVRs auch die
Ergebnis-Formatierung (ADLAR).
> Das ginge glaub ich auch ohne Array
Dann musst Du aber per If-Orgie die richtigen Werte ermitteln.
Array-Zugriffe sind nicht nur eleganter, sondern vor Allem schneller.
Deshalb gönne ich der ADC-Abfrage auch ohne Reue die paar Bytes SRAM,
die das Array mit den MUX-Werten kostet.
Da ich in ASM programmiere und es die genialen Befehle LDD und STD gibt,
kann ich beide Arrays über einen Pointer (als Index) ansprechen, was die
Sache extrem effizient macht. (Ein Pointer ist in ASM nicht dasselbe wie
in C)
>> Wenn ich das in die ADC-ISR packen möchte, so muß der Anstoß zur> Wandlung aber von wo anders erfolgen,
Richtig, und zwar in der Reset-Routine. Dort werden die ersten Parameter
gesetzt (Index, ADMUX) und die erste Wandlung (Messung) angestoßen.
> wenn ich den ADC nicht frei laufen> lassen möchte.
Der Freerun-Modus bringt aber nur was, wenn man das im Timer-Interrupt
nebenher macht. Dann stellt man das Timing so ein, dass der ADC bis zur
nächsten Abfrage mindestens 2 neue Ergebnisse ermittelt hat, das bringt
stabilere Ergebnisse weil unter gewissen Bedingungen die erste Messung
nach der Quellenumschaltung nicht ganz genau sein könnte.
> Z.B. in meiner Timer1-ISR, alle 8msec?
Ich wüsste jetzt nicht warum? 8 ms halte ich für das Messen auf 4
Kanälen für etwas langsam.
> Von dort muß ich> aber auch dann die Kanäle wechslen
Nööö, das kann auch der ADC-Interrupt erschlagen. Deshalb die
Reihenfolge:
- ADC-Wert auslesen und Messwert über den Index ins Array kopieren
- Index erhöhen, bei Überlauf (Array-Größe) Index auf 0 setzen und
Funktion für die Tastenermittlung aufrufen
- MUX-Wert gemäß Index aus Mux-Array holen und in ADMUX schreiben
- Nächste ADC Einzelmessung mit Interrupt starten
Die Funktion der Tastenermittlung ermittelt über eine LUT, oder über
eine Switch- oder IF-Orgie den Tastenwert, und vergleicht diesen mit dem
beim letzten mal ermittelten Tastenwert. Bei Gleichheit wird der
Prellzähler erhöht, bei Ungleichheit gelöscht. Erreicht der Prellzähler
(Global bzw. Static) die Prellschwelle, dann ist der Tastenwert gültig
und wird (falls er nicht 0 ist, was für "keine Taste gedrückt" steht)
dem Hauptprogramm in eine globale Variable gelegt. Dieses reagiert
darauf und löscht sie nach Abarbeitung.
Dies wäre die einfache Lösung, die nur Tastendrücke erkennt und nicht
zwischen kurz und lang unterscheiden kann. Die Lösung mit
Kurz/Lang-Unterscheidung habe ich oben schon erklärt.
> und die Kanalnummer muß eine globale> Variable sein, damit ich in der ADC-ISR weiß, in welches Array ich das> Ergebnis schreiben muß.
Ja sicher doch. Zumindes "Static", falls es in C sowas gibt (in Basic
kann man lokale Variablen als Static definieren, wodurch sie ihren Wert
zwischen den Aufrufen behalten).
>> Habe ich da richtig gedacht?
Teils.
Aber ich will Dir nicht meine Methode aufzwingen, deshalb halte ich mich
jetzt etwas zurück. Konzentriere Dich also erstmal auf Winfrieds
Konzept. Denn viele Köche verderben... Hmmm, äähhh, achja, ...die
Köchin.
...
@ Hannes
viele Wege führen nach ROM
und ich sehe das eher als Bereicherung auch für mich. Und wie gesagt war
das damals sicher auch nicht der Elganz und Weisheit letzer Schluß.
Ich habe damals die Grenzen Vor- und Nachteile des ADC verstehen wollen,
mehr nicht.
Dabei erkannte ich das Taster und ADC eher eine bescheidene Kombination
ist, aber mit genügend Redundanz und guter Filterstrategie zum Erfolg
(20 Tasten bei min 4 Digit Abstand und Serienbauteilen) führt.
Peter D. packt das Problem wahrscheinlich in 128 byte code und 5
register
Aber ich war damals noch nicht soweit, genau wie heute ric.
Das Problem war nicht ADC zu bedienen sondern die Werte richtig
auszuwerten weil: Wer misst misst viel Mist.
if(){} select case oder brn.
Es läuft immer auf ein Orgie hinaus.
Also Siebkette und kräftig geschüttelt wichtig ist es die Übersicht zu
behalten.
Permanenter Stilwechsel ist dem zwar nicht förderlich,
gibt aber neue Impulse und ohne PAP ist es nicht einfach die Struktur
eines fremden Quellcodes zu lesen. Einfacher ist es den Eigenen zu
erklären
Wenn das Prinzip dan klar ist muss man das im eigenen Stil umsetzen.
Namaste
LUT ist nett erfordert aber für die Tastatur einen definierten
Übergangswiderstand an den Tasten (unrealistisch) deshalb hier if Orgie
als Siebkette mit Komperatorschwellen.
Bei mir ein Fensterdiskriminator mit 21 Fenstern
Für ihn 5 gültige Fenster
Namaste
Winfried J. schrieb:> LUT ist nett erfordert aber für die Tastatur einen definierten> Übergangswiderstand an den Tasten (unrealistisch)
Damit hatte ich noch keine Probleme. Ich benutze gern die
Kurzhub-Taster, meist unter einer Laminierfolie mit einlaminiertem
bedruckten Blatt Papier.
Z.B. hier bei einem Eigenbau-Gerät:
http://www.hanneslux.de/dcc/z1/dccz1b.html
Oder hier ohne eigenen (selbstprogrammierten) AVR als Ersatz für das
Poti eines Steuerknüppels:
http://www.hanneslux.de/planet5b/planet5-Umbau.html> deshalb hier if Orgie> als Siebkette mit Komperatorschwellen.>> Bei mir ein Fensterdiskriminator mit 21 Fenstern
Ist auch mit LUT machbar. Jeder Eintrag bekommt 2 Werte, zuerst den
Schwellenwert, dann die Tastennummer. Die Schwellenwerte liegen dann
zwischen den per Tasten erreichten ADC-Werten.
In einer Schleife werden beide Werte gelesen und der ADC-Wert mit dem
Schwellenwert verglichen. Ist der ADC-Wert kleiner als der Schwellenwert
der Liste, so wird die Schleife verlassen und die zuletzt gelesene
Tastennummer ist gültig.
>> Für ihn 5 gültige Fenster
Da ist die If-Orgie billiger...
>
Sorry, da ich in ASM werkele, versuche ich auch den verfügbaren
Befehlssatz halbwegs effizient zu nutzen. Das hat vielleicht auch damit
zu tun, dass ich die AVR-Architektur, auf der der Befehlssatz basiert,
einigermaßen kenne. Meine ersten AVRs waren AT90S1200, ATTiny12 und
ATTiny15, die hatten kein SRAM und waren mit Hochsprachen nicht oder nur
sehr schwierig zu programmieren, daher ASM...
> Namaste
Dito...
...
Rick M. schrieb:> Ich weiß, daß es eine Komfort-Routine und das Bsp. mit der> Matrixtastatur am ADC von Peter Dannegger dazu gibt, aber leider ist mir> das als Anfänger etwas zu hoch....
Wenn ich diesen langen Thread sehe, vermute ich mal, es wäre einfacher
gewesen, mich zu den Sachen zu fragen, die Dir Probleme beim Verstehen
bereiten.
In meinem Code ist ja zu sehen, daß ich den Compiler das Ohmsche Gesetz
selber ausrechnen lasse (Ich bin nämlich stink faul).
Auch wenn Deine Schaltung anders aussieht, kann man dafür bestimmt auch
eine Formel aufstellen.
Ich bin ein Fan von modularem Programmieren, d.h. ich mache kleinste
Unterfunktionen für jede einzelne Aufgabe.
Ich kann nur jedem empfehlen, es genauso zu machen.
Gerade Anfänger neigen dazu, alles immer zusammen zu verwursten. Ich
kann aus Erfahrung davon nur dringend abraten, das ist ne Sackgasse.
Peter
hallo
Peter hast du eine Klingel, wenn jemand deinen Namen hier erwähnt?shelt
es aus dem Forum?
Du erscheinst ja aufs Stichwort.
Ich schrieb:> Peter D. packt das Problem wahrscheinlich in 128 byte code und 5> registerPeter Dannegger schrieb:> (Ich bin nämlich stink faul).
Faulheit ist die antribesfeder der Intelligenz und damit jeder
Entwicklung.
zu Rick
Man halte ihm zu gute das er sich reedlich durchwurstelt, und das lehrt
mehr als eine ffertige lösung welche auf anhieb funktioniert.
Namaste
Hallo Winfried!
Zu deimen geposteten Code:
Nehmen wir mal an der Code stellt ein Unterprogramm dar, nennen wir es
"uint8_t read_button(void)".
Zuerst holst Du dir vom ADC 2 neue Messwerte (direkt aufeinander
folgend?)und ermittelst von beiden den Größeren.
Diesen vergleichst du dann mit einer Maximalschwelle, was bei dir einen
losgelassenen Taster gleich kommt.
Falls dies der Fall ist, löscht du das komplette Schiebe-Register und
setzt den Messwert gleichzeitig (wahrscheinlich aus Sicherheitsgründen)
auf den Maximalwert des ADC (1023).
Ist die Maximal-Schwelle nicht überschritten, so wird der ADC-Max-Wert
durch deine Vergleichstabelle geschick und die dazugehörige
Tasten-Nummer ermittelt.
Diese Tasten-Nummer speicherst Du dann in einem 4-Stelligen
FIFO-Register.
Erst wenn alle 4 Stellen in diesem Register gleich sind liefert das
Unterprogramm eine Tasten-Nummer zurück.
Warum die if-Verschachtelung, ginge es nicht auch so:
1
if(t==t0==t1==t2)
2
returnt2;
Das Unterprogramm muß mindestens 4 mal, bei gedrückter Taste, aufgerufen
werden, um eine Tasten-Nummer ungleich Null zurück zu bekommen.
Somit müßte das Unterprogramm zyklisch, z.B. alle 10msec, aufgerufen
werden.
Ist das richtig?
Deine LUT gibt mir allerdings noch zu denken, denn wenn ich nur sage
1
if(adc_value<=100)
Dann umfasst dies auch alle unter dieser Schwelle liegenden Tasten und
nicht nur diese eine Taste
Gruß Rick
Hallo Peter!
Peter Dannegger schrieb:> Wenn ich diesen langen Thread sehe, vermute ich mal, es wäre einfacher> gewesen, mich zu den Sachen zu fragen, die Dir Probleme beim Verstehen> bereiten.
Da müßte ich erst mal konkrete Fragen haben.
Wenn ich mir einen fremden Code ansehe, so suche ich zuerst nach einem
Grundschema. Detail-Lösungen interessiern mich zu diesem Zeitpunkt noch
gar nicht.
Änlich einem Blockschaltbild von einem IC-Datenblatt.
Ich frage mich, was für ein Konzept verfolgt er und was sind die
->Rahmenbedingungen<- ?
Konkret: Woher nimmst Du den ADC-Wert her, wie wird er übergeben?
Wird der ADC-Kanal zyklisch abgefragt? Du hast ja einen Timer am laufen
(10msec)....
Dein 2bit vertikal Zähler gibt mir ja schon Rätsel auf, aber das gehört
ja schon wieder zu den Detail-Lösungen.
Du siehst ich habe schlicht weg das Problem, daß ich das Gesamt-Konzept
und dessen Rahmenbedingungen nicht kenne bzw. nicht verstehe und somit
weiß ich auch nicht wo ich den Hebel ansetzen soll.
Peter Dannegger schrieb:> Ich bin ein Fan von modularem Programmieren, d.h. ich mache kleinste> Unterfunktionen für jede einzelne Aufgabe.> Ich kann nur jedem empfehlen, es genauso zu machen.
Das bin ich auch und ich versuche dieses Konzept nicht nur in der
Schaltungtechnik, sondern auch beim Programmieren umzusetzen.
Das einem dies als Anfänger nicht immer gelingt, weil man schlichtweg
den Überblick verliert, steht außer Frage.
Gruß Rick
Rick M. schrieb:> Hallo Winfried!>> Zu deimen geposteten Code:>> Nehmen wir mal an der Code stellt ein Unterprogramm dar, nennen wir es> "uint8_t read_button(void)".
o.k.
voraussetzung pullup an plus, taster schaltet über R mess nach Ground
schau dir mein Schaltbild an Rmess wird durch die Matrix realisiert
Einzelwiderstände gehen auch (aber nicht bei meiner Tastaturmatrix)
> Zuerst holst Du dir vom ADC 2 neue Messwerte (direkt aufeinander> folgend?)und ermittelst von beiden den Größeren.
ich habe 2 variablen
nenn wir sie alt und neu alt wird mit max initialisiert
desweiteren habe ich einen tastenwertstapel in dem alle tastenwerte
gelöscht(0) sind
nun stoße ich die erste messung an warte af das ergebniss
und vergleiche neu mit alt
ist der neue wert kleiner als der alte wird der neue mit dem alten
überschrieben. Ansonsten wird nichts getan und das Progremm fort
gesetzt.
> Diesen vergleichst du dann mit einer Maximalschwelle, was bei dir einen> losgelassenen Taster gleich kommt.> Falls dies der Fall ist, löscht du das komplette Schiebe-Register und> setzt den Messwert gleichzeitig (wahrscheinlich aus Sicherheitsgründen)> auf den Maximalwert des ADC (1023).
richtig
mit diesem jetz ermittelten Wert in alt liegend wird die If Siebkette
vom größten zur kleinsten maschenweite durchlaufen und in jeder stufe
wird der aktuelle tastaturcode(ascii)der stufe nach t geschrieben.
so wird jeweis in der folgenden stufe der neue Tastaturwert eingetragen.
fällt der messwert alt nicht mehr weiter durch die maschen der
darunterliegenden siebe so gleitet das letzte ermittelt askciizeichen in
t liegend den siebstufen vorbei das ist mein aktueller tastatur wert.
> Ist die Maximal-Schwelle nicht überschritten, so wird der ADC-Max-Wert> durch deine Vergleichstabelle geschick und die dazugehörige> Tasten-Nummer ermittelt.
nein auch mit wenn er überschritten wurde , dann bleibt er in dem ersten
sie hängen und es bleibt 0 in t erhalten
> Diese Tasten-Nummer speicherst Du dann in einem 4-Stelligen> FIFO-Register.
eher schiebregister (beim fifo wird auch geschoben aber am ausgang kommt
alles sukzessife wieder raus bei mir kommt nur raus was vier gleich
zeigt alles andere landet im nirvana)
> Erst wenn alle 4 Stellen in diesem Register gleich sind liefert das> Unterprogramm eine Tasten-Nummer zurück.
gebnauso
> Warum die if-Verschachtelung, ginge es nicht auch so:>
1
>if(t==t0==t1==t2)
2
>returnt2;
3
>
>
das wird warscheinlich gehen wen der compiler kapiert was du willst
da denke ich wahrscheinlich zusehr assembler, den der kann nur 2 werte
vergleichen und der compiler muss aus deinem therm eh wieder meine if
veschachtelungsorie machen
> Das Unterprogramm muß mindestens 4 mal, bei gedrückter Taste, aufgerufen> werden, um eine Tasten-Nummer ungleich Null zurück zu bekommen.
ja und zwar so oft bis es einen gültigen wert hat der auch sein kann das
viermal hintereinander keine taste gedrückt wurde.
daher würde ich die 4 gleiche zur abruchbedingung einer while schleife
machen
> Somit müßte das Unterprogramm zyklisch, z.B. alle 10msec, aufgerufen> werden.>
wenn du die von mir vorgeschlagene whileschleife nimmst in das
unterprogramm nimmst liefert es dir gleich eine gültige taste sobald es
eine hat.
> Ist das richtig?
ansonsten ja
>> Deine LUT gibt mir allerdings noch zu denken, denn wenn ich nur sage>
1
if(adc_value<=100)
> Dann umfasst dies auch alle unter dieser Schwelle liegenden Tasten und> nicht nur diese eine Taste
es ist ein Sieb mit Bypas alles was nicht durchs sieb passtt wird
rausgeschütteltund vorbeigeleitet. Beim durchfallen einersiebstufe wird
t umgestempelt.
Hinter dem sieb ist alt unwichtig und kann verworfen werden da ja jetzt
ein tastaturcode ermittelt ist
und wenn es 0 ist weil schon das erste sieb zu eng war
es ist wie mit meinen "nicht FiFo"
wie gesagt ich stand am gleichen punkt wie du heute und wollte es testen
das ist schon ein paar Jahre her und wurde nicht optimiert
aber da der assembler eh nur 2 register vergleichen kann ...
> Gruß Rick
e tu
Namaste
Winfried J. schrieb:>> Diese Tasten-Nummer speicherst Du dann in einem 4-Stelligen>> FIFO-Register.> eher schiebregister (beim fifo wird auch geschoben aber am ausgang kommt> alles sukzessife wieder raus bei mir kommt nur raus was vier gleich> zeigt alles andere landet im nirvana)
also ein FiFo, daß erst ausgewertet wird, wenn es 4 gleiche Werte
beinhaltet.
Wenn du einen neuen t-Wert vorne reinschiebst, fällt der alte-t2 Wert
raus.
Ist aber natürlich reine Ansichtssache... ;-)
Winfried J. schrieb:> wenn du die von mir vorgeschlagene whileschleife nimmst in das> unterprogramm nimmst liefert es dir gleich eine gültige taste sobald es> eine hat.
also
Rick M. schrieb:> Winfried J. schrieb:>>> Diese Tasten-Nummer speicherst Du dann in einem 4-Stelligen>>> FIFO-Register.>> eher schiebregister (beim fifo wird auch geschoben aber am ausgang kommt>> alles sukzessife wieder raus bei mir kommt nur raus was vier gleich>> zeigt alles andere landet im nirvana)>> also ein FiFo, daß erst ausgewertet wird, wenn es 4 gleiche Werte> beinhaltet.> Wenn du einen neuen t-Wert vorne reinschiebst, fällt der alte-t2 Wert> raus.> Ist aber natürlich reine Ansichtssache... ;-)>> Winfried J. schrieb:>> wenn du die von mir vorgeschlagene whileschleife nimmst in das>> unterprogramm nimmst liefert es dir gleich eine gültige taste sobald es>> eine hat.>> also>
das sollte passen
aber auf deine Hw bezogen
muss der vergleich neu alt immer den größeren wert bernehmen
du nach pluss schaltest
ich würde es jedoch auch die HW noch mal umbauen, da dei ADC an einer
floatenden leitung hängt wenn keine Taste gedrückt ist oder habe ich
etwas übersehen?
Besser wäre auf jeden Fall bei offener Taste ein definiertes Potential
am Eingang zu haben und mit der Taste eine Spannugsteiler zu ralisieren.
Sieh dir meine Schaltung noch mal an, falls dich noch niemand darauf
aufmerksam gemacht hat.
Dann gibt es weniger Fehlmessungen bei offener Tastern
Alternativ die Taster durch einen sehr großen widerstand nach Masse
ziehen(20-100K).
dann brauchst du natürlich neue schwellwerte
Keines Falles Kondensatoren dort verwenden, das kostet etliche Messungen
mehr.
Namaste
Nachtrag!!!!
Ohne das floatende Signal auf der ADC Leitung zu beheben wird sich die
das programm regelmäßig im While, aufhängen da du nicht erkennen kannst
das die Taster alle offen sind das Potential (Spannung der Leitung ist
dann undefiniert)
Mit deinen Einzelmessungen hättst du alle mögliche tasten vermuten
können.
Meine Schleife kommt einfach nicht mehr zurück, wenn nicht 4 Messungen
den selben Tastaturcode liefern!!!!
Winfried J. schrieb:> ich würde es jedoch auch die HW noch mal umbauen, da dei ADC an einer> floatenden leitung hängt wenn keine Taste gedrückt ist oder habe ich> etwas übersehen?
siehe meinen ersten Beitrag:
Rick M. schrieb:> Ich habe zusätzlich den Pin PA7 mit 100k gegen GND gezogen,> damit der ADC nicht in der Luft hängt.
bzw:
Rick M. schrieb:> zu beachten ist, daß es sich jeweils um eine Parallelschaltung von (1> bis 5k) und 100k handelt.> So ergebne sich für die einzelnen Tasten folgende Widerstanswerte:>> Taster1: 4,76k>> Taster2: 3,846k>> Taster3: 2,913k>> Taster4: 1,961k>> Taster1: 990 OhmWinfried J. schrieb:> Sieh dir meine Schaltung noch mal an, falls dich noch niemand darauf> aufmerksam gemacht hat.
Welche Schaltung, hab ich da was übersehen?
Einen Schaltplan hast Du nie angehängt.
Winfried J. schrieb:> Keines Falles Kondensatoren dort verwenden, das kostet etliche Messungen> mehr.
Ist klar, das ergibt eine C-Lade/Entlade-Kennlinie
Winfried J. schrieb:> ich habe 2 variablen> nenn wir sie alt und neu alt wird mit max initialisiert> nun stoße ich die erste messung an warte af das ergebniss> und vergleiche neu mit alt> ist der neue wert kleiner als der alte wird der neue mit dem alten> überschrieben.
1
uint16_tadc_alt=1023;
2
uint16_tadc_neu=0;
3
4
//**** Aufruf im Main **************************************
adc_neu=adc_alt// gedrückte Taste wird vernichtet!
Eine gedrückte Taste würde bei Dir z.B den ADC-Wert 70 bedeuten.
Da 70 kleiner 1023 wird 70 mit 1023 überschrieben und somit die
Erkennung der gedückten Taste vernichtet?
Mist hab schon wieder n over flow......
Winfried J. schrieb:> Ohne das floatende Signal auf der ADC Leitung zu beheben wird sich...
...keine Tastatur ordentlich abfragen lassen, egal ob mit meiner
Methode, mit Winfrieds Methode, mit Peter Danneggers Methode oder wie
auch immer.
Entweder, Du baust einen Pull-Down-(Pull-Up-)Widerstand (etwa 20..50k)
ein, oder Du änderst die Spannungsteilerschaltung so ab, wie ich sie
weiter oben beschrieben habe.
...
Ich hab nicht alles gelesen, aber ich habe den Eindruck, daß Du bisher
nichtmal meinem Rat gefolgt bist und die ADC-Werte ausgibst.
Es hat keinen Zweck, den zweiten Schritt zu tun, bevor man nicht sicher
ist, daß der erste Schritt klappt.
Schau Dir also die ADC-Werte an, wenn man eine Taste drückt. D.h. wie
schnell erreichen sie den Endwert, wie weit zappeln sie und wie schnell
reagieren sie auf das Loslassen.
Ich würde allerdings den 10k rausnehmen und dafür direkt vom ADC-Eingang
nach VCC legen. Dann hast Du immer maximal 10k Eingangsimpedanz und
Störungen beim Loslassen sind 10-mal besser unterdrückt, als bei großen
100k.
Peter
Rick M. schrieb:> Winfried J. schrieb:>> ich habe 2 variablen>> nenn wir sie alt und neu alt wird mit max initialisiert>> nun stoße ich die erste messung an warte af das ergebniss>> und vergleiche neu mit alt>> ist der neue wert kleiner als der alte wird der neue mit dem alten>> überschrieben.>
sorry natürlich umgekehrt der alte wird bedingt überschrieben und der
wird auch ausgewertet
>>>> uint16_t adc_alt = 1023;> uint16_t adc_neu = 0;> //**** Aufruf im Main **************************************> adc_neu = adc_lesen(); // ADC lesen>>> button = read_button( adc_alt); // Tastennummer auslesen,>> //*******************************************************************>>> uint8_t read_button(uint16_t adc_neu)> {>>> if (adc_neu > adc_alt) // adc_alt = 1023!! Bedingung wahr>>> adc_alt = adc_neu // gedrückte Taste wird vernichtet!>>>>> Eine gedrückte Taste würde bei Dir z.B den ADC-Wert 70 bedeuten.> Da 70 kleiner 1023 wird 70 mit 1023 überschrieben und somit die> Erkennung der gedückten Taste vernichtet?> richtig
so das sollte für deine HW jetzt passen.
Namaste
Hannes Lux schrieb:> Winfried J. schrieb:>> Ohne das floatende Signal auf der ADC Leitung zu beheben wird sich...>> ...keine Tastatur ordentlich abfragen lassen, egal ob mit meiner> Methode, mit Winfrieds Methode, mit Peter Danneggers Methode oder wie> auch immer.
ich habe einen Pull down widerstand!!!
Hannes Lux schrieb:> Entweder, Du baust einen Pull-Down-(Pull-Up-)Widerstand (etwa 20..50k)> ein, oder Du änderst die Spannungsteilerschaltung so ab, wie ich sie> weiter oben beschrieben habe.
was ich schon von anfang an habe brauch ich nicht nochmal machen...
Peter Dannegger schrieb:> Ich hab nicht alles gelesen, aber ich habe den Eindruck, daß Du bisher> nichtmal meinem Rat gefolgt bist und die ADC-Werte ausgibst.
Die von mir programmierten Tasten-Fenster beruhen darauf, daß ich mir
die ADC-Werte auf dem LCD ausgeben habe lassen...
es liegt also nicht an meiner faulheit
Peter Dannegger schrieb:> Schau Dir also die ADC-Werte an, wenn man eine Taste drückt. D.h. wie> schnell erreichen sie den Endwert, wie weit zappeln sie und wie schnell> reagieren sie auf das Loslassen.
fast kein zappeln feststellbar.
um die Anstiegszeit bzw. Abfallzeit zu bestimmen ist das LCD zu
langsam..
Werde über eine Änderung des Layouts nachdenken....
Rick M. schrieb:> Hannes Lux schrieb:>> Winfried J. schrieb:>>> Ohne das floatende Signal auf der ADC Leitung zu beheben wird sich...>>>> ...keine Tastatur ordentlich abfragen lassen, egal ob mit meiner>> Methode, mit Winfrieds Methode, mit Peter Danneggers Methode oder wie>> auch immer.>> ich habe einen Pull down widerstand!!!
kein Grund zu schreien
Beitrag "Re: 5 Tasten am ADC"
Rick M. schrieb:> fast kein zappeln feststellbar.
Aus der Nase zieh: wie groß ist die Zahl "fast kein"?
2, 4, 10?
Rick M. schrieb:> um die Anstiegszeit bzw. Abfallzeit zu bestimmen ist das LCD zu> langsam..
Das LCD ist zumindest deutlich schneller, als Du es ablesen kannst.
Aber Du kannst ja mit der Entprellkonstante (z.B. 10ms) reihum die
letzten 20 Meßwerte speichern und dann mit der UART untereinander
ausgeben.
Das Speichern machst Du solange, bis der Wert sich nicht mehr größer
ändert, als das "fast kein zappeln" und vielleicht noch 5 Werte weiter.
Du kriegst also für jeden Tastendruck/loslassen 25 Werte im 10ms Raster
angezeigt.
Dann sollte gut zu erkennen sein, wie man das entprellen und auswerten
kann.
Peter
Rick M. schrieb:> ja, sorry...galt nicht Dir....war nur frustriert....
Schon gut und verständlich, aber bedenke niemand will dich hier ärgern.
Du must bewerten was dir weiter hilft jeder Andere kann nur Empfehlungen
geben. Und Peter ist hier sicher der Guru. Hans ist auch ein Erfahrener.
Ich habe lediglich mit dem Problem eigenständige Erfahrungen gesammelt,
welche ich Dir gern zur Verfügung stelle.
Schon auf Grund der Länge des Threads geht auch bei mir mal eine
Information unter zumal das Thema komplexer ist als man glaubt. Noch
dazu ist mein Experiment über 6 Jahre her ein wunder das ich alles
sochnell wieder fand.
Und dann gibt es ja noch allgemeine Kommunikationsunsicherheiten.
Also ist das Job oder Hobby?
Wo drückt der Schuh?
Namaste
Winfried J. schrieb:> Schon gut und verständlich, aber bedenke niemand will dich hier ärgern.
ja, dachte Hannes wollte mich nur verar...durch den Beitrag mit dem
Pull-Down-R, kenne die Menschen hier ja (noch) nicht ....und verstehe da
vielleicht beiläufige Kommentare vollkommen falsch...wie z.b.
Programmieren wie n Mädchen.....etc.
Winfried J. schrieb:> Ich habe lediglich mit dem Problem eigenständige Erfahrungen gesammelt,> welche ich Dir gern zur Verfügung stelle.
und darüber bin ich Dir, und auch jeden anderen, der mir helfen will,
sehr dankbar...
Winfried J. schrieb:> Schon auf Grund der Länge des Threads geht auch bei mir mal eine> Information unter zumal das Thema komplexer ist als man glaubt.
vollkommen verständlich.
Es ist ja auch nicht gerade sehr lustig, sich in einen so langen Beitrag
einzuarbeiten, nur um jemand anderen zu helfen. Du opferst ja hier Zeit
und Energie für andere...
Winfried J. schrieb:> Und dann gibt es ja noch allgemeine Kommunikationsunsicherheiten
Tja, die Sprache ist eben nur eine sehr unzulängliche
Kommunikations-Schnittstelle.....
Winfried J. schrieb:> Also ist das Job oder Hobby?> Wo drückt der Schuh?
Zum Glück nur Hobby, aber ich wollte mir aus gesundheitlichen Gründen
ein Gerät bauen und muß eben wieder einmal feststellen, daß ich einfach
viel zu blauäugig war, was die Umsetzung eines scheinbar einfachen
Problems mittels MC betrifft.
Also nochmal Danke für eure Zeit und Geduld!
Schönen Abend
Rick
Gern auch weiterhin.
Ich hatte etwas Luft, da Strohwitwer und auch sonst etwas Ruhe.
Ab morgen wird es wieder etwas turbulenter und ich werde etwas weniger
Zeit haben. Aber ich beantworte dir gern weiter fragen wenn ich das
vermag.
Also keine Sorge.
Namaste
Rick M. schrieb:> ja, dachte Hannes wollte mich nur verar...
Warum sollte ich das tun?
> durch den Beitrag mit dem> Pull-Down-R,
In Deinem Schaltbild im ersten Post ist der nicht drin.
Der Thread geht nun schon fast 2,5 Tage, ich habe die einzelnen Beiträge
zwar alle gelesen, aber nicht in einem Zuge, sondern so, wie sie
geschrieben wurden und ich Zeit fürs Forum hatte. Dazwischen habe ich
andere Dinge gemacht und auch andere Threads gelesen. So ist es völlig
normal, dass ich einige Details vergessen habe, so auch das Detail, dass
Du einen 100k-PullDown eingesetzt hast.
Wobei ich 100k für etwas hochohmig halte, die Sample&Hold-Stufe arbeitet
durch Umladung eines Kondensators auf die Spannung des Eingangspins. Und
dieses "Tor" ist nur sehr kurz offen. Siehe Diagramm im Kapitel ADC des
Datenblatts. Gut, der Tasten-Spannungsteiler ist niederohmig genug, aber
für das Erkennen der unbetätigten Tastatur halte ich 100k für
genzwertig.
...
Habe nochmal nachgeschaut ich bin sogar deutlich niederohmiger, fixer
Pullup 7,4 k
0<=Rt<=0.46k
Ich könnte bei meiner ca 160 Tasten an die Matrix hängen.
Allerdings würde ich dafür eher eine PS2 -Tastatur hernehmen.
Namaste
Hallo!
Hannes Lux schrieb:> Wobei ich 100k für etwas hochohmig halte, die Sample&Hold-Stufe arbeitet> durch Umladung eines Kondensators auf die Spannung des Eingangspins. Und> dieses "Tor" ist nur sehr kurz offen. Siehe Diagramm im Kapitel ADC des> Datenblatts. Gut, der Tasten-Spannungsteiler ist niederohmig genug, aber> für das Erkennen der unbetätigten Tastatur halte ich 100k für> genzwertig.
Hab nochmal im Datenblatt nachgelesen:
"The ADC is optimized for analog signals with an output impedance of
approx 10kOhm or less"
Hab mir das sogar mit Leuchtstift angestrichen, ist aber anscheinend
wieder in Vergessenheit geraten.
Werde den Pull-Down-R von 100k auf 10k verkleinern und alle ADC-Werte
neu berechnen und zusätzlich anzeigen lassen.
Gruß Rick
Rick M. schrieb:> Werde den Pull-Down-R von 100k auf 10k verkleinern
Dann liegen aber Deine Werte zu dicht beieinander. Mit um die 22 k bist
Du besser bedient.
Ich habe (als Ersatz eines Steuerknüppelpotis einer modernen
RC-Fernsteuerung) 19 Widerstände 510 Ohm in Reihe zwischen GND und +3,3V
und einen Widerstand 56 k als PullDown. Dies wird vom ADC des Mega8 des
Fernsteuersenders eingelesen. Die Auswertung der 17 Tasten erfolgt auf
der Empfängerseite anhand der Kanalimpulsbreite und ist fehlerfrei.
Rick M. schrieb:> with an output impedance of> approx 10kOhm or less
Richtig, das wäre "optimal". Ich bevorzuge auch 10 bis 20 k.
In meinem Fall des Funkfernsteuersenders hätte mir ein PullDown von 10
oder 20 k den Spannungsteiler zu sehr belastet, also die Linearität zu
sehr beeinträchtigt. Diese war mir aber wichtig, weil sie das Auswerten
der Tasten enorm erleichtert. Als Differenz zwischen unterer und oberer
Kanalimpulsbreite hat sich aufgrund des verwendeten Baudratenquarzes und
des Timer-Vorteilers ein Wert von 136 ergeben. Das macht bei 17 Tasten +
unbetätigten Tasten, also 18 "Stellungen" 8 Zahlenwerte von Taster zu
Taster. Also wurde zur Auswertung der ICP-Zahlenwert nach Abzug des
Offsets durch 8 geteilt und schon war ein Index für die Tasten-Nummer
ermittelt. Index und LUT deshalb, weil es mehr Freiheit beim Anordnen
der Taster und des Spannungsteilers bietet und damit die Platine
vereinfacht.
Manchmal sind eben 10 Zeilen Software billiger als eine unnötig
komplizierte Platine. Andererseits können ein paar Überlegungen zur
Hardware und deren Dimensionierung die Software stark vereinfachen.
...
Hallo!
Hannes Lux schrieb:> Rick M. schrieb:>> Werde den Pull-Down-R von 100k auf 10k verkleinern>> Dann liegen aber Deine Werte zu dicht beieinander. Mit um die 22 k bist> Du besser bedient.
Folgende Werte hab ich für einen 10k Pull-Down-R berechnet:
AREF=2,13V / U_teiler=4,93V
144
263
365
451
527
Bei AREF=AVCC=U_teiler=4,93V
62
114
158
195
228
Als zu eng empfind ich das jetzt nicht.....
Werd aber gerne auf Deine Empfehlung eingehen und einen 22k Pull-Down
nehmen.
Hannes Lux schrieb:> Also wurde zur Auswertung der ICP-Zahlenwert nach Abzug des> Offsets durch 8 geteilt und schon war ein Index für die Tasten-Nummer> ermittelt.
ICP-Zahlenwert?
Kann Dir da leider nicht ganz folgen..
Daß eine Linearität beim Spannungsteiler die Sache enorm erleichtert is
mir klar, denn dann kann man z.B. den Präprozessor rechnen lassen, so
wie es Peter immer gerne macht.
Is ja auch ne schlaue Sache, da eine Änderung der Hardware hierdurch
sehr leicht übertragen werden kann. Es müssen nur die Werte in der
Formel geändert werden, die Fenster oder Maschen für die Taster werden
automatisch berechnet.
MfG Rick
Rick M. schrieb:> Daß eine Linearität beim Spannungsteiler die Sache enorm erleichtert is> mir klar, denn dann kann man z.B. den Präprozessor rechnen lassen, so> wie es Peter immer gerne macht.
Meine Schaltung ist auch nichtlinear, der obere
Spannungsteilerwiderstand ist ja fest. Zu höheren Widerständen hin sinkt
der Spannungsunterschied zwischen 2 Tasten.
Wenn man das ohmsche Gesetz kennt, kann man jede beliebige
Widerstandsschaltung berechnen lassen.
Peter
Rick M. schrieb:> Hab nochmal im Datenblatt nachgelesen:> "The ADC is optimized for analog signals with an output impedance of> approx 10kOhm or less"
Das bezieht sich aber nur auf die Umladegeschwindigkeit der
Kondensatoren da drin.
Rein statisch ist der Eingangswiderstand ziemlich hochohmig. Lass
deine 100 kΩ Pulldown da drin. Dein eigentlicher Spannungsteiler ist
niedrig genug, und im Vergleich zur ADC-Geschwindigkeit bist du ja
sowieso schnarchlangsam.
Jörg Wunsch schrieb:> Das bezieht sich aber nur auf die Umladegeschwindigkeit der> Kondensatoren da drin.
Das Drücken und Loslassen der Taster ist ein dymamischer Vorgang
@Winfried
Winfried J. schrieb:>> uint16_t adc_alt = 1023;>> uint16_t adc_neu = 0;>>> //**** Aufruf im Main **************************************>>> adc_alt = adc_lesen(); // ADC lesen>>>> button = read_button( adc_alt); // Tastennummer auslesen,>>>> //*******************************************************************>>>>>> uint8_t read_button(uint16_t adc_alt)>> {>>>> if (adc_neu > adc_alt) // adc_alt = 1023!! Bedingung wahr>>>> adc_alt = adc_neu // gedrückte Taste wird vernichtet!>>>>>>>>
Bei diesem Code macht der Vergleich gar nichts.
adc_neu ist immer 0 und adc_alt der ADC-Wert von den Tasten
adc_neu kann nie größer adc_alt werden
.... nach meinem Verständnis muß ich vorher 2 ADC-Werte im Abstand von
8msec abfragen, anschl. das Unterprogramm 4 mal aufrufen, damit ich ne
gültige Tastennummer zurückbekomme. Das dauert dann minimum 32msec.
Ich steh da aufm Schlauch...Deinen Vergleich mit dem max-Init kapier ih
ned
Gruß Rick
Hallo, hier wird gross um die HW diskutiert, aber an der HW sehe ich
kein Fehler, sondern nur Verbesserungsvorschläge. Die 100kOhm sind im
gruenen Bereich oder möchtest Du deine Betriebsspannung gerne unnötig
belasten?
Die Entprellzeit bzw. deine Timerzeit ist ehrlich gesagt Murks. Wozu
fragst Du den Zustand alle 8ms ab, die Abfrage reicht alle 100ms locker!
Der Code im Thread ist nicht compilierbar, deshalb bitte den richtigen
Code hier posten.
Wieso benutzt Du den ADC nicht im continues read mode und holst Dir die
Werte nur zu den entsprechenden Zeiten ab?
Hier ein Pseudo C Code:
1
voidadc_init()
2
{
3
// ADC Kanal einstellen, prescaler und continues mode
4
}
5
6
voidtimer0_init()
7
{
8
//timer 0 prescaler und overflow betrieb
9
//30ms == overflow
10
}
11
12
isr(timer0_ovf)
13
{
14
timer_tick++// Systemtimer erhöhen
15
}
16
17
intmain(void)
18
{
19
volatileu8timer_tick=0;
20
volatileu8temp=0;
21
22
adc_init();//adc einrichten
23
timer0_init();// timer0 einrichten
24
sei();//golable interrupt flag aktiviert
25
26
u8adc_read()
27
{
28
returnadc_wert//
29
}
30
31
32
33
for();;
34
{
35
if(timer_tick)==3
36
{
37
adc_alt=adc_read()
38
}
39
40
iftimer_tick==6
41
adc_neu=adc_read()
42
if(adc_alt==adc_neu){
43
//wert mit LUT vergleichen und somit die gedrückte Taste auswerten
44
adc_alt=0;// alte werte löschen
45
adc_neu=0;
46
timer_tick=0;// zaehler löschen
47
}
48
}//
Ist kein Super Pseudo Code aber es beinhaltet die wichtigsten Sachen.
Dirk schrieb:> Hallo, hier wird gross um die HW diskutiert, aber an der HW sehe ich> kein Fehler, sondern nur Verbesserungsvorschläge. Die 100kOhm sind im> gruenen Bereich oder möchtest Du deine Betriebsspannung gerne unnötig> belasten?
Ich persönlich finde den Einwand, daß 100k zu hoch sind, für richtig.
Deshab verwende ich jetzt auch fix 22k als Pull-Down-R.
5V/22k ich glaub, daß wird der 7805er verkraften.
Dirk schrieb:> if (adc_alt == adc_neu)
Das kann alleine schon wegen des Pendelns der Werte bei gedückter Taste
nicht klappen.
Verglichen können hier höchstens die resultierenden Tastennummern nach
der LUT werden.
Gruß Rick
Rick M. schrieb:>> Das bezieht sich aber nur auf die Umladegeschwindigkeit der>> Kondensatoren da drin.>> Das Drücken und Loslassen der Taster ist ein dymamischer Vorgang
Ja. Alles außer Gleichspannung ist nach dieser Definition ein
dynamischer Vorgang. ;-)
Deine 8 ms sind saulahm im Vergleich zu dem, was der ADC an
Geschwindigkeit schaffen könnte. Folglich sind alle kritischen
Kondensatoren spätestens dann umgeladen, wenn du den das zweite Mal
abfragst.
Ich habe gerade den Kollektorwiderstand eines Fototransistors am
ADC-Eingang von 100 kΩ auf 2,2 MΩ vergrößert, weil er mir ansonsten
bei geringer Beleuchtungsstärke zu wenig Auflösung gebracht hat.
Abgefragt wird im Sekundentakt, und eine Änderung von ganz hell auf
ganz dunkel (bei der die 2,2 MΩ ja die Kondensatoren auf Vcc umladen
müssen) ist trotzdem stets mit der nächsten Sekunde erkannt und die
Reaktion (Dimmen der LEDs) erfolgt.
Interessanter Nebeneffekt dabei: anfangs hatte ich versehentlich noch
ADATE aktiv (von vorangegangenen Versuchen), sodass der ADC im freerunning mode lief. Da hat der Sprung von ganz hell nach ganz dunkel
noch ca. 2 s benötigt. Liegt offenbar daran, dass die S&H-Schaltung
in diesem Falle jeweils nur kurz sampelt, dabei entlädt sie die
Eingangs- und Schaltungskapazität, weil die 2,2 MΩ nicht so schnell
nachladen können. Nachdem ich das ADATE rausgenommen habe (und damit
die S&H-Schaltung sehr viel länger am Eingang klemmt), war dieser
Effekt jedoch verschwunden.
Rick M. schrieb:> Dirk schrieb:>> Hallo, hier wird gross um die HW diskutiert, aber an der HW sehe ich>> kein Fehler, sondern nur Verbesserungsvorschläge. Die 100kOhm sind im>> gruenen Bereich oder möchtest Du deine Betriebsspannung gerne unnötig>> belasten?
Der Spannungsteiler (10k, mehrere 1k) liegt ständig an der
Betriebsspannung, belastet die Betriebsspannung also ständig. Die 100k
bzw. 22k wirken nur bei gedrückter Taste.
>> Ich persönlich finde den Einwand, daß 100k zu hoch sind, für richtig.
Ich inzwischen nicht mehr, ich war da zu voreilig. Denn es geht auch
ganz gut ohne PullDown.
Der (vorgegebene) Spannungsteiler berücksichtigt die externe
ADC-Referenz von etwa 2V, deshalb mehrmals 1k auf der GND-Seite und 10k
auf der Plus-Seite. Nachteil: Bei sich ändernder Betriebsspannung misst
das Ding falsch, da die Referenz konstanz bleibt. Es ist also keine
radiometrische Messung. Das ist aber nicht das, worauf ich hinaus will,
denn bei 5 Werten ist der Abstand immernoch groß genug...
Alles oberhalb der ADC-Referenz wird als "Voll Haus" gemessen, also als
255 (8 Bit) bzw. 1023 (10 Bit). Somit reicht es aus, den internen PullUp
einzuschalten, wenn die Tastatur gemessen wird. Und natürlich wieder
aus, wenn andere Kanäle gemessen werden. Der interne PullUp ist zwar
recht ungenau (Exemplarstreuungen), aber doch um Einiges hochohmiger als
der verwendete Spannungsteiler, verfälscht die Werte also nur
unwesentlich. Und er "zieht" den Pegel nicht nur nach AREF, sondern nach
Vcc, hat also AREF bei offenen Tastern schnell überschritten. Somit hast
Du für unbetätigte Taster immer den Maximalwert (also kein Fenster), was
als Kriterium genutzt werden kann, ob keine Taste gedrückt ist, also
darüber entscheidet, ob Du den ADC überhaupt auf die Fenster der
einzelnen Tasten prüfen musst.
> Deshab verwende ich jetzt auch fix 22k als Pull-Down-R.> 5V/22k ich glaub, daß wird der 7805er verkraften.
Wie ich bereits schrieb, wirkt der PullDown nur bei gedrücktem Taster.
Die 15k des Spannungsteilers wirken immer, aber auch die verkraftet der
7805.
>> Dirk schrieb:>> if (adc_alt == adc_neu)>> Das kann alleine schon wegen des Pendelns der Werte bei gedückter Taste> nicht klappen.> Verglichen können hier höchstens die resultierenden Tastennummern nach> der LUT werden.
Richtig, wobei LUT erst bei mehr Tasten sinnvoll wird, Deine 5 Tasten
kannst Du mittels IF oder Switch selektieren.
>> Gruß Rick
...
Jörg Wunsch schrieb:> Nachdem ich das ADATE rausgenommen habe (und damit> die S&H-Schaltung sehr viel länger am Eingang klemmt), war dieser> Effekt jedoch verschwunden.
Danke...
...
Hi
> Liegt offenbar daran, dass die S&H-Schaltung>in diesem Falle jeweils nur kurz sampelt, dabei entlädt sie die>Eingangs- und Schaltungskapazität, weil die 2,2 MΩ nicht so schnell>nachladen können. Nachdem ich das ADATE rausgenommen habe (und damit>die S&H-Schaltung sehr viel länger am Eingang klemmt), war dieser>Effekt jedoch verschwunden.
Die Länge der Sample-Phase hängt nur vom ADC-Clock ab. Daran ändert
auch der Free-Running-Mode nichts.
MfG Spess
spess53 schrieb:> Die Länge der Sample-Phase hängt nur vom ADC-Clock ab. Daran ändert> auch der Free-Running-Mode nichts.
Um die reine Sample-Phase geht es aber nicht, sondern darum, wie
lange die S&H-Kondensatoren bereits am Eingang klemmen. Das tun
sie ganz offenbar auch bereits vor dem Sampeln, anders ließe sich
der Unterschied zwischen free running mode und explizitem Triggern
einmal pro Sekunde nicht erklären.
Wirklich detailliert beschrieben ist das im Datenblatt ohnehin alles
nicht.
Hallo!
Jörg Wunsch schrieb:> Deine 8 ms sind saulahm im Vergleich zu dem, was der ADC an> Geschwindigkeit schaffen könnte. Folglich sind alle kritischen> Kondensatoren spätestens dann umgeladen, wenn du den das zweite Mal> abfragst.
Ich glaubte, daß der Kondensator immer nur ganz kurz an der Mess-Spg.
"anliegt", auch wenn der Kanalwechsel sehr langsam erfolgt (8msec) und
der ADC im single-shot-Modus läuft.
Deinen Schilderungen entnehme ich, daß dies nicht der Fall ist und der
S&H Kondensator bei Single-Shot so lange an der Mess-Spg. aniegt bis ein
anderer Kanal eingestellt wird.
Dann sind die 100k problemlos...
Jörg Wunsch schrieb:> Interessanter Nebeneffekt dabei: anfangs hatte ich versehentlich noch> ADATE aktiv (von vorangegangenen Versuchen), sodass der ADC im free> running mode lief. Da hat der Sprung von ganz hell nach ganz dunkel> noch ca. 2 s benötigt. Liegt offenbar daran, dass die S&H-Schaltung> in diesem Falle jeweils nur kurz sampelt, dabei entlädt sie die> Eingangs- und Schaltungskapazität, weil die 2,2 MΩ nicht so schnell> nachladen können. Nachdem ich das ADATE rausgenommen habe (und damit> die S&H-Schaltung sehr viel länger am Eingang klemmt), war dieser> Effekt jedoch verschwunden.
Also im free-running-Modus liegt der Kondensator nur kurz an der
Mess-Spg.
Hannes Lux schrieb:> Nachteil: Bei sich ändernder Betriebsspannung misst> das Ding falsch, da die Referenz konstanz bleibt.
Nein, da bei meinem Board AREF über einen Spannungsteiler aus der
Betriebsspg. erstellt wird. Somit ändert sich auch AREF mit der
Betriebsspg.
spess53 schrieb:> Die Länge der Sample-Phase hängt nur vom ADC-Clock ab. Daran ändert> auch der Free-Running-Mode nichts.
??
Gruß Rick
Hatte ich schon erwähnt, daß man sich die ADC-Werte einfach mal ausgeben
lassen sollte?
Und danach kann man sich zusätzlich die Bewertung anzeigen, ob die
Bewertungslogik (if, switch oder LUT) funktioniert.
Erst dann kanns ans Entprellen gehen.
Einfach nur einen Schritt nach dem anderen machen und nicht alles
gleichzeitig.
Peter
Peter Dannegger schrieb:> Hatte ich schon erwähnt, daß man sich die ADC-Werte einfach mal ausgeben> lassen sollte?
ja, mach ich auch..
Hab momentan folgendes Problem:
Ich versuche die Tastenerkennung nach dem Schema von Hannes hin zu
bekommen.
Hab folgende Files:
ADC.h
ADC.c ........... ADC ISR
Timer1.h
Timer1.c ....... Timer1 ISR
KoSi_Gen.h ........beinhaltet Unterprogramme für Main
KoSi_Gen.c ........beinhaltet Main
Die Variable adc_value_number benutze ich in der Timer1-ISR und ist in
der Timer1.h deklariert.
Aber diese Variable benutz ich auch in der ADC-ISR.
Nun schreibt mir der Compiler, daß die Variable in ADC.c nicht definiert
wurde, klar ist ja auch in Timer1.h definiert.
Wenn ich jetzt aber in der ADC.c nicht nur ADC.h sonder auch Timer1.h
einbinde, hab ich wieder multible definitionen der Variable
"adc_value_number"
Wie lös ich dieses Problem?
Hallo!
Hab bis jetzt folgendes umsetzen können:
Einfachster Versuchsaufbau: kein Kanalwechsel, Single-Shot
In der Timer1-ISR wird alle 4msec eine ADC-Wandlung angestoßen.
Eine globale Variable hilft mir das 1. und das 2te Wandlungsergebnis in
der ADC-ISR auseinander halten zu können.
In der ADC-ISR werden 2 aufeinander folgende Tasten-Nummern miteinander
verglichen und bei Gleichheit beginnt ein Prellzähler zu zählen.
Sobald die Taste wieder losgelassen wird, also der 1. der beiden
Messwerte wieder null wird und der Prellzähler die Minimalschwelle
überschritten hat, wird der Tastendruck als gülig gewertet und dem
Hauptprogramm übergeben.
Folgendes wird am LCD angezeigt:
Erkannte Taste
momentaner ADC-Wert
momentaner Wert des Prellzählers
ADC-Werte der Tasten (berechnet/angezeigt) bei
****AREF = AVCC = U_teiler = 4,93V****
**Pull-Down-R = 22k**
T5: 65/64
T4: 125/125
T3: 180/183
T2: 231/239
T1: 278/294
Wobei sich das Pendeln der Werte lt. LCD auf die Einerstelle begrenzt,
also kleiner 10 ist.
Komischerweise driften die höheren Werte zw. Berechnung und gemessen
immer mehr auseinander.
Wenn AREF wieder auf 2,13V reduziert wird, verdoppelt sich dieser Effekt
sogar.
Wenn ich eine der Tasten betätige kann ich mir schön ansehen, wie der
Prellzähler hochläuft. Somit funktioniert die LUT für alle Tasten.
Auch der Überlaufschutz des Zählers funktioniert.
Leider wird der Tastendruck immer noch nicht 100% verlässlich erkannt.
Ein weiteres Mysterium ist das Verhalten der LED an PC7, welche
eigentlich im Sekundentakt an und wieder aus gehen soll. (Sekundentakt
wird von der Timer1-ISR erzeugt).
Die LED geht für mehrere Takte nicht mehr vollständig aus, sondern
reduziert die Helligkeit nur um die Hälfte. Dann funktioniert sie für
ein paar Takte wieder normal und das Spiel beginnt von vorne.
Da die Ausgangspegel ja nur Low oder High sein können, würde dies
bedeuten, daß der Ausgang schwingt. Wieso weiß ich aber nicht da ich die
LED bzw. den Ausgang nur toggle.
1
if(second_puls==1)// toggle LED7
2
PORTC^=(1<<PC7);
Ich hab mal den gesamten Code angehängt und alles überflüssige gelöscht,
damits übersichtlicher wird.
Gruß Rick
Hallo !
Hab jetzt endlich geschafft, meine Tasten anständig auszulesen.
Kann mir jemand erklären warum diese Anweisung nicht funktioniert:
1
if(second_puls==1)// LED7 als Sekundenanzeige
2
PORTC^=(1<<PC7);
aber diese Anweisung, um die LED blinken zu lassen:
1
if(second_puls==1)// LED7 als Sekundenanzeige
2
PORTC|=(1<<PC7);
3
4
if(second_puls==0)
5
PORTC&=~(1<<PC7);
Beim Togglen erlischt die LED nicht immer vollständig, sondern leuchtet
nur mit halber stärke weiter, was auf ein schwingen des Ausgangs
hinweist.
Der Grund, warum bisher die Tasten nicht korrekt ausgelesen werden
konnten, ist, daß das Sichern der gedrückten Taste früher erfolgen
mußte. Momentan erledige ich das mit einer zusätzlichen Variable
temp_button.
Gruß Rick
Rick M. schrieb:> was auf ein schwingen des Ausgangs> hinweist.
Richtig, denn Du toggelst PC7 bei jedem Hauptschleifendurchlauf, solange
second_puls 1 ist. Da fehlt eine Flankenerkennung.
...
Hallo!
Hannes Lux schrieb:> Da fehlt eine Flankenerkennung.
Danke, war ein Denkfehler.
Könnte mir bitte jemand erklären, warum ich hier eine mehrfache
Definition von "adc_channel" habe:
1
uint16_tvolatileadc_value[ADC_INDEX_MAX];// Feld für die Wandlungsergebnisse des ADC = ADC-Ergebnis-Speicher
2
uint8_tvolatileadc_channel[]={7,7};// Kanalabfolge für das Auslesen der ADC-Werte
3
uint8_tvolatileadc_index;// Index für Kanalwahl und ADC-Speicher
adc_channel wir nur mehr in der Fkt. "adc_init" und in der "adc-ISR"
verwendet:
"adc_init"
Hallo!
Meine Tastenerkennung funktioniert jetzt ganz gut.
Momentan wird vom meinem Timer1-ISR alle 4msec eine Wandlung angestoßen.
Möchte ich jedoch meine Wandlungsfrequenz erhöhen, also die nächste
Wandlung am Ende meiner ADC-ISR anstoßen, weil ich mehrere Messkanäle
abarbeiten möchte, so funktioniert meine Tastenerkennung auf einmal
nicht mehr.
Der Prellzähler zählt tadellos hinauf (Anzeige am LCD), auch der
ADC-Wert stimmt (Anzeige per LCD), die Tasten werden jedoch anscheinend
nicht mehr richtig ausgewertet.
Hat da vielleicht jemand von euch ne Idee?
Ich hab mal meinen Code angehängt, die Tastenerkennung befindet sich in
der Datei "adc.c"
Grüße Rick
Hallo!
Ich konnte den Fehler bis zur Übergabe der Tasten-Nummer zum
Hauptprogramm eingrenzen.
Wenn ich Taste-5 drücke so erhalten die Variablen button_1, button_2 und
temp_button den Wert 5 und der Prell-Zähler zählt hoch.
Beim Loslassen der Taste wird die Tastennummer (Variable button) aber
anscheinend dem Hauptprogramm nicht richtig übergeben.
Wenn ich eine Wandlung nur alle 4msec aus der Timer1-ISR anstoße
funktionierts, wenn ich die nächste Wandlung gleich in der ADC-ISR
anstoße nicht?
Ich komme einfach nicht auf den Fehler.
Meine ADC-ISR
funktioniert die Tastenerkennung wieder, was darauf schließen läßt, daß
das Loslassen der Taste nicht mehr richtig erkannt wird.
Ich habe bereits versucht die Weitergabe der erkannten Taste erst zu
machen , wenn button_1 == button_2 == 0 ist. Es findet zwar eine
Verbesserung statt, (es funktioniert sporadisch) aber eine sichere
Erkennung ist so auch nicht möglich.
Warum das so ist, verstehe ich allerdings nicht.
Könnte mir hier bitte wer weiterhelfen.
Gruß Rick