Hi,
der Titel sagt es eigentlich schon, ich wollte mal schauen, wie sich die
Auswertung eines 4-Wire-Touchpanels ohne irgendwelche Hilsmittel direkt
am AVR macht. Also:
PA0/ADC0 -> x1
PA1/ADC1 -> x2
PA2/ADC2 -> y1
PA3/ADC3 -> y2
Mir ist nicht 100% klar, wie man zur Abfrage nun die Ports schaltet, da
es an irgend einem Punkt zu kurzschlüssen kommen kann. Finde aber den
Beitrag dazu nicht mehr. Der Ansatz
PA2/ADC2 sowie PA3/ADC3 als Eingang ohne Pullup, einen zum Messen des
Wertes verwenden
PA0/ADC0 als Ausgang logisch 1
PA1/ADC1 als Ausgang logisch 0
Achsentausch:
PA0/ADC0 sowie PA1/ADC2 als Eingang ohne Pullup, einen zum Messen des
Wertes verwenden
PA2/ADC3 als Ausgang logisch 1
PA3/ADC3 als Ausgang logisch 0
natürlich muss zusätzlich noch bei Pinfunktionswechsel darauf geachtet
werden, dass man nicht plötzlich durch den vorher gesetzten Ausgang auf
logisch 1 man plötzlich beim Input den Pullup aktiviert hat.
Funktioniert das so ?
Wo ist der kritische Punkt an dem ein Kurzschluss entstehen kann ? War
damit eventuell gemeint, dass man unachtsamerweise an einer Stelle z.B.
versehentlich x1 auf logisch 1 und zugleich y2 auf logisch 0 ziehen
könnte, deren Kontaktstellen an einem Punkt nahezu aneinander grenzen ?
Mh, die Beschreibung sagt mir leider nichts dazu, wie die Ports zu
schalten sind, zudem bringt sie einen neuen Aspekt in´s Spiel: nämlich
die Erkennung eines Druck bevor überhaupt eine Position eingelesen wird.
Kleine Vorteile mag das ja haben, der große Sinn bleibt mir allerdings
verborgen.
Hatte ja selber schon mal ein 4-Wire-Touchpanel ausgewertet, da
allerdings mit Transistoren geabeitet, die x2 oder y2 gegen Masse
schalten. Also eine vorherige Toucherkennung war dabei nicht nötig
sondern er wurden einfach kontinuierliche AD-Wandlungen durchgeführt und
mit den Daten weitergeabeitet.
Weicht aber vom Thema ab, primär geht es immer noch darum, wie die Ports
zu schalten sind und auf was man unbedingt achten sollte.
Guck mal Seite 4 in dem Dokument von Atmel zu Touchscreens.
Die Tabelle die ich als Bild angehängt habe steht da auch.
Das sollte deine Frage klären.
Der Interrupt wird benutzt um nicht ständig den ADC laufen zulassen,
bzw. den Controller schlafen zu legen solange das Display nicht benutzt
wird.
Hallo, ich habe eben den Code von Rene ausprobiert, bekomme leider nur
Zufallszahlen, zwar im definierten Bereich (128*64, Größe des
Touchscreens) und es scheint auch so, dass es auf Touchs reagiert, aber
die Zahlen sind total wild, wenn man nichts anfasst kommt z.B. für x 121
und gleich dahinter 22 :(
Woran kann das liegen? den Code habe ich nur minimal an meinen ATMega32
angepasst. Gebe die Werte per USART an meinen Notebooke.
nach 30min stelle ich fest, dass die Koordinaten richtig erkannt werden,
nur im Ruhemodus, wo eigentlich nichts erkannt werden soll, wird wild
weiter gemessen....
Hat jemand eine Idee??
Ausserdem funzt das besser, wenn man durch Selbstkalibrierung den nicht
immer vernachlässigbaren stark temperatur- und
betriebsspannungsabhängigen Innenwiderstand der Porttreiber rausrechnet.
Immerhin fliesst bei solchen Touchpanels mitunter deutlich Strom.
Das geht recht einfach, denn netterweise kann man bei AVRs die Spannung
eines als Ausgang konfigurierten Pins messen. Ergibt zwar 6 Messungen
statt 2, aber klappt recht gut.
Innenwiderstand der Porttreiber war die Ursache, vielen Dank an A. K.!
Ich habe den Code von Rene einfach um eine Zeile erweitert und schon
läuft die Messung, wie geschmiert.
Durch den Pullup Widerstand im Ruhezustand wird nun immer ~1024 gemessen
und somit ergibt sich ungültige Messung.
1
uint8_tlese_touch(uint8_t*x,uint8_t*y){
2
uint8_tdaten=gueltig;
3
DDRA|=((1<<PA0)|(1<<PA1));// Top (PA0) und Button (PA1) Ausgang
4
PORTA|=(1<<PA0);// Top (PA0) +3,3V
5
PORTA&=~(1<<PA1);// Button (PA1) 0V
6
7
PORTA=(1<<PA2)|(1<<PA3);// für Left und Right Pullups einschalten
8
9
_delay_ms(10);// warten
10
ADMUX=((1<<REFS0)+2);// ADC Kanal 2 (PA2 Left) auswaehlen
11
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung
12
while(ADCSRA&(1<<ADSC)){;}// auf Abschluss der Konvertierung warten
13
uint16_tUy=ADCW;// Ergebniss nach Uy
14
PORTA&=~(1<<PA0);// Top (PA0) 0V
15
DDRA&=~((1<<PA0)|(1<<PA1));// Top (PA0) und Button (PA1) Eingang
Hallo,
ich habe ein ähnliches Problem.
Bleiben die Touchpanel Pärchen Anschlüsse des jeweiligen ADC High-Z,
dann springen die Werte des ADC wie wild, sofern man das Display nicht
berührt.
So sollte es ja laut den Specs aber ja gemacht werden (Atmel oder auch
die TouchSreen Controller wie XPT2046 oder ADS7843).
Ein wenig Abhilfe habe ich auch bekommen, wenn wie beim Posting hier
vor, bei den ADC Pärchen bei der Messung Anstelle High-Z beide Pullup´s
einschalte.
Manchmal bekomme ich 03FF zurück (wäre ja ok). Aber manchmal gehen die
Werte auch bis 03B0 herunter. (ATmega32 ADC=0-1023 = 03FF Hex)
Den ADC 2x hintereinanderlesen bringt auch nichts.
Bei gewolltem "Touch" an irgendeiner Stelle, sind die ADC Werte auf den
ersten Blick ok.
Was kann ich noch tun?
Danke schon mal für hoffentlich konstruktive Vorschläge - auch wenn es
warm draußen ist. Herbert
(das ist Pascal, Anschlüsse wie 1. Posting)
Touch_X_Plus_Direction := Direction_Eingang;
Touch_X_Minus_Direction := Direction_Eingang;
Touch_Y_Plus_Direction := Direction_Ausgang;
Touch_Y_Minus_Direction := Direction_Ausgang;
// Touch_X_Plus_Output := wenn_Input_High_Z;
Touch_X_Plus_Output := wenn_Input_Pull_Up_Ein; // TEST
// Touch_X_Minus_Output := wenn_Input_High_Z;
Touch_X_Minus_Output := wenn_Input_Pull_Up_Ein; // TEST
Touch_Y_Plus_Output := 0;
Touch_Y_Minus_Output := 1;
// Touchpanel_Delay_20ms;
// Touch_ADC_Y := ADC_Read(Touch_X_Minus_ADC);
Touchpanel_Delay_20ms;
Touch_ADC_Y := ADC_Read(Touch_X_Minus_ADC);
> ich habe ein ähnliches Problem.> Bleiben die Touchpanel Pärchen Anschlüsse des jeweiligen ADC High-Z,> dann springen die Werte des ADC wie wild, sofern man das Display nicht> berührt.
Das ist normal, da die Eingänge undefiniert sind.
Wenn nicht gedrückt wird, sollte der ADC gar nicht in Betrieb sein. Erst
nachdem ein Drücken erkannt wurde, wird der ADC in der Software
aktiviert und dann in 2 Schritten die X und Y-Position per ADC gemessen.
Beitrag "Re: 4Draht-Touchpanel direkt am AVR und die Portschaltung"
Thomas
Hallo,
wie soll ich denn das Drücken erkennen, ohne das der ADC mißt?
Ich habe keinen ATmega88, der Level Interrupts kann, sondern einem
ATmega32.
Ich überlege ja schon die ganze Zeit. Allerdings fällt mir nichts ein.
Viele Grüße Herbert
du legst die X-Achse an Masse (einen oder auch beide Anschllüsse), an
der Y-Achse lässt du einen auf Eingang ohne Pullup und den anderen auf
Eingang mit PullUp. Diesen letzten überwachst du per PinChangeInt oder
auch per polling - im Ruhezustand liegt der auf High (pullup) Touch'st
du geht er auf Low.
Sascha
> Ich habe keinen ATmega88, der Level Interrupts kann, sondern einem> ATmega32.
Macht nix. Schalte die vier Leitungen wie in der Tabelle.
Ich mache es so:
Beide X-Leitungen als Ausgang und Low.
Beide Y-Leitungen als Eingang.
Bei einer Y-Leitung den internen Pull-up einschalten.
In einem Timer-Interrupt wird die Y-Leitung mit Pull-up abgefragt. Im
Standby ist diese High wegen dem Pull-up.
Wenn das Touch nun gedrückt wird, ziehen die beiden X-Leitungen diese
auf Low. Das ist das Startkriterium für die folgenden Positionsabfragen
nach Zeile zwei und drei in der Tabelle.
Thomas
PinChangeInt kann aber der ATmega32 nicht an jedem Port Pin oder?
Ich müßte dafür einen der beiden X/Y Pins, den ich nicht für den ADC
benötige, auf External Int 0,1,2 umlegen, falls ich das per Interrupt
machen will oder?
Herbert
Dieser Beitrag hatte sich mit dem von Thomas beim Tippen überschnitten.
Werde mir das mal durch den Kopf gehen lassen.
Danke!
> Bitte um Entschuldigung, falls es im C Code oben schon so> steht.
Keine Ahnung, hab ihn nicht gelesen, da ich auch kein c kann. ;-)
Naja, lesen schon, aber nicht schreiben. Daher habe ich meine
Touch-Abfrage nach dem Atmel-Datenblatt dann in ASM selbst geschrieben.
Thomas
@ferdi
Danke für den Hinweis. Den Artikel kannte ich bereits. Nur bei meinem
Problem hilft der nicht. Der berücksichtigt in keiner Weise ein "Touch"
oder auch nur ein Calibrieren. Da bin ich schon wesentlich weiter.
Trotzdem auch an Dich ein Danke!
Für Wakeup ohne PCINT muss man eben einen der 4 Anschlüsse zusätzlich an
einen Interrupt-Eingang anschliessen und verliert einen Pin. Das war's
aber auch schon.
Code mit Autokalibrierung hatte ich oben bereits gepostet.
@Thomas Forster (igel)
Hallo Thomas,
"Beide X-Leitungen als Ausgang und Low.
Beide Y-Leitungen als Eingang.
Bei einer Y-Leitung den internen Pull-up einschalten. ..."
Ich habe das eben noch in der Art eingebaut (als Poll). Funktioniert
prima! Danke! Manchmal sieht man den Wald vor lauter Bäumen nicht.
"In ASM programmiert..." -> Hut ab! Das mache ich nur im Notfall.
Viele Grüße an alle und ein schönes Wochenende wünscht Euch Herbert
Einerseits steckt da die Display-Grösse drin, d.h. wenn das Display
128x128 statt 128x64 hat, dann ändert sich die Rechung. Diese Änderung
hast du nur teilweise nachvollzogen, eine nun falsche 64 steckt bei dir
noch drin.
Andererseits hat er darin möglicherweise den oben erwähnten
Spannungsabfall durch die Porttreiber (oder externe Widerstände?) sehr
grob über den Daumen gepeilt und direkt ins Programm eingetragen.
A. K. schrieb:> Andererseits hat er darin möglicherweise den oben erwähnten> Spannungsabfall durch die Porttreiber (oder externe Widerstände?) sehr> grob über den Daumen gepeilt und direkt ins Programm eingetragen.
Also dem nach liegt die max. Spannung nur noch bei 4.4V (ADC: 900) ?
könnte es dann auch so berechnet werden?
Neuling schrieb:> Also dem nach liegt die max. Spannung nur noch bei 4.4V (ADC: 900) ?
Woher soll ich das wissen? Das hängt vom Touchpad, der Temperatur des
AVR und von der Zeit ab, denn der Port erwärmt sich mit der Zeit durch
den ggf. recht hohen Strom und verändert dadurch seinen Innenwiderstand.
Daher habe ich das selbstkalibierend implementiert, siehe oben.