Hallo zusamnmen,
ich habe ein TFT-Display mit (resistiver) Touchfunktion wie dieses bei
ebay Art. Nr. 221075052240, 320 x 240 Pixel, das ich an einer Arduino
Mega Hardware betreibe.
Das funzt auch alles ganz wunderbar, mit Ausnahme der Touch-Auswertung.
Während die X-Achse (schmale Seite des Display) einen korrekten Wert
(0...255) liefert, ist das in der Y-Achse (lange Seite) nicht der Fall.
Zunächst werden 255...0 korrekt ausgegeben, bei 0 ist jedoch nicht
y-Pixel 320 sondern erst Pixel-Nr. 240 erreicht. Das wäre ja bei einem
quadratischen Display mit 240 xx 240 Pixel auch richtig, aber hier
fehlen noch 80 Pixel in Y-Richtung.
Gehe ich nun weiter in Y-Richtung, dann springt die Ausgabe wieder auf
einen Startwert (nicht exact reproduzierbar), um dann weiter wieder auf
0 zu gehen, und das 2..3 Mal auf der restlichen 80-Pixel Strecke.
Dies sollte bei einem resistiven Touchpanel insb im Differenzmode doch
nicht der Fall sein? Oder ist das TFT exotisch verkabelt und die
Ansteuerung des Touchcontrollers muß "exotisiert" sein?
Ach ja, ich habe drei dieser Displays von unterschiedl. Lieferanten und
Herstellern, alle zeigen das gleiche Verhalten. Touch-Controller ist der
XPT2046 bzw. der ADS7843. Angesteuert wird über die
Arduino-SPI-Schnittstelle. Der Atmel wird mit 16 MHZ getaktet,
SPCR = 0b01010011; // durch 128 -> 125 khz bei 16 mhz MAXWERT fur TOUCH
SPSR = 0b00000000;
Der Touchcontroller läuft im 8-bit Mode (12 bit Mode macht keinen
Unterschied.) Start des Controller mit:
WriteCharTo7843(0x98); //y-Achse
bzw.
WriteCharTo7843(0xD8);
Please help... Wer hat eine Idee? Danke.
Düsendieb schrieb:> Hast Du diese Libary im Einsatz?>> http://henningkarlsen.com/electronics/library.php?id=52>> Da muss das Display kalibriert werden
Nein, habe ich nicht. Nur um ein paar bytes per SPI zu übertragen ist
hier eine Lib auch nicht notwendig.
Ebenso ist eine Kalibrierung der Display-Touchfunktion zum jetztigen
Zeitpunkt nicht möglich, da die Positionsausgabe der y-Position über die
Länge gesehen nicht stetig ist und Sprünge aufweist.
Tassilo H. schrieb:> Vor langer Zeit habe ich mal das hier geschrieben um einen solchen> Touchcontroller auszulesen:>>
1
>
2
>//Do data conversion for X, Y
3
>// controller clock rate is 16MHz, each cycle takes 62ns to finish
4
>voidtpReadXY()
5
>{
6
>uint8_tdl,dh;
7
>// set CS=0
8
>TPPORT&=~(_BV(TPCS));
9
>// read X channel
10
>tpTransmitByte(0x90);
11
>dh=tpTransmitByte(0x00);
12
>dl=tpTransmitByte(0xD0);// prepare for Y conversion
13
>// combine into x value
14
>tpXData=(uint16_t)((dh<<5)|(dl>>3));
15
>dh=tpTransmitByte(0x00);
16
>dl=tpTransmitByte(0x00);
17
>tpYData=(uint16_t)((dh<<5)|(dl>>3));
18
>// set CS=1
19
>TPPORT|=_BV(TPCS);
20
>}
21
>
Meine Methode sieht funktional identisch aus:
(bei mir sind x und y vertauscht)
(Beipiel für x-pos)
1
U16GetXposFromTouch(void)// 16bit
2
{
3
U16pos;
4
init_spi_TOUCH();
5
TOUCH_PORT&=~TOUCH_CS_PIN;//SS auf LO
6
WriteCharTo7843(0xD0);
7
pos=((U16)ReadCharFrom7843())<<4;
8
pos|=((U16)ReadCharFrom7843())>>4;
9
10
TOUCH_PORT|=TOUCH_CS_PIN;//SS auf HI
11
returnpos;
12
}
ReadCharFrom7843 überträgt dabei0x00 zum Controller.
Diese meine Version erzeugt den 12 Bit Wert. Mein Eingangsposting
bezieht sich auch die 8-bit Version bzw. auf die oberen 8 bits des 12
Bit Ergebnisses.
Vielleicht ist mein Problembeschreibung etwas untergegangen.
Mein Problem ist nicht die prinzipielle Ansteuerung des Touch
Controllers, sondern das dubiose Ergebnis des Y-Wertes ("Meine"
Y-Richtung des Displays ist größer als die X-Richtung. X: 240 pix; y:
320 Pix)
Also die Größe oder Pixelzahl des Displays spielt keine Rolle. Der
Touchscreen ist einfach ein Spannungsteiler. Entweder die beiden X- oder
die beiden Y-Anschlüsse werden an GND bzw VCC gelegt. Am "Berührpunkt"
entsteht ein Abgriff, der dann über eine der anderen beiden Anschlüsse
(welcher ist egal) ausgelesen wird. Über die Displaybreite oder
Displayhöhe gibt es dann immer (fast) den ganzen Wertebereich des
A/D-Wandlers.
Ist Dir aufgefallen, daß Du in deinem Code um vier Bits nach links oder
rechts schiebst:
1
pos=((U16)ReadCharFrom7843())<<4;
2
pos|=((U16)ReadCharFrom7843())>>4;
Das ist nicht richtig so, der Tochcontroller spuckt das Ergebnis so aus,
daß im ersten Byte das MSB und im zweiten Byte die drei LSB 0 sind, also
erstes Byte um 5 nach links und zweites Byte um 3 nach rechts schieben
für eine 12-bit Wandlung.
Ach ja: 8-Bit Wandlung brauch man eigentlich nicht. Das Timing sieht
quasi genauso aus, das Ergebnis ist genauso in den übertragenen Bytes
verteilt, aber man ist 4 bits eher fertig, d.h. man könnte den zweiten
Transfer nach 4 clocks abbrechen. Mit einem 8-bit SPI-Interface geht das
eh' nicht, es sei denn man überlappt die X- und Y-Wandlung geschickt.
Tassilo H. schrieb:> Also die Größe oder Pixelzahl des Displays spielt keine Rolle. Der> Touchscreen ist einfach ein Spannungsteiler. Entweder die beiden X- oder> die beiden Y-Anschlüsse werden an GND bzw VCC gelegt. Am "Berührpunkt"> entsteht ein Abgriff, der dann über eine der anderen beiden Anschlüsse> (welcher ist egal) ausgelesen wird. Über die Displaybreite oder> Displayhöhe gibt es dann immer (fast) den ganzen Wertebereich des> A/D-Wandlers.
Das ist mir alles klar. Auch, daß der "lange" y-Bereich damit den
"vollen" Wertebreich umfassen müßte. Nur, das tut er nicht. Und das
ist mein Problem.
>> Ist Dir aufgefallen, daß Du in deinem Code um vier Bits nach links oder> rechts schiebst:>
1
>pos=((U16)ReadCharFrom7843())<<4;
2
>pos|=((U16)ReadCharFrom7843())>>4;
3
>
>> Das ist nicht richtig so, der Tochcontroller spuckt das Ergebnis so aus,> daß im ersten Byte das MSB und im zweiten Byte die drei LSB 0 sind, also> erstes Byte um 5 nach links und zweites Byte um 3 nach rechts schieben> für eine 12-bit Wandlung.
Nun, warum erhalte ich dann einen Wertebereich von 0...4095? Aber, sei
es drum, das ist ja nicht mein aktuelles Problem (s.o.).
Ich nehme schon an, das "mein" Problem auf einen von mir gemachten
Fehler zurückgeht, aber ich finde keinen :-( . Wie gesagt: X-Richtung
ist okay, die längere Y-Richtung halt nicht.
Hanns-Jürgen M. schrieb:> Nun, warum erhalte ich dann einen Wertebereich von 0...4095? Aber, sei> es drum, das ist ja nicht mein aktuelles Problem (s.o.).
Doch, dann stimmt da was nicht. Das erste gelesene Byte vom
Touch-Controller sollte das oberste Bit auf Null haben, also 0xxx xxxx.
Wenn Du das dann um 4 nach links schiebst, hast Du dann maximal 0xxx
xxxx 0000; nach dem verodern mit dem um 4 nach rechts geschobenen
zweiten Byte also maximal 0xxx xxxx xxxx, also 7+4 = 11 mal x, also
sollte da maximal 2^11-1 = 2047 rauskommen.
Wenn das ein höherer Wert rauskommt, stimmt was nicht, entweder mit der
SPI-Übertragung oder die y-Leseroutine sieht anders aus als die
X-Routine die Du gepostet hast. Und das könnte dann auch gut dein
"aktuelles" Problem erklären.
Tassilo H. schrieb:> Hanns-Jürgen M. schrieb:>> Nun, warum erhalte ich dann einen Wertebereich von 0...4095? Aber, sei>> es drum, das ist ja nicht mein aktuelles Problem (s.o.).>> Doch, dann stimmt da was nicht. Das erste gelesene Byte vom> Touch-Controller sollte das oberste Bit auf Null haben, also 0xxx xxxx.> Wenn Du das dann um 4 nach links schiebst, hast Du dann maximal 0xxx> xxxx 0000; nach dem verodern mit dem um 4 nach rechts geschobenen> zweiten Byte also maximal 0xxx xxxx xxxx, also 7+4 = 11 mal x, also> sollte da maximal 2^11-1 = 2047 rauskommen.>> Wenn das ein höherer Wert rauskommt, stimmt was nicht, entweder mit der> SPI-Übertragung oder die y-Leseroutine sieht anders aus als die> X-Routine die Du gepostet hast. Und das könnte dann auch gut dein> "aktuelles" Problem erklären.
Nun, laut Datenblatt hast Du eigentlich Recht, auch die Datafruit-Lib
(Soft-SPI) fü+hrt nach dem Conversion-Start einen Dummy-Clock-Zyklus
ein. Von daher ist mein "Ergebnis" "eigentlich" unmöglich, aber es ist
so.
Bei mir sind beide Routinen für x und y identisch (nur das Controlyte
unterscheidet sich). Ich werde etzt aber mal in die Tiefen
hinabsteigen..... Das wird ein paar Minuten dauern...
..es blieb mir nichts anderes übrig, als mit dem Oszi mal nachzusehen.
Und dabei habe ich herausgefunden, daß das Busy-Signal nur rund 300 ns
lang ist.
Es beginnt bei der fallenden Flanke des 8. Clocks (Ende Übetragung
Startbyte(Configbyte) und endet deutlich vor der Startflanke
(Sample-Flanke) der 1. Clocks des ersten Lesebytes.
Clockrate ist 125 kHz (T = 8000 ns), also bleiben zwischen dem Ende des
Busysignales und der Startflanke 3700 ns Zeit...
Es wird also sofort das MSB 'rausgetaktet.....
Kann eigetlich nicht sein. Nach Datenblatt ändert sich das Busy-Signal
erst mit der nächsten fallenden Taktflanke wieder.
Zeig doch auch mal die WriteCharTo und ReadCharFrom-Routinen...
Tassilo H. schrieb:> Kann eigetlich nicht sein. Nach Datenblatt ändert sich das Busy-Signal> erst mit der nächsten fallenden Taktflanke wieder.
ja, so verstehe ich die Datenblätter für den ADS sowie für den XPT
auch...
> Zeig doch auch mal die WriteCharTo und ReadCharFrom-Routinen...
mach ich...
1
voidWriteCharTo7843(U8c)
2
{
3
SPI_Byte_Transfer(c);
4
}
5
U8ReadCharFrom7843()
6
{
7
U8c;
8
c=SPI_Byte_Transfer(0x00);
9
returnc;
10
}
11
12
U8SPI_Byte_Transfer(U8i)
13
{
14
SPDR=i;
15
while(!(SPSR&(1<<SPIF)))
16
;
17
returnSPDR;
18
}
19
20
voidinit_spi_TOUCH(void)// vor jeder touch-berabeitung aufrufen
21
{
22
23
TOUCH_PORT|=TOUCH_CS_PIN;//SS auf HI
24
SPCR=0b01010111;// durch 128 -> 125 khz bei 16 mhz MAXWERT fur TOUCH
25
SPSR=0b00000001;// LSB MUSS damit Clockteiler richtig
>SPCR=0b01010111;// durch 128 -> 125 khz bei 16 mhz MAXWERT fur TOUCH
2
>SPSR=0b00000001;// LSB MUSS damit Clockteiler richtig
Das ist nicht die Initialisierung, die Du im Ursprungsposting
geschrieben hast!
Bei SPCR=0b01010111 heisst:
SPIE = 0 interrupt aus OK
SPE = 1 SPI enabled OK
DORD = 0 MSB first OK
MSTR = 1 Master OK
CPOL = 0 SCK low when idle OK
CPHA =1 Daten gültig bei zweiter (=fallender) Flanke von SCK -
FALSCH!!!!!
SPR1=SPR0 = 1 fOsc/128 OK
und SPSR = 0b00000001
SPI2X doppelte SPI-Frequenz FALSCH (macht nämlich 250kHz SPI-Takt bei
16MHz clock und /128)
Insbesondere das falsche CPHA-Bit sollte zu den komischsten Ergebnissen
führen, da sich die Daten immer gerade dann ändern, wenn sie gesampelt
werden.
Hanns-Jürgen M. schrieb:> Ebenso ist eine Kalibrierung der Display-Touchfunktion zum jetztigen> Zeitpunkt nicht möglich, da die Positionsausgabe der y-Position über die> Länge gesehen nicht stetig ist und Sprünge aufweist.
Ich würde auf jeden Fall die 16-Bit-Version des Daten Auslesens
benutzen (so mache ich es jedenfalls). Du bekomst bei den Touch-
Rohdaten nie die Null oder den Vollausschlag geliefert. Somit wird
die 8-Bit Auflösung noch um einiges schlechter als der reine Werte-
bereich der UINT8 vermuten lässt.
In meinem Fall (gleiches 16-Bit Display) waren die Mininmal- und
Maximalwerte die folgenden (aus meiner Source herauskopiert):
1
#define X_MIN_RAW 60ul
2
#define X_MAX_RAW 1970ul
3
#define Y_MIN_RAW 110ul
4
#define Y_MAX_RAW 1970ul
Die Rohwerte musst du sowieso skalieren um auf das Display-Format
zu kommen.
>>SPCR=0b01010111;// durch 128 -> 125 khz bei 16 mhz MAXWERT fur TOUCH
2
>>SPSR=0b00000001;// LSB MUSS damit Clockteiler richtig
3
>
>> Das ist nicht die Initialisierung, die Du im Ursprungsposting> geschrieben hast!
Richtig, nach der 1. Intialisierung SPSR=0 betrug die Clock
fälschlicherweise da zu hoch laut Spec 250 kHz, ob wohl die Änderung auf
SPSR = 1 (125 kHz Clock) keine Änderung am ergebnis brachte.
>> CPHA =1 Daten gültig bei zweiter (=fallender) Flanke von SCK -> FALSCH!!!!!
Ja, das ist theoretisch falsch und hatte ich nur probeweise auf "§1"
gesetzt. Brachte keine Änderung des Erscheinungsbildes. CPHA Ist
mittlerweilöe wieder "0".
> Insbesondere das falsche CPHA-Bit sollte zu den komischsten Ergebnissen> führen, da sich die Daten immer gerade dann ändern, wenn sie gesampelt> werden.
Da denke/dachte ich auch, brachte aber keinen pos/neg Änderung.
Aber ich bin mit dem Oszi einer anderen WH-Sache auf der Spur: Da der
Arduino mit 5 V läuft, werden die Signale zum TFT/TOUCH Modul mittels
Widerständen (22k Vorw., 33k geg. Masse) auf 2/3 heruntergeteilt. Meine
OSZI zeigt jedoch ziemlich flaue Flanken beim heruntergeteilten Clock
an. Das kann natürlich auch am Tastkopf liegen, den ich zwar in Stellung
1:10 benutze, aber vlt. ist die Eingangskap. zu hoch. Ich werde gleich
mal einen besseren Tastkopf nehmen und dann ggf. die Widerstandswerte
verringern.
Hanns-Jürgen M. schrieb:> werden die Signale zum TFT/TOUCH Modul mittels> Widerständen (22k Vorw., 33k geg. Masse) auf 2/3 heruntergeteilt.
Das ist zu hochohmig, das dürfte bei den üblichen SPI-
Geschwindigkeiten nicht funktionieren.
.... und wie geschieht das "Hochteilen" des MISO-Signals
des Touch Controllers? Noch eine Fehlerquelle ....
Arduinoquäler schrieb:> Hanns-Jürgen M. schrieb:>> werden die Signale zum TFT/TOUCH Modul mittels>> Widerständen (22k Vorw., 33k geg. Masse) auf 2/3 heruntergeteilt.>> Das ist zu hochohmig, das dürfte bei den üblichen SPI-> Geschwindigkeiten nicht funktionieren.>> .... und wie geschieht das "Hochteilen" des MISO-Signals> des Touch Controllers? Noch eine Fehlerquelle ....
So, ja, was soll ich sagen. Das "Problem" waren tatsächlich die
"hochohmigen" Spannungsteiler. NAchdem ich die Werte auf ein Elftel
reduziert habe, stimmen die Flanken und auch die aushelesenen Rohwerte
sind plausibel.
Ich könnte mich selber in den Besagten beißen, daß ich nicht eher zum
Oszi gegriffen habe... Aber ich habe eine fadenscheinige Ausrede: Das
SainSmart Adapterboard, das ich kürzlich erstanden habe, benutzt nur
Vorwiderstande von 10k Ohm, während der effektive Innenwiderstand der
heruntergeteilten Spannungsquelle 22k || 33k vergleichbare 13 k ergibt.
Ich vermute, das Adapterboard funzt dann auch nicht richtig. Allerdings
ist dort defaultmäßig eine Soft-SPI für den Touchcontroller zuständig,
während die Hard-SPI für die SD Karte zustäöndig ist. Was die dann wohl
sagt?
Ach ja, bezüglich des "Hochteilens" verwende ich eine Diode und einen
Pullup auf der 5V Seite. Die Flanken sind okay.
So, nachdem jetzt die Meßwerte vorliegen, kann ich mich an das
Kalibrieren machen. Aber das sind Peanuts..
Dabke für eure Hilfen und Tipps, und sorry für meine Nichtbeachtung der
Hardwareprobleme