Forum: Mikrocontroller und Digitale Elektronik ADS7843 Werte berechnen


von Constantin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ich versuche den Touchscreen zu kalibrieren Touch Controller ist 
ein ADS7843.

Wenn ich die werte so lasse in Coordinate DisplaySample dann kann ich 
denn Touch Calibrieren das geht aufn 320x240 Display.

Mein Display ist aber ein 800x480 Display,da Funktioniert das nicht so 
gut,ändere ich die werte für mein Display(800x480)
auf 45,45
    755,45
    400,240

So kann ich kein abgleich mehr machen.

kann mir einer weiterhelfen.
mfg
1
Coordinate DisplaySample[3] =   {
2
                                { 45, 45 },
3
               { 45, 270},
4
                                { 190,190}
5
                          } ;

von Lattice User (Gast)


Lesenswert?

long double?
Wirklich?
1
typedef struct Matrix 
2
{            
3
long double An,  
4
            Bn,     
5
            Cn,   
6
            Dn,    
7
            En,    
8
            Fn,     
9
            Divider ;
10
} Matrix ;
Ist das wirklich aus dem Orginal?


Das Problem liegt vermutlich in Zeilen wie dieser:
1
    matrixPtr->An = ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - 
2
                    ((displayPtr[1].x - displayPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ;

Die linke Seite des = ist zwar long double, rechts davon ist aber 
alles uint16_t. Vermutlich gibt es einen Überlauf bei dem grösseren 
Display. Auch müssen die Punkte so gewählt werden, dass kein Ergebnis 
dieser Gleichungen negativ ist.

von Constantin (Gast)


Lesenswert?

Lattice User schrieb:
> long double?
> Wirklich?typedef struct Matrix
> {
> long double An,
>             Bn,
>             Cn,
>             Dn,
>             En,
>             Fn,
>             Divider ;
> } Matrix ;
>
> Ist das wirklich aus dem Orginal?

Ja das war mit auf der CD zu diesen Board.



>
> Das Problem liegt vermutlich in Zeilen wie dieser:    matrixPtr->An =
> ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y -
> screenPtr[2].y)) -
>                     ((displayPtr[1].x - displayPtr[2].x) *
> (screenPtr[0].y - screenPtr[2].y)) ;
>
> Die linke Seite des = ist zwar long double, rechts davon ist aber alles
> uint16_t. Vermutlich gibt es einen Überlauf bei dem grösseren Display.
> Auch müssen die Punkte so gewählt werden, dass kein Ergebnis dieser
> Gleichungen negativ ist.

wie müsste ich dann die Gleichung anpassen damit wie sie sagten das 
Ergebniss nicht Negativ wird.

Für eine Antwort währe ich sehr Dankbar
mfg

von Lattice User (Gast)


Lesenswert?

Constantin schrieb:
> Lattice User schrieb:
>> long double?
>> Wirklich?typedef struct Matrix
>> {
>> long double An,
>>             Bn,
>>             Cn,
>>             Dn,
>>             En,
>>             Fn,
>>             Divider ;
>> } Matrix ;
>>
>> Ist das wirklich aus dem Orginal?
>
> Ja das war mit auf der CD zu diesen Board.
>
>

Dann stammt es von jemanden der schnell mal etwas zusammengeschustert 
hat. Man braucht dafür kein Floatingpoint, und schon gar nicht long 
double.

Auf die Schnelle mal
1
typedef  struct POINT 
2
{
3
   uint16_t x;
4
   uint16_t y;
5
}Coordinate;

durch
1
typedef  struct POINT 
2
{
3
   int32_t x;
4
   int32_t y;
5
}Coordinate;

ersetzen. Sollte das Overflow und auch das Vorzeichenproblem lösen.
Bei dem ganzen Floatingpoint Mist macht das auch nichts mehr aus.

Auf Dauer sich mit der Auswertung von resistiven Touch vertraut machen 
und
selbst implementieren. Google ist da sicher behilflich.

von Karl H. (kbuchegg)


Lesenswert?

Lattice User schrieb:

> Dann stammt es von jemanden der schnell mal etwas zusammengeschustert
> hat. Man braucht dafür kein Floatingpoint, und schon gar nicht long
> double.

long double ist vermutlich etwas übertrieben.
Floating Point wird der Autor genommen haben um Nichtlinearitäten aus 
dem Display rausrechnen zu können.

von Constantin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
So ich hab das für mein 7Inch Display mal angepasst ich kann den Toch 
auch Kalibrieren Funktioniert.

so wenn ich etwas Zeichnen will auf das Display hab ich in Y immer eine 
Differenz.
In X pass der Touch einwandfrei.
1
  while (1)  
2
  {
3
    getDisplayPoint(&display, Read_Ads7846(), &matrix ) ;
4
    TP_DrawPoint(display.x,display.y+440);
5
  }

zb. drücke ich den Touch bei x350 und Y460 zeichnet er mir in Y schon 
bei 470
und bei Y20 zeichnet er mir Y10.

Wie kann ich diese Differenz in Y beseitigen.

mfg

von Karl H. (kbuchegg)


Lesenswert?

Indem du erst mal die +440 weglässt und dann dem nachgehst, was 
LCD_DrawPoint macht.

von Karl H. (kbuchegg)


Lesenswert?

> drücke ich den Touch bei x350 und Y460

wie hast du das verifiziert?

Vorgehensweise:
mittels TP_DrawPoint erst mal ein paar Punkte aufs LCD zaubern und 
visuell kontrollieren, ob die Koordinaten stimmen können bzw. plausibel 
sind. Auch darauf achten, in welcher Ecke der 0-Punkt liegt und in 
welche Richtung die positive Koordinatenachse verläuft.

Dann machst du mittels TP_DrawPoint einen Punkt an eine bestimmte 
Koordinate (zb 100/100). WEnn du dann da drauf drückst muss dir deine 
Touch-Funktion auch die 100/100 liefern (mit ein wenig Abweichung, denn 
so genau wirst du nicht drücken können). WEnn nicht, dann ist in deiner 
Rückrechnung noch was faul: Kontrollieren, indem man sich die Werte in 
der kompletten Berechnungskette ansieht und nachrechnet

Ja, so ist das nun mal. Progrmmieren heisst nicht nur, sich fertigen 
Code besorgen, drauf spielen und alles ist gut.

von Constantin (Gast)


Lesenswert?

Mit der Rückrwchnung da hab ich ja noch probleme.

Ich sehe ja wenn ich mit dem Touchstift über den Touch gehe,wirden ja 
gleich die pixel gezeichnet.
in X stimmt es ja nur in Y gibs eine Differenz.
Ich mache nachher mal ein video.
Danke.
mfg

von Karl H. (kbuchegg)


Lesenswert?

Constantin schrieb:
> Mit der Rückrwchnung da hab ich ja noch probleme.
>
> Ich sehe ja wenn ich mit dem Touchstift über den Touch gehe,wirden ja
> gleich die pixel gezeichnet.
> in X stimmt es ja nur in Y gibs eine Differenz.
> Ich mache nachher mal ein video.

brauchst du nicht. sieh dir die werte an. und zwar von vorn, beginnend 
mit den adc werten bzw. den Faktoren in der Umrechnungsmatrix. 
Insbesondere musst du bei einem Druck auf deine Kalibrierpunkte genau 
die von dir vorgegebenen Pixelwerte zurückgerechnet bekommen.
Alles andere bringt nichts, da kannst du Videos machen soviel du willst 
und rumdrücken so viel du willst. Das ist nur verschwendete Zeit.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Um es klar zu sagen:
Hier an dieser Stelle
1
void TouchPanel_Calibrate(void)
2
{
3
...
4
  setCalibrationMatrix( &DisplaySample[0],&ScreenSample[0],&matrix ) ;

muss danach die Rückrechnung
1
...
2
  Coordinate P1, P2, P3;
3
4
  getDisplayPoint( &P1, &ScreenSample[0], &matrix );
5
  getDisplayPoint( &P2, &ScreenSample[1], &matrix );
6
  getDisplayPoint( &P3, &ScreenSample[2], &matrix );
7
8
...

genau die von dir vorgegebenen Punkte
1
Coordinate DisplaySample[3] =
2
{
3
  { 45, 45 },
4
  { 45, 270},
5
  { 190,190}
6
} ;
ergeben. Ansonsten sind die Werte in deiner Matrix falsch bzw. bei 
irgendeiner der Berechnungen zur Erlangung der Matrix läuft was über. In 
dem Fall zb. mal die Berechnung von den Ausgangswerten her mit einem 
Tschenrechner nachvollziehen und die Zwischenwerte notieren (und auch 
mit dem Taschenrechner kontrollieren, ob die Rückrechnung mit der auf 
dem Taschenrechner gewonnenen Matrix zu den DisplaySamples Punkten 
passt). Danach mit den Werten vergleichen, die in deinem Programm 
tatsächlich während des Rechengangs zur Gewinnung der Matrix auftauchen.

: Bearbeitet durch User
von constantin (Gast)


Lesenswert?

Meine Werte sind:
 45,  45  =  320, 3545
745,  45  = 3694, 3469
400, 434  = 2025,  606





1
Coordinate DisplaySample[3] =   {
2
                                            {  45, 45},
3
              { 754, 45},
4
                                            { 400,434}
5
                              } ;
6
7
void TouchPanel_Calibrate(void)
8
{
9
  u8 i;
10
  Coordinate * Ptr;
11
  Coordinate P1, P2, P3;
12
  
13
  ssd1963_Clear(BLACK);
14
  for(i=0;i<3;i++)
15
  {
16
   //ssd1963_Clear(BLACK);
17
   WriteString(10,10,"Touch crosshair to calibrate",0xffff,BLACK);
18
   Delay1(50);
19
   DrawCross(DisplaySample[i].x,DisplaySample[i].y);
20
   do
21
   {
22
   Ptr=Read_Ads7846();
23
   }
24
   while( Ptr == (void*)0 );
25
   ScreenSample[i].x= Ptr->x; ScreenSample[i].y= Ptr->y;
26
   
27
   LCD_ShowNum(0,400,ScreenSample[i].x,6,RED,BLACK);
28
   LCD_ShowNum(0,440,ScreenSample[i].y,6,RED,BLACK); 
29
  
30
  }
31
  setCalibrationMatrix( &DisplaySample[0],&ScreenSample[0],&matrix ) ;     
32
  //ssd1963_Clear(BLACK);
33
}

von Karl H. (kbuchegg)


Lesenswert?

constantin schrieb:
> Meine Werte sind:
>  45,  45  =  320, 3545
> 745,  45  = 3694, 3469
> 400, 434  = 2025,  606

Ja. ok.
Und? Weiter?

Was ergibt sich daraus für eine Matrix? Welche Koordinaten kommen raus, 
wenn du genau diese ScreenSample Werte durch die Matrix jagst und zurück 
rechnen lässt?

Du musst schon ein bisschen mitarbeiten. Ansonsten kannst du es auch 
lassen. Ich seh meinen Job hier nicht darin, mit dir Ferndebugging bis 
runter auf die Statement-Ebene zu machen und dir beibringen zu müssen, 
wie man eigentlich an Debugging rangeht. Wenn du von dir aus nicht 
gewillt bist, zu ergründen wie und warum das funktioniert, wie die Mathe 
dahinter arbeitet, dann lassen wir es.

: Bearbeitet durch User
von constantin (Gast)


Lesenswert?

An = 0
Bn = 151122
Cn = 21732
Dn = 0
En = 184894
Fn = 504048

von Karl H. (kbuchegg)


Lesenswert?

Die ganze Rückrechnung ist nichts anders als eine lineare Gleichung
1
   display.x = a * screen.x + b * screen.y + c;
2
   display.y = d * screen.x + e * screen.y + f;

(und einen zusätzlichen Divisor hat er noch eingeführt, wohl zur 
Vorbereitung für die Umstellung von Floating Point auf 
Fixkommaarithmetik).
Aber mehr steckt da nicht dahinter. Die entscheidende Komponente ist die 
Bestimmung der Koeffizienten a, b, c, d, e und f (und natürlich des 
Divisors, weil er benutzt wird). Wenn die nicht korrekt sind, dann geht 
das eben schief. Also muss man sich die Bestimmung dieser Koeffizienten 
ansehen, wo da das Problem entsteht. Das schafft man aber nicht, in dem 
man sich stundenlang irgendwelche Bildchen hinmalen lässt, sondern indem 
man sich die Zahlen, Zwischenergebnisse ansieht und vor allen Dingen im 
Vorfeld bestimmt, welches eigentlich dir richtigen Zwischenergebnisse 
sein müssten. Dazu muss man aber wiederrum verstehen, wie man das obige 
Gleichungssystem lösen kann, wenn man 3 Wertepaare hat. Mit 3 
Wertepaaren lassen sich somit 6 Gleichungen aufstellen - 6 Gleichungen 
mit 6 Unbekannten (a,b,c,d,e,f) und das wiederrum ist lösbar.

>
>
1
> An = 0
2
> Bn = 151122
3
> Cn = 21732
4
> Dn = 0
5
> En = 184894
6
> Fn = 504048

das kann nicht stimmen. A kann schon mal nicht 0 sein. Und E müsste 
negativ sein.
Wie gross ist der Divider?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> das kann nicht stimmen. A kann schon mal nicht 0 sein. Und E müsste
> negativ sein.

Bist du sicher, dass deine Ausgaberoutinen korrekt sind und du die zum 
Datentyp in Matrix passenden benutzt hast?

von Karl H. (kbuchegg)


Lesenswert?

Zusammen mit dem hier
1
typedef  struct POINT 
2
{
3
   uint16_t x;
4
   uint16_t y;
5
}Coordinate;

ergibt das hier
1
    matrixPtr->En = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].y - displayPtr[2].y)) - 
2
                                                          ********************************

mit den Werten
1
45, 45   = 320, 3545
2
745, 45  = 3694, 3469
3
    *****
4
400, 434 = 2025, 606
5
    ****
ein negatives Ergebnis. Das Ergebnis kann aber nicht negativ sein, wegen 
dem uint16_t Datentyp von screenPtr.

Da haben wir schon mal die Erklärung, warum von den Y-Werten keiner 
negativ ist, was er aber sein müsste, damit sich die reverese 
Abhängigkeit der Y-Werte
1
45   ->   3469
2
434  ->   606
3
4
ja größer der Wert links, desto kleiner der Wert rechts
ergeben kann.

Da muss also zumindest mal irgendwo ein Umstieg auf einen signed 
Datentyp rein. (und um ehrlich zu sein, würde ich die uint16_t in 
Coordinate auf int16_t wechseln. Auch wenn es scheinbar unsinnig ist, 
negative Display Koordinaten zu haben, so vereinfacht sich vieles, wenn 
sie es sein können und man eine Linie von den Koordinaten -10/-50 zu den 
Koordinaten 400/300 ziehen kann und das Display zeigt nur den davon 
sichtbaren Ausschnitt an. Dazu bräuchte es allerdings wieder ein 
Clipping und damit beginnt dann für dich der Rattenschwanz an 
Grafik-Funktionen und der Grund, warum man Computer Grafik nicht einfach 
aus der hohlen Hand schütteln kann, auch wenn es simpel ist einen 
einzelnen Punkt zu setzen und alles andere darauf aufbaut.

: Bearbeitet durch User
von constantin (Gast)


Lesenswert?

dann werd ich mich den Nachmittag hinsetzen und das Stück für Stück 
durchgehen .

von Karl H. (kbuchegg)


Lesenswert?

Das hier
1
Coordinate DisplaySample[3] =   {
2
                                { 45, 45 },
3
               { 45, 270},
4
                                { 190,190}
5
                          } ;

waren die Originalwerte?

Dann hast du hier
1
auf 45,45
2
755,45
3
400,240
aber eine andere Punktanordnung

Du kannst nicht einfach Punkte so anordnen, wie es dir Spass macht! Da 
steckt eine Abhängigkeit in den Oririginaldaten!
1
Coordinate DisplaySample[3] =   {
2
               { 45, 45 },     <- Punkt rechts oben
3
               { 45, 270},     <- x bleibt gleich, aber in y gehts nach unten (bzw. oben)
4
               { 190,190}      <- diagonal gegenüber von rechts/oben
5
                          } ;

Der Code zur Ermittlung der Matrix geht von dieser Anordnung aus! Wenn 
du die anders machst, dann stimmt nichts mehr. Beachte auch die 
impliziten Größer/Gleich Beziehungen, die da in den Originaldaten 
drinnen steckt. Die sind wichtig, damit sich in den Zwischenergebnissen 
bei der Bestimmung der Matrix kein negatives Ergebnis ergibt.
45 ist kleiner als 190, wohingegen 190 wiederrum kleiner als 270 ist. 
Diese Abhängigkeit ist mit ziemlicher Sicherheit nicht ohne Grund so 
gewählt (ohne das ich jetzt die Berechnungen in der getMatrix Funktion 
näher aufgedröselt hätte. Ändert aber nichts daran, dass die E 
Komponente im Eregebnis negativ sein müsste. Sonst kommt die 
Reverse-Beziehung in der Y Komponente nicht raus)
1
             +---  45      45 ----+
2
      gleich +---  45     270 ----+ größer
3
      größer +--- 190     190 ----+ kleiner

: Bearbeitet durch User
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.