Forum: Mikrocontroller und Digitale Elektronik Touch - wie kalibrieren in C?


von AVRli .. (avrli)


Lesenswert?

Hi,

ich habe bei einem kleinem 4,3 Zoll Display solange hin und her probiert 
bis das Touch Panel ungefähr zu dem Display mit den Ergebnissen passte.

Nun habe ich ein größeres im Einsatz und würde gerne eine 
Kalibirirungsroutine vorsehen.

Dazu habe ich mir 4 Positionen auf dem Bildschirm gezeichnet und die 
Werte dazu ausgegeben, wenn alle 4 angetippt wurden.
1
Xmax = 800, Ymax = 480
2
3
          Xmin                       Xmax
4
          +--------------------------+ Ymin
5
          | P1 ------------------ P2 |
6
          |  |                    |  |
7
          |  |                    |  |
8
          |  |                    |  |
9
          | P4 ------------------ P3 |
10
          +--------------------------+ Ymax
11
12
P1.x =  80 (4850)   P1.y =  48 (3080)
13
P2.x = 720 (1832)   P2.y =  48 (2378)
14
P3.x = 720 (1882)   P3.y = 432 (6181)
15
P4.x =  80 (6500)   P4.y = 432 (6324)
16
17
Werte in den Klammern = 12 Bit ADC RAW Werte.
Im Idealfall wäre z.B. P1.x = P4.x und P3.y = P4.y, dass ist nun 
natürlich nicht der Fall. :-/ (Fertigungsbedingt wohl von Display zu 
Display sehr unterschiedlich...)

Wie berechnet man nun aus diesen Informationen die tatsächlich 
angetippte X/Y Position?

Gruß AVRli...

von pegel (Gast)


Lesenswert?

Wo kommen die großen Zahlen her? 12 bit geht doch nur bis 4095.

von M. K. (sylaina)


Lesenswert?

pegel schrieb:
> Wo kommen die großen Zahlen her? 12 bit geht doch nur bis 4095.

Jepp, Werte größer 4095 ist kein 12 Bit mehr. ists vielleicht ein 14bit 
ADC? Oder wird hier mit Oversampling gearbeitet?

: Bearbeitet durch User
von pegel (Gast)


Lesenswert?

Zum berechnen würde ich die x und y Werte die zusammen passen müssten 
erst einmal mitteln und dann die 10% Ränder einfach hochrechnen.

von AVRli .. (avrli)


Lesenswert?

M. K. schrieb:
> ists vielleicht ein 14bit
> ADC? Oder wird hier mit Oversampling gearbeitet?

Da schreibt ihr ja was! :-( grübel
Der Controller ist der XPT2046, ein 12 Bit SPI Touch Controller.

Ich schau mal wo ich den Fehler mache.
Vielleicht sind die Abweichungen ja gar nicht so schlimm.

Gruß AVRli...

von pegel (Gast)


Lesenswert?

Wie ich sehe misst der auch wie stark "getoucht" wird.
Ist vielleicht dieser Wert in deinen Angaben mit drin?

von m.n. (Gast)


Lesenswert?

AVRli .. schrieb:
> Ich schau mal wo ich den Fehler mache.
> Vielleicht sind die Abweichungen ja gar nicht so schlimm.

P1.x und P4.x sollten annähernd gleich sein. Gleiches gilt für P1.y und 
P2.y.
Die Werte stimmen nicht!

von Sigi (Gast)


Lesenswert?

Bei Touchscreens sollte dir zuerst mal klar
werden, mit welcher max. Frequenz überhaupt
abgetastet werden kann. Dein Controller hat
glaube ich 100KHz oÄ, mit Touch aber wesentlich
langsamer, vlt. 0.25-1000KHz. 1000 vollständige
Koordinaten sind schon sehr viel.

Schalte dazu einfach mal z.B. die X-Achse ein
und sample sofort danach hintereinander ein
paar Tausend Werte und zeige die als Plot da,
bei dem sich der finale Wert über die Zeit
stabilisieren sollte. Daraus ergibt sich dann
die Sample-Frequenz bzw. der Algo:
1. Auf Achse Umschalten
2. Warten
3. Samplen
(dann auch die andere Achse umschalten etc.)
Lässt sich bei uCs leicht per Timer-Interrupt
machen.

Ich habe das mal auf meinen Terasic-NEEK-Board
(FPGA-Board) sehr genau aufgezeichnet und so
die optimale/maximale Sampling-Frequenz bestimmt.
Wird schneller abgetastet, dann deuten die
Werte "scheinbar" auf einen verzerten Screen
hin, bei langsamereren Samplen dagegen ein
"exaktes" Rechteck. Erst dann sollte kalibriert
werden.

von DPA (Gast)


Lesenswert?

Ich würde das Problem so angehen:

Man könnte überall linear interpolieren & normalisieren. Man hat 
einerseits 4 Punkte in einem unbekannten Koordinatensystem (uPn), und 4 
in einem bekannten (bPn). Stelle dir nun eine Gerade durch die Punkte in 
X Richtung vor. Nun sagen wir, dass beim linken Punkt jeweils 0% ist, 
und beim rechten 100%. Nun wählen wir einen Punkt auf beiden Linien, der 
jeweils bei (tx)% liegt. Nun machen wir das selbe mit diesen 2 Punkten, 
so können wir hoch und runter, also nennen wir die Prozentangabe mal ty.
1
u1x = uP1.x*(1-tx) + uP2.x*tx
2
u1y = uP1.y*(1-tx) + uP2.y*tx
3
u2x = uP4.x*(1-tx) + uP3.x*tx
4
u2y = uP4.y*(1-tx) + uP3.y*tx
5
uresx = u1x*(1-ty) + u2x*ty
6
uresy = u1y*(1-ty) + u2y*ty
7
8
b1x = bP1.x*(1-tx) + bP2.x*tx
9
b1y = bP1.y*(1-tx) + bP2.y*tx
10
b2x = bP4.x*(1-tx) + bP3.x*tx
11
b2y = bP4.y*(1-tx) + bP3.y*tx
12
bresx = b1x*(1-ty) + b2x*ty
13
bresy = b1y*(1-ty) + b2y*ty

tx und ty sind nun effektiv Koordinaten eines neuen normalisierten 
Koordinatensystems, und mit den Formeln oben kann man damit den selben 
Punkt in unserem quell und ziel Koordinatensystem bestimmen. Die uPn 
Punkte sind die Koordinaten der Kalibrationspunkte. bPn sind die selben 
Punkte im Wunschkoordinatensystem. ures ist ein input Punkt. bres ist 
ein output Punkt. Nun müssen wir das nur umformen, so dass wir t anhand 
von ures, und uPn berechnen können.

Erstmal alles einsetzen:
1
uresx = (uP1.x*(1-tx) + uP2.x*tx)*(1-ty) + (uP4.x*(1-tx) + uP3.x*tx)*ty
2
uresy = (uP1.y*(1-tx) + uP2.y*tx)*(1-ty) + (uP4.y*(1-tx) + uP3.y*tx)*ty
Und dann, ähm, ok, wie man das jetzt nach tx und ty auflöst, da bin ich 
etwas überfragt...

von AVRli .. (avrli)


Lesenswert?

Danke für den Hinwies, dass die Werte nicht stimmen!
In der Tat war das ein Fehler in meinen Software SPI-Routinen.

Da habe ich nicht richtig hingesehen und da hat sich eingeschlichen das 
nach 12 Bit noch einmal nach links geshiftet wurde! :-/

Nun die neuen Werte...
1
Xmax = 800, Ymax = 480
2
3
          Xmin                       Xmax
4
          +--------------------------+ Ymin
5
          | P1 ------------------ P2 |
6
          |  |                    |  |
7
          |  |                    |  |
8
          |  |                    |  |
9
          | P4 ------------------ P3 |
10
          +--------------------------+ Ymax
11
12
P1.x =  80 (3020)   P1.y =  48 (1137)
13
P2.x = 720 (900)    P2.y =  48 (1177)
14
P3.x = 720 (887)    P3.y = 432 (3062)
15
P4.x =  80 (3198)   P4.y = 432 (3154)
16
17
Werte in den Klammern = 12 Bit ADC RAW Werte.

Das ist nun mit einem Stift getippt.
Die Werte sind auch konstant, bei erneuter Eingabe.

DPA schrieb:
> Ich würde das Problem so angehen:

OK, das muss ich erstmal verinnerlichen... :-D
Puhh...

Gruß AVRli...

von Dirk B. (dirkb2)


Lesenswert?

Das ist doch das Gleiche wie bei 
Beitrag "Trigonometrie zum Platinenbohren"
(nicht vom Titel verwirren lassen)

von AVRli .. (avrli)


Lesenswert?

Dirk B. schrieb:
> Das ist doch das Gleiche wie bei

Danke!
Na ich bin noch keinen Schritt weiter... :-(
So ganz trivial, wie ich dachte, ist das mit der Kalibrierung wohl 
nicht.

von m.n. (Gast)


Lesenswert?

AVRli .. schrieb:
> OK, das muss ich erstmal verinnerlichen..

Du solltest auch das Datenblatt der Touch-Folie verinnerlichen, die 
bestenfalls eine Genauigkeit von 1 - 3% liefert.
Dann wirst Du erkennen, daß es ausreichend ist, jeweils den Mittelwert 
der x/y Koordinaten zu verwenden, der zwischen den Eckpunkten liegt.

Beispiel: der obere y-Wert ergibt sich aus P1.y + (P2.y - P1.y) / 2
Das gleiche Spiel dann für die anderen drei Werte, woraus man dann die 
mittlere Steigung der x- und y-Achse und den Offset y-oben und x-links 
erhält.
Das reicht.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Was du suchst ist eine Abbildung "f" von ADC-Werten, also Vektoren (A_x, 
A_y) auf Touch-Koordinaten (P_x, P_y):
bzw

Wenn dir eine (affin) lineare Kalibrierung ausreicht, ist das doch nicht 
so schwer. Dazu definierst du f als Abbildung der Form
Wobei du jetzt die "m" und "b" bestimmen musst, d.h. 6 Unbekannte. Mit 
deinen 4 Kalibrations-Punkten hast du sogar 8 Gleichungen. Davon suchst 
du dir 6 aus, setzt in die Funktion ein und baust ein Gleichungssystem:
usw.

ergibt, wenn P1 - P3 genutzt werden:

Das löst du für die "m" und "b" und erhältst deine Abbildungsfunktion.

Mit Wolfram Alpha
https://www.wolframalpha.com/input/?i=LinearSolve%5B%7B%7B4850,3080,0,0,1,0%7D,%7B0,0,4850,3080,0,1%7D,%7B1832,720,0,0,1,0%7D,%7B0,0,1832,720,0,1%7D,%7B1882,6181,0,0,1,0%7D,%7B0,0,1882,6181,0,1%7D%7D,%7B80,48,720,48,720,432%7D%5D

ergibt sich als Lösung diese Abbildung (exakt):

(hoffentlich nicht verrechnet :) )

: Bearbeitet durch User
von AVRli .. (avrli)


Lesenswert?

Niklas G. schrieb:
> Was du suchst ist eine Abbildung "f" von ADC-Werten, also Vektoren (A_x,
> A_y) auf Touch-Koordinaten (P_x, P_y):

Im Prinzip hast Du recht!
Bei den Formeln ist bei mir Feierabend, schade! :-(

Ich mach mir mal einen Kaffee und versuche es mal nachzuvollziehen, 
glaube aber jetzt schon, dass ich das nicht packen werde.

von AVRli .. (avrli)


Lesenswert?

m.n. schrieb:
> Dann wirst Du erkennen, daß es ausreichend ist, jeweils den Mittelwert
> der x/y Koordinaten zu verwenden, der zwischen den Eckpunkten liegt.

Ja vlt. fange ich damit erstmal an!

von pegel (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe zum Spass auch mal gerechnet.
Siehe Anhang.

Es werden die gemessenen ADC Werte gemittelt und damit die ADC Werte der 
linken oberen und rechten unteren Ecke als Kalibrierwerte berechnet.

Kommentare sind in der Datei. Compiliert mit gcc unter Linux, lässt sich 
aber leicht übernehmen.

Ich hoffe es ist kein Fehler drin.

von pegel (Gast)


Lesenswert?

Ach ja, die Funktion adc2pix() wandelt ADC Werte in Pixel Koordinaten.

von J. -. (Gast)


Lesenswert?

AVRli .. schrieb:
> Ich mach mir mal einen Kaffee und versuche es mal nachzuvollziehen,
> glaube aber jetzt schon, dass ich das nicht packen werde.

Das gilt nicht, es wird noch schlimmer g

Unterschiedliche Displays sind an den ADC des XPT unterschiedlich 
angeschlossen. Du mußt erstmal checken, ob x+, x-, y+ und y- der 
Touchpanelfolie so angeschlossen sind, wie Du es Dir vorstellst 
(Landscape = horizontal mehr Pixel, Portrait = vertikal mehr Pixel).
Da stößt man auf das Control-Register des XPT
const uint8_t TPLctr[4] = {0xD2,0x92,0xB2,0xC2};
oder
const uint8_t TPLctr[4] = {0x92,0xD2,0xB2,0xC2};  // x/y 'vertauscht'
bzw. ohne Powerdown des XPT:
const uint8_t TPLctr[4] = {0xD0,0x90,0xB0,0xC0};
oder
const uint8_t TPLctr[4] = {0x90,0xD0,0xB0,0xC0};  // x/y 'vertauscht'
Wahrscheinlich hast Du das schon berücksichtigt, dann spielt das keine 
Rolle mehr. Aber nur für den Fall.
-
Der Teil mit der linearen Interpolation ist nicht schwierig, Du hast ja 
schon die wesentlichen Zahlen und mußt jetzt nur noch ein wenig rechnen. 
Das Modell mit den 4 Punkten benutze ich auch und es taugt.
Achte darauf, die ADC-Werte des XPT als signed integer (also int16_t) zu 
nehmen, das vereinfacht die (kleinen) Rechnungen.
Wenn Du die Rechnung (im Grunde geht es nur um Offset und Steigung in x- 
und y-Richtung) gemacht hast, kommen die Feinschliff-Herausforderungen:
1) SPI-Geschwindigkeit
2) Druckerkennung
3) Mitteln
4) Abweich(varianz)erkennung in x- und y-Richtung
-
Zum ersten Punkt, der SPI-Geschwindigkeit, gilt: Der  XPT kann mit 2.5 
MHz ausgelesen werden, aber während des Sampelns der Koordinaten sollte 
er mit niedriger Taktung betrieben werden, z.B. 650 kHz. Die gennanten 
Zahlen kommen vom STM32, deshalb nicht AVR-kompatibel, aber man muß 
darauf achten.

Der zweite Punkt, die Druckerkennung, bezieht sich auf die 
'Kontaktierung' der beiden Folien im Touchpanel, dieser Widerstand 
beeinflusst die Qualität der Positionserkennung ganz erheblich.
Mal ein Beispiel, wie die Sensitivität und auch das korrekte 
Koordinatensystem (siehe ganz oben) in die Berechnung eingeht:
#if (USE_TFT==TFT_ILI9328) || (USE_TFT==TFT_SSD1289) || 
(USE_TFT==TFT_ILI9327) || (USE_TFT==TFT_ILI9486)
    r = (abs(z2-z1)*y2)/z1;
#else
    r = (abs(z2-z1)*x2)/z1;
#endif
Andere Displays sind anders verdrahtet. Nur, wenn das berücksichtigt 
wird und Du den "Druckpunkt" bzw. Widerstand zwischen den Folien r mit 
oberem und unterem Limit versiehst, um einen gültigen Touchpanelprozeß 
auszulösen, kommt am Ende etwas Zuverlässiges dabei heraus..
Dazu mußt Du das XPT2046-Datenblatt etwas genauer studieren, aber es 
lohnt sich ;)

Nach diesen Dingen kommt das Mitteln (ein einzelner ADC-Wert des XPT 
kann zwar reichen, aber besser ist es, mehrere aufzusummieren und dann 
festzustellen, ob während des Drückens x- und y-Position zu sehr 
variieren), was ein Vorposter schon angesprochen hatte.

Nun fang aber mal mit der linearen Interpolation an, Dein Konzept ist 
richtig, und der Rest kommt dann beim Experimentieren ;)

von AVRli .. (avrli)


Lesenswert?

Mich haben die irren Formeln abgeschreckt, dass ist zu viel gewesen. Ich 
habe mit sowas bisher wirklich wenig bis gar nichts zu tun gehabt. Habe 
ich noch nie so benötigt.

pegel schrieb:
> Ich habe zum Spass auch mal gerechnet.
> Siehe Anhang.

Vielen Dank für Deine Mühe! :-)
Ich schau mir das an und versuche zu verstehen, wie das mit der 
Berechnung funktioniert.


Jürgen S. schrieb:
> Das gilt nicht, es wird noch schlimmer g

Danke für Deine ausführlichen Erläuterungen! :-)
Besonders die Hintergrundinfos auf was noch zu achten ist und welche 
Erfahrungen Du gemacht hast! Toll, vielen Dank!

Gruß AVRli...

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

AVRli .. schrieb:
> Mich haben die irren Formeln abgeschreckt, dass ist zu viel gewesen.

Hmm, ist doch nur etwas lineare Algebra, das macht man doch sogar in der 
Schule... Letztendlich musst du nur die Messwerte in die Matrix 
einsetzen und diese invertieren/lösen - dafür gibt es Bibliotheken. 
Besser wäre es sie analytisch allgemein zu lösen (hat ja viele Nullen). 
Aus dem Ergebnis wieder eine Matrix bauen und du hast deine Abbildung.

Dieses Vorgehen hat den Vorteil, dass Offsets und Spiegelungen 
automatisch mit einberechnet werden; man spart sich entsprechende 
Fallunterscheidungen.

: Bearbeitet durch User
von max (Gast)


Lesenswert?


von Hendrik L. (hlipka)


Lesenswert?

Auch wenn es ohne Code ist:
https://www.maximintegrated.com/en/app-notes/index.mvp/id/5296
https://www.embedded.com/design/system-integration/4023968/How-To-Calibrate-Touch-Screens
sollte die Theorie erklären.
Praktischer ist es natürlich wenn man einen Controller verwendet der 
diese Umrechnung gleich selber erledigen kann...

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ich hab das ganze nochmal durch WA geschicht... Seien (A_1x, A_1y) 
jeweils die ADC-Werte der drei Kalibrations-Punkte, und (P_1x, P_1y) die 
gewünschten entsprechenden LCD-Koordinaten, dann ergibt sich folgende 
leicht unübersichtliche Lösung der Kalibration.

Mit

und

Ist die Abbildung dann:

D.h. wenn man gemessene a_x und a_y einsetzt, kommen die gewünschten 
LCD-Koordinaten heraus. Das müsste automatisch Offsets (Translation), 
Drehung, Scherung und Spiegelung "herauskalibrieren" (praktisch alles 
was sich als affin lineare Abbildung darstellen lässt).

von Mr_Sven (Gast)


Lesenswert?

Moin,
schau dir Mal die CalibrateApp von hier an: 
https://github.com/rossumur/microtouch das geht über 3 definierte Touch 
Punkte. Ich benutze das in meinen Touch Systemen, klappt wunderbar. 
Irgendwo hab ich auch Mal was über das Prinzip gelesen, weiß aber nicht 
mehr wo.
Gruß Sven

von AVRli .. (avrli)


Lesenswert?

Vielen Dank für ALLE Beiträge!
Es gibt hier wohl wirklich min. 5 Wege zum Ziel.

In Anbetracht, das die Touch-Folie wirklich Toleranzen hat und ich auf 
einen 8-Bit'er programmiere, habe ich den Weg der linearen Interpolation 
gewählt.

Ich bin am Ziel angekommen und bekomme nun die Pixel zu den ADC Werten 
angezeigt. :-)

Grobe Orientierung war der Beitrag von pegel - DANKE!

Jetzt fehlt mir noch die Interpretation von der Z-Achse, damit nicht 
gleich der geringste Druck als Wert interpretiert wird.

Ich freue mich riesig, dass es nun endlich in die richtige Richtung 
geht.

Gruß AVRli...

von pegel (Gast)


Lesenswert?

Bitte sehr.

von AVRli .. (avrli)



Lesenswert?

Jürgen S. schrieb:
> Der zweite Punkt, die Druckerkennung

Das habe ich mir nun angesehen aber ich glaube das sich das hier völlig 
anders verhält.

Die RAW Werte sehe ich schon...
Z1 zappelt zwischen 0 und 30 wenn man nichts drückt. Geht dann aber auf 
ca. 100 (X Pixel 800) und ca. 2000 (X Pixel 1)

Z2 zappelt um 4095 und 4070 wenn nicht gedrückt. Geht auf ca. 3850 wenn 
gedrückt.

Laut Datenblatt gibt es zwei Varianten den Druck r zu berechnen.
Ich würde gerne die erste Varianten nehmen, da sie nur Z1, Z2 und X 
benötigt. Bild angehangen...

Die Formel die dazu angegeben ist kann ich nicht nachvollziehen, kannst 
Du mir da noch einen Tip geben welche Deiner beiden Formeln für r hier 
zutreffend ist?

Jürgen S. schrieb:
> #if (USE_TFT==TFT_ILI9328) || (USE_TFT==TFT_SSD1289) ||
> (USE_TFT==TFT_ILI9327) || (USE_TFT==TFT_ILI9486)
>     r = (abs(z2-z1)*y2)/z1;
> #else
>     r = (abs(z2-z1)*x2)/z1;
> #endif


Ich nehme an das es die 2. sein sollte wo auch X benötigt wird aber die 
passt irgendwie nicht zu der aus dem Datenblatt. Oder sehe ich den 
Zusammenhang einfach nicht?

Gruß AVRli...

von C. W. (chefkoch)


Lesenswert?

Und zum Schluss sollte man das gelesen haben:

https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591546

(Application note AVR341)

von J. -. (Gast)


Angehängte Dateien:

Lesenswert?

> Ich nehme an das es die 2. sein sollte wo auch X benötigt wird aber die
> passt irgendwie nicht zu der aus dem Datenblatt. Oder sehe ich den
> Zusammenhang einfach nicht?
Weiß nicht, ich kann mich selber kaum noch erinnern, was ich da gemacht 
habe g

Ich vermute mal, ich habe auch die von Dir verwendete Formel im Sinn 
gehabt. Das kleine 'r' in der von mir angegebenen Formel ist 
wahrscheinlich nicht der echte 'Widerstand', sondern  der 
Widerstand*4096. Wegen x2 bzw. y2 komme ich jetzt selbst nochmal ins . 
Ist ja wurscht, ob man's in x- oder y-Richtung macht, aber ich wollte 
die längere Achse (also die mit mehr Pixeln) verwenden, warum auch 
immer. Und irgendwie kürzt sich der Absolutwert von Rx dann raus.
Ich habe einen Haufen Displays ausprobiert und es funktioniert bei allen 
mit ungefähr gleicher Druckempfindlichkeit unabhängig von der 
Druckposition.

Prinzipiell ist das die gleiche Formel wie von Dir gezeigt, nur 
umgestellt und z1 'herausgezogen', um mit integer besser rechnen zu 
können (als Zwischenvariablen für x,y und z habe ich außerdem int32_t 
verwendet, weil ich auch mit den aufsummierten (Mittel)Werten rechne, 
bevor ich am Schluß wieder auf int16_t caste. Das liegt aber am STM32 
und seinen 32-bit, da verschenkt man keine Rechenzeit beim Aufpumpen auf 
32 bit wie beim AVR).

Super, daß das mit der linearen Interpolation bei Dir also doch schon 
geht ;)

Du kannst ja nun folglich beim Drücken permanent Pixel zeichnen lassen, 
da sieht man schon, wohin die Pixel weglaufen oder welche Varianz sie 
haben, wenn zuwenig Druck ausgeübt wird, zuwenig Mittelwerte gesampelt 
wurden oder die SPI-Geschwindigkeit zu hoch ist (wobei es da noch von 
der Leitungsführung auf der TFT-Platine abhängt, wieviel noise vom SPI 
in den ADC des XPT eingestreut wird, glaube ich).

Ich habe noch 2 ältere touch-Dateien angehängt, nur zum Überblick, 
schlecht kommentiert, und außerdem sind die auf Displaypixeldimension 
bezogenen Positionen TPLx und TPLy global - was nicht sein muß, man kann 
sie auch von TPL_Read über pointer zurückgeben, aber so laufen sie 
derzeit bei mir.
Man erkennt auch die Grafikfunktionen zum Zeichnen und Abfragen der 4 
Punkte, die allerdings 16% von den Rändern entfernt sind, nicht 10%.

Nur zur Info: Ein Timerinterrupt 10ms dekrementiert die Variable 
'deltim', wenn sie größer als 0 ist, außerdem wird in diesem Interrupt 
auf TPL_Read == 0 abgefragt. Der PEN-Interrupt wird nicht an einem 
Interruptpin betrieben, sondern in TPL_Read gepollt.

Ich habe damals eine Struktur "panel" deklariert, die enthält die 
Faktoren und Offsets in einem gut handelbaren Integerformat, 
panel.thresup und panel.thresdo sind die Grenzwerte für 'r', sie liegen 
bei den meisten Displays bei 3000 (up) bzw. 500 (do). Wie gesagt, keine 
echten Widerstandswerte, weil diese zu klein wären bzw. zuwenig 
Auflösung hätten, aber sie sind proportional zum Quer-Widerstand.

von J. -. (Gast)


Lesenswert?

> Wegen x2 bzw. y2 komme ich jetzt selbst nochmal ins .
Grübeln ;)

Wegen der Codelänge von 'touch.c' nicht erschrecken, der untere Teil ab
#elif USE_TOU & TOU_ADC
bezieht sich auf Auswertung der Touchpanel ohne den XPT, sondern direkt 
mit den ADC-Wandlern des Prozessors angeschlossen an das Touchpanel. Den 
kann man vergessen.

von AVRli .. (avrli)


Lesenswert?

Danke Jürgen S. für die weitere Hilfestellung,
So langsam wird das richtig gut!

Jürgen S. schrieb:
> Du kannst ja nun folglich beim Drücken permanent Pixel zeichnen lassen,
> da sieht man schon, wohin die Pixel weglaufen

Auf die einfachsten Sachen komme ich nicht, mein Gott!
Das habe ich nun mal gemacht, ich lasse bei gültigen ADC_x und ADC_y 
Werten nun einen Kreis von einem Radius 10 Pixel zeichnen.

Ein kleiner Bock war noch drin! Nun ist der fast immer unter der 
Stiftspitze. An manchen Stellen etwas daneben, aber selten verlässt er 
den Durchmesser von 20 Pixel. Das passiert dann auch erst zu den Rändern 
hin... da weiß ich nun nicht genau ob das im Rahmen liegt oder ob ich 
doch nochmal nach Fehlern suchen muss.



Jürgen S. schrieb:
> Man erkennt auch die Grafikfunktionen zum Zeichnen und Abfragen der 4
> Punkte, die allerdings 16% von den Rändern entfernt sind, nicht 10%.

OK, das mit den 10% hatte ich nun irgendwo aufgeschnappt, vlt. ist 16% 
noch besser? Ich probiere es heute Abend mal aus.


Jürgen S. schrieb:
> panel.thresup und panel.thresdo sind die Grenzwerte für 'r', sie liegen
> bei den meisten Displays bei 3000 (up) bzw. 500 (do).

OK, es sind also 2 Werte mit denen man arbeitet?
Bei 3000 legt man fest, nicht mehr gedrückt und bei 50 beginnt man und 
weiß es wird gedrückt?

Die Rechnung schau ich mir auch heute Abend an und mal sehen ob ich auf 
ähnliche Werte komme.

Gruß AVRli...

von J. -. (Gast)


Lesenswert?

Hört sich ziemlich gut an.

In den Ecken bzw am Rand ist es bei mir auch etwas schwieriger, man 
braucht etwas mehr (mechanischen) Druck, aber das liegt vermutlich 
daran, daß dort die Klebestelle für die Panels ist, inklusive dem dort 
verklebten Abstandsrähmchen. Trotzdem laufen die Punkte nicht weg bzw. 
es ist dort nicht wesentlich unexakter als im mittleren Bereich.
Das liegt aber auch daran, daß die Auswertung das auch gar nicht mehr 
zuläßt, dazu muß man die x/y-Mittelung abschalten.

-

Wenn ich mein Code-Geschreibsel richtig lese, sind in TPL_Read zwei 
'Begrenzer' für die x- und y-Positionen eingebaut:

//X
x1 = TPL_GetChannel(0);
do
{
 x1 = x2;
 x2 = TPL_GetChannel(0);
}while(abs(x2-x1)>(TPLAVG<<1));//(TFTXSIZE/100));

(Böse Endlosschleifen übrigens, allerdings geht das lesen so schnell, 
daß real innerhalb kürzester Zeit ein gültiger Punkt gefunden wird, man 
kann flüssig seine Unterschrift auf das TFT zeichnen, auch der AVR 
sollte das halbwegs schaffen).

Es wird also ein Punkt genommen, und dann (schnell) weitergemessen. 
Liegt der darauffolgend gemessene Punkt in dem Radius TPLAVG<<1 vom 
zuvor gemessenen Punkt, wird die Position als gültig akzeptiert. Das ist 
also die horizontale Mittelung. Kann man verbessern, ich hatte den Wert 
mal auf das die Displaypixelanzahl selbst bezogen, aber dann wohl den 
Mittelwert bzw. dessen Varianz als logischer für die Bildung des 
'Akzeptanzradius' empfunden, weiß nicht mehr.

-

Wegen der zwei treshold-Werte für z: Das ist eher ein Bereich, den man 
vorgibt, wobei die kleinere Zahl (panel.thresdo) kaum eine Rolle spielt, 
die kann man auch anfangs 0 setzen (hatte irgendwas mit dem Rauschen zu 
tun, weshalb ich die nahm). Vergiß die mal.

Daß 'r < panel.thresup' gilt, ist viel wichtiger. Man kann beobachten 
(falls die o.a. Mittelung in horizontaler Richtung mal weggelassen 
wird), daß die gezeichneten Pixel zu den Ecken hin weglaufen, wenn man 
zu leichten Druck ausübt (und damit r > als die Threshold ist - das 
bedeutet ja nichts anderes, als daß der Widerstand zwischen den Panels 
zu groß ist und die anderen Querströme innerhalb der Folie eben nicht 
(druck)punktgenau gesampelt werden).

Damit war's das aber auch schon, mit den Zahlen und Konstanten kann man 
noch spielen,und für unterschiedliche Displays (bzw. Touchfolien) 
ergeben sich auch unterschiedliche Zahlen für r.  Bei zwei 4.3"-Displays 
von Sainsmart ist der Wert für panel.thresup ca. 2200, aber bei den 
meisten anderen (von 2.8" bis 7", unterschiedliche Hersteller) ist es um 
3000 herum.

Ich hatte mir eine kleine GUI gebastelt und für die Z- bzw. r Justage 4 
Touchbuttons (up +/- und do +/-) definiert, somit konnte ich auf dem TFT 
"zeichnen" und gleichzeitig auch die Werte für den Bereich von 
zulässigen r verändern (wenn die Werte schon halbwegs stimmen natürlich, 
sonst drückt man vergeblich auf + und - ;)). Der obere Grenzwert 
(panel.thresup) ist wirklich gut bestimmbar - entweder man wählt ihn zu 
klein, dann muß man drücken wie ein Ochse ;), oder man wählt ihn einiges 
zu groß, dann laufen die Pixel zum Rand hin weg, wenn man zu schwach 
drückt - läßt sich wirklich nett simultan beobachten. Beides will man 
nicht, und die Schwelle läßt sich gut finden.

-

Wegen 10% oder 16%: Prinzipiell sind die 10% sogar besser, weil die 
Interpolation dann zwischen weiter entfernten Punkten erfolgt. Ich habe 
bei mir halt ziemlich große Berührkreise mit einem kleinen 'Loch' (wie 
ein Donut) gezeichnet, um einerseits einen vergleichbaren Radius zu 
meinen Wurschtfingerkuppen zu haben, wo ich dann gefühlt mittig 
draufdrücken kann, oder eben für präzisere Positionskalibrierung mit 
einem PEN im Donutloch punktgenau kalibrieren kann. Beides hat Vor- und 
Nachteile, der PEN übt einen stärkeren, lokalen Druck aus als der 
Finger. Den Range für r (aber auch die x/y-Mittelung) kann man 
dementsprechend eher für Wurschtfinger oder für PEN optimieren.

von AVRli .. (avrli)


Lesenswert?

Ich muss zugeben das ich die Sache mit dem Touch völlig unterschätzt 
habe.
Egal nun bin ich ja soweit, das man wirklich noch etwas Zeit in den 
Feinschliff stecken kann.

Mit Z habe ich nochmal probiert, nun sind die folgende Zustände für Z.
Touch nicht gedrückt: zappelt zwischen 0 und -1
Touch ordentlich gedrückt: Z zwischen 3120 - 3300 :-)

Mit den Rändern habe ich mal nur 3% eingestellt. Was soll ich schreiben? 
Die Positionen sind nun noch deutlich exakter! :-)

Damit kann ich nun mehr als leben! Ich habe mir auch so ein "Donut" 
innen R5, außen R10. Maximal 5 Pixel leg ich nun mit einem PEN daneben 
und das auch nur im 3% Rand.

Ich möchte ja eigentlich darauf nicht zeichnen, könnte man wohl aber.

Etwas beruhigt bin ich das es nun so toll funktioniert. Man liest ja 
viel und auch Beiträge, in denen behauptet wird, dass die Dinger nichts 
taugen.

Irre ist wie viele Parameter da einen Einfluß haben. Danke für Deine 
Geduld und den Crashkurs! :-D

Gruß AVRli...

von J. -. (Gast)


Lesenswert?

AVRli .. schrieb:
> Ich muss zugeben das ich die Sache mit dem Touch völlig unterschätzt
> habe.

Hatte ich anfangs auch, insbesondere die Druckauswertung schien erstmal 
'überflüssig'. Dann mal die Physik mit den Widerständen überlegt, 
gleichzeitig gesehen, daß die Pixel systematisch 'weglaufen', und dann 
viel Code gelesen (u.a. auch die anderen Vorschläge, die hier in Form 
von application notes etc. kamen) und für meine Zwecke optimiert und 
zusammengekocht. Es geht sicher besser, bzw. vielleicht sogar in sich 
"geschlossener". Sooo viele Parameter sind's ja auch nicht, wenn man mal 
das Wesentliche herausschält.

Übrigens ist der XPT m.E. nach nicht das Gelbe vom Ei. Mit den ADCs vom 
Prozessor direkt angeschlossen ging das Einlesen der Koordinaten besser 
und schneller. Allerdings habe ich keine Lust, alle XPTs abzulöten und 
die 4 Leitungen + Strombegrenzungswiderstände der Touchfolien zu 
verlegen, und manchmal werden auch die Prozessorpins knapp, da ist SPI 
schon sparsamer.
Nichts zu danken (also den anderen meinetwegen schon g), bin ja schon 
froh, wenn jemand anders noch C programmiert und nicht nur nach 
Arduino-Sketches fragt pfeif

Ja, die kapazitiven sollen besser/universeller sein, aber mit denen 
fange ich lieber nicht an, das ist zu kompliziert g. Viel Spaß noch 
beim Feinschliff.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.