PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 'Schiefes Koordinatensystem' begradigen



Jaecko
09.12.2008, 19:13
Moin.

Mal ein kleines mathematisches bzw. geometrisches Problem.
Von einem Touch-LCD werden die X/Y-Positionen über 2 ADC-Kanäle eingelesen.
Bisher hab ich es bei Tasten immer so gemacht, dass ich auf den Mittelpunkt des Tastenrands gedrückt hab und die jeweilige Position mit dem ADC-Wert bestimmt hab. Also der linke Rand einer Taste liegt z.B. auf 100, der rechte auf 200; oben auf 400, unten auf 500.
Damit weiss ich, dass die Taste gedrückt ist, wenn die Bedingung
((x >= 100) && (x <= 200)) || ((y >= 400) && (y <= 500)) zutrifft.

Ich möchte das Ganze jetzt so umbauen, dass ich nicht mehr bei jeder Taste die ADC-Werte "ausprobieren" muss, sondern dass ich die Position von der jeweiligen GetPos-Funktion gleich als Pixelwert bekomme.

Und da kommt schon das Problem: Fahr ich z.B. auf einer waagrechten Linie von links nach rechts, sollte der y-Wert ja gleich bleiben... tut er aber nicht.
Ich hab hier mal die ADC-Werte der 4 Eckpunkte (X / Y):

Position: X_ADC / Y_ADC (= X_Pixel / Y_Pixel)
Oben links: 101 / 145 (= 0, 0)
Oben rechts: 867 / 150 (= 127, 0)
Unten links: 102 / 759 (= 0, 63)
Unten rechts: 848 / 802 (= 127, 63)

Die Y-Werte ganz oben unterscheiden sich nur um 5 "Punkte", die ganz unten dafür schon um 43.
Wär die Abweichung immer die gleiche oder nur bei einer Achse, wäre es eigentlich kein Problem. Nur dass eben die Abweichung mit der Position selber "abweicht" macht mir irgendwie nen Knoten ins Rechenhirn...

Wie kann ich das ganze so begradigen, dass ich die erwarteten Pixelwerte krieg?

mfG

Vitis
09.12.2008, 20:01
entweder mathematisch indem du ne Funktion bildest
oder per lookup table

thewulf00
10.12.2008, 07:07
Im Prinzip hat Vitis Recht.
Aber wie wäre es, wenn Du von Deinem Touch auch die 2.Leitung abfragst?
Es funktioniert ja so, dass Du auf eine Ebene eine Spannung anlegst, und dann auf der 2.Ebene eine Seite/Leitung abfragst. Da liegt aber noch ne 2. rum. Probiers mal aus, dann hast Du nur ein "halbschiefes" Koordinatensystem.

mare_crisium
11.12.2008, 09:39
Jaecko,

leider ist die Aufgabe nur mit einer Iteration zu lösen (siehe angehängte pdf-Datei). Ich hab's mal mit Deinen Werten durchgespielt: Für den Punkt in der Mitte des schiefen Vierecks brauche ich 4 Iterationen um die Koordinaten im Zielrechteck mit einer Genauigkeit besser als 10^-4 zu berechnen.

Die schlechte Nachricht ist also, dass Du iterieren musst, die gute, dass es schnell geht. Erinnert mich irgendwie an meinen jüngsten Zahnarztbesuch... ;-).

Ciao,

mare_crisium

Edit: Anhang gelöscht wg. Upload-Quota.

thewulf00
11.12.2008, 13:20
@mare_crisium: Deine mathem. Herleitung finde ich schlüssig. Wobei ich mich frage, ob Dir das aus dem FF kam oder Du ne ganze Weile überlegen musstest.
Hattest Du ein solches Problem im Studium?

Jaecko
11.12.2008, 13:29
Thxle schon mal.
Sieht ja soweit nicht schlecht aus. Werd mir das ganze aber erst am Wochenende so richtig anschauen + verstehen können... und dann überlegen, wie ich das ganze AVR-gerecht verpack...
Vektorrechnung ist bei mir doch schon etwas länger her.

mare_crisium
12.12.2008, 15:43
@thewulf00,

nee, das hat mich auch einen Abend und einen Morgen gekostet, bis ich raus hatte, wie's geht. Eine besonders wichtige Quelle der mathematischen Eingebung war die morgentliche Dusche :-) .

@Jaecko,

wenn ich mein Modell in der Tabellenkalkulation angucke, dann kann ich Dir für die Umsetzung auf den AVR raten, die Kalibrierung folgendermassen durchzuführen:
1. Die Vektoren der vier Eckpunkte messen.
2. Den Vektor zum Mittelpunkt des schiefen Vierecks berechnen (ist einfach nur der Mittelwert aus den vier Eckpunkt-Vektoren)
3. Den Mittelpunkt-Vektor von den vier Eckpunkt-Vektoren abziehen und die Auswertung mit diesen "verkürzten" Vektoren durchführen. Dazu musst Du dann auch von allen gemessenen "Touch-Vektoren" den Mittelpunkt-Vektor abziehen.

Das hat den Vorteil, dass die maximal auftretenden Zahlenwerte so klein wie möglich gehalten werden. Spart Bytes und Rechenzeit - bzw. wie es früher bei "Dr. Dobb's Journal of Computer Calisthenics and Orthodontia" hiess: "Running Light, without Overbyte" ;-).

Sag' mal, ob's klappt.

mare_crisium

Jaecko
19.12.2008, 21:54
Also ich habs mir jetzt jeden Tag angeschaut.
Nur irgendwie... Mathe war noch nie meine Stärke. Wärs ein Blechviereck, könnt ichs mit entsprechenden Hammerschlägen schon so hinbiegen... nur hinrechnen *g*...

Das Grundproblem ist schon mal: Wie bring ich dem AVR Vektoren bei? Ich weiss, dass die Antwort darauf wohl trivial sein wird; also das typische Problem: Die Frage ist so leicht, dass man nicht draufkommt, weil man einfach zu kompliziert denkt.

(Und Matlab auf nem AVR zum laufen zu kriegen... naaaja...)

mare_crisium
20.12.2008, 17:43
Jaecko,

ich nehme gerade meine Grippe... :-( Sobald ich ohne zu Husten ein vollständiges Posting schreiben kann, melde ich mich wieder. Wir kriegen das schon noch hin.

Ciao,

mare_crisium

P.S.:
Vorab im Anhang die Tabellenkalkulation mit dem Algorithmus.

Edit: Anhang gelöscht wg. Upload-Quota

Jaecko
20.12.2008, 20:02
Gute Besserung. Nimm dir die Zeit, eilt nicht.
Liegen ja genügend Projekte rum, wo noch was zu tun ist *g*
(u.a. mal nen vernünftigen FAT-Treiber zum Laufen kriegen...)

Aber die Excel hilft schon mal ein Stück weiter. Thx.

Jaecko
21.12.2008, 10:15
Also ich hab mal den Algorithmus nachgebaut (zumindest versucht).

Eigentlich müsste er so laufen, nur ich erhalte als Positionen immer 0 / 0.




#define Iterations 5
#define LCD_Width 128
#define LCD_Height 64

// Calibration values; set with defaults
ui16_t r0_x = 101;
ui16_t r1_x = 867;
ui16_t r2_x = 848;
ui16_t r3_x = 102;
ui16_t r0_y = 145;
ui16_t r1_y = 150;
ui16_t r2_y = 802;
ui16_t r3_y = 759;



void TPAD_GetPosPrecise(ui8_t *xp, ui8_t *yp)
{
ui8_t cycle;
ui16_t x_raw;
ui16_t y_raw;
ui32_t main_det;
double W = 0; // iteration parameter
double LV_x = 0; // solving vector X
double LV_y = 0; // solving vector Y
double D_x = 0; // det. x
double D_y = 0; // det. y
double factor_x = 0;
double factor_y = 0;

TPAD_GetPos(&xraw, &yraw);

// calculate constant values for iteration:

// (r1_x - r0_x) = D20 (Excel cell D20)
// (r1_y - r0_y) = E20
// (r3_x - r0_x) = D21
// (r3_y - r0_y) = E21
// D = D20 * E21 - E20 * D21

main_det = ((r1_x - r0_x) * (r3_y - r0_y)) - ((r1_y - r0_y) * (r3_y - r0_y));

// (r - r0) = (x_raw - r0_x) = D23
// (r - r0) = (y_raw - r0_y) = E23
// (r0-r1)-(r3-r2) = (r0_x - r1_x) - (r3_x - r2_x) = D24
// (r0-r1)-(r3-r2) = (r0_y - r1_y) - (r3_y - r2_y) = E24

// Iteration:
for (cycle = 0 ; cycle < Iterations ; cycle++)
{
LV_x = (x_raw - r0_x) - (W * ((r0_x - r1_x) - (r3_x - r2_x))); // = D31
LV_y = (y_raw - r0_y) - (W * ((r0_y - r1_y) - (r3_y - r2_y))); // = E31

D_x = (LV_x * (r3_y - r0_y)) - (LV_y * (r3_x - r0_x)); // = D33
D_y = (LV_y * (r1_x - r0_x)) - (LV_x * (r1_y - r0_y)); // = E34

factor_x = D_x / main_det; // = D36
factor_y = D_y / main_det; // = E37
W = factor_x * factor_y;
}

*xp = (factor_x * (LCD_Width - 1));
*yp = (factor_y * (LCD_Height - 1));
}



Werd den Fehler natürlich weiter verfolgen.

mare_crisium
21.12.2008, 13:12
Jaecko,

ich hab noch zuviel Watte im Kopp um Deinen Code gründlich zu lesen, aber die Zeile

main_det = ((r1_x - r0_x) * (r3_y - r0_y)) - ((r1_y - r0_y) * (r3_y - r0_y));

müsste meiner Meinung nach

main_det = ((r1_x - r0_x) * (r3_y - r0_y)) - ((r1_y - r0_y) * (r3_x - r0_x));

heissen.

Ciao,

mare_crisium

Jaecko
21.12.2008, 18:13
Stimmt, da bin ich durcheinandergekommen.
Hab den Algorithmus jetzt mal neu aufgebaut und dabei noch einige "Fehler" im alten gefunden. U.a. hab ich zu wenig gecastet.
(ui16_t * ui16_t ist wieder ui16_t, obwohl z.B. eine ui32_t erwartet wird)

Jetzt funktionierts schon fast perfekt. Hier ist ein Video, in dem das Programm einfach gesagt nur folgendes durchführt:
- Hol die Rohwerte der Position.
- Berechne mit dem "mare_cirisum-Algorithmus" die echte Position
- Pinsel das Pixel an der entsprechenden Stelle weiss.

http://www.youtube.com/watch?v=fdpV7baRqgs

Wie man auf dem Video sieht, geht das in der linken Displayhälfte schon perfekt. Nur in der rechten ist noch ein kleiner Offset nach unten drin.
Ich vermute, dass ich da nochmal irgendwo nen Cast vergessen hab.
Lässt sich aber auch noch rausfinden.

Hier der neue Algorithmus:




// Those values are determined by a calibration procedure (touch all 4 corners)
// Here they are loaded with default values
ui16_t r0[2] = { 101, 145 };
ui16_t r1[2] = { 867, 150 };
ui16_t r2[2] = { 848, 802 };
ui16_t r3[2] = { 102, 759 };

// variables for precise algorithm; declared here to save stack memory
ui16_t r_raw[2]; // raw value vector
double W = 0; // Iteration parameter; Start value = 0
i16_t r1_r0[2]; // solution vector for r1 - r0
i16_t r3_r0[2]; // solution vector for r3 - r0
i16_t rraw_r0[2]; // solution vector for rraw - r0
i32_t D; // determinant
i32_t D_part[2]; // partial solution for determinant
double factor[2]; // solution vector factors
i16_t r01_r32[2]; // solution vector for (r0 - r1) - (r3 - r2)
double solVec[2]; // soluton vector
double D_XY[2]; // determinant D_X, D_Y


#define LCD_Width 128
#define LCD_Height 64
#define Iterations 4
#define X 0
#define Y 1


void TPAD_GetPosPrecise(ui8_t *xp, ui8_t *yp)
{
ui8_t step;

// Check if constant 'Iteration' is defined already. If not, use default value of 5.
#ifndef Iterations
#define Iterations 5
#endif

TPAD_GetPos(&r_raw[X], &r_raw[Y]); // get raw values via 'old' method (ADC-Values)
// r_raw[X] = 560; // test value
// r_raw[Y] = 200; // test value
// Constant values, needed for calculation; constant for a single iteration:

// r1-r0
r1_r0[X] = r1[X] - r0[X];
r1_r0[Y] = r1[Y] - r0[Y];

// r3-r0
r3_r0[X] = r3[X] - r0[X];
r3_r0[Y] = r3[Y] - r0[Y];

// Determinant
D_part[0] = (i32_t) r1_r0[X] * (i32_t) r3_r0[Y];
D_part[1] = (i32_t) r1_r0[Y] * (i32_t) r3_r0[X];
D = D_part[0] - D_part[1];

// r_raw - r0
rraw_r0[X] = r_raw[X] - r0[X];
rraw_r0[Y] = r_raw[Y] - r0[Y];

// (r0 - r1) - (r3 - r2)
r01_r32[X] = (r0[X] - r1[X]) - (r3[X] - r2[X]);
r01_r32[Y] = (r0[Y] - r1[Y]) - (r3[Y] - r2[Y]);

// Iteration Step 0
for (step = 0 ; step < Iterations ; step++)
{

// Solution vector
solVec[X] = (double) rraw_r0[X] - (W * (double) r01_r32[X]);
solVec[Y] = (double) rraw_r0[Y] - (W * (double) r01_r32[Y]);

// Determinant
D_XY[X] = -(((double) r3_r0[X] * solVec[Y]) - ((double) r3_r0[Y] * solVec[X]));
D_XY[Y] = ((double) r1_r0[X] * solVec[Y]) - ((double) r1_r0[Y] * solVec[X]);

// factor
factor[X] = (double) D_XY[X] / (double) D;
factor[Y] = (double) D_XY[Y] / (double) D;

// New iteration parameter:
W = factor[X] * factor[Y];
}
*xp = (ui16_t) (factor[X] * ((double) (LCD_Width - 1)));
*yp = (ui16_t) (factor[Y] * ((double) (LCD_Height - 1)));
}

mare_crisium
22.12.2008, 10:36
Hi, Jaecko,

auf Deinem Video sieht das schon ziemlich gut aus :-) ! Ich hätte auch nicht gedacht, dass die Umrechnung so schnell geht.

Mit meinen beschränkten C-Kenntnissen (bin ein Pascal-Veteran) habe ich in Deinem Programm keinen Fehler gefunden. Der Sprung in der rechten Hälfte des Touchscreens könnte imho daher kommen, dass ein signed Typ als unsigned interpretiert wird oder umgekehrt... In diesem Sinne kommen mir die Zeilen

*xp = (ui16_t) (factor[X] * ((double) (LCD_Width - 1)));
*yp = (ui16_t) (factor[Y] * ((double) (LCD_Height - 1)));

verdächtig vor.

Ciao,

mare_crisium

Jaecko
23.12.2008, 19:22
Sooo... jetzt gehts. Dieser Fehler in der rechten Hälfte war ein "Fehler" in der Kombination Algorithmus + Displayansteuerung. War manchmal so, dass es ging und der Displayinhalt plötzlich als ganzes verschoben wurde. Also konnts kein Rechenfehler sein (da ja bereits gezeichnete Pixel nicht verändert werden).

Im Algorithmus können als Endergebnis Positionen rauskommen, die ausserhalb des Display-Bereichs liegen (u.a. häufiger "inf"). Da das Display ja nur 128x64 Pixel hat, scheints der Treiber nicht zu packen, wenn er grössere bzw. unendliche Werte kriegt.

Packt man in die Funktion unter die Zuweisungen von *xp und *yp noch die folgenden Zeilen, dann gehts (bis auf wenige Ausreisserpixel, die aber im Video auch zu sehen sind) fehlerfrei.



*xp = (i16_t) (factor[X] * ((double) (LCD_Width - 1)));
*yp = (i16_t) (factor[Y] * ((double) (LCD_Height - 1)));

// prevent 'tilt' of display driver by eliminating invalid values
if (*xp > (LCD_Width - 1))
{
*xp = LCD_Width - 1;
}
if (*yp > (LCD_Height - 1))
{
*yp = LCD_Height - 1;
}



(Ein neues Video folgt demnächst)

mare_crisium
24.12.2008, 05:26
Na, Jaecko,

prima, dass es jetzt läuft :-) ! Was meinst Du mit "häufiger inf"? Division durch Null?

Bin gespannt auf das nächste Video. Zeichne mal einen Weihnachtsbaum!

Frohe Weihnacht

mare_crisium

Jaecko
24.12.2008, 08:32
Hier mal der Baum... keine Schönheit, aber glaub man erkennts:
http://www.youtube.com/watch?v=wPJbjVy5GlQ

Ich hab mir in der Funktion mal die Werte von xp/yp bzw. factor[n] ausgeben lassen. Stellenweise ist es so, dass dort statt dem eigentlichen Wert (der auch dann stimmt, wenns am Bildschirm falsch dargestellt ist), "inf" drinsteht. Und sobald dieses "inf" zum ersten Mal auftaucht, spinnt das Display.

Das komische: Die einzige Division ist durch die Determinante... und die ist durch die vorgegebenen Werte aber konstant != 0.

Nen Pipelineeffekt halt ich jetzt mal für unwahrscheinlich.
(also, dass die Berechnung schon ausgeführt wird, während ein vorheriges Ergebnis noch nicht fertig ist)

Ebenfalls frohe Weihnachten.

hacker
24.12.2008, 08:40
Hast du dir mal die ADC Werte ausgeben lassen und die dazugehörigen Ausreiserpixelpositionen? Sind das Messfehler vom ADC?

Jaecko
24.12.2008, 09:09
Die ganzen Werte stimmen. Der Fehler scheint erst bei der Division aufzutreten, und da eben auch nicht immer.

Und auch wenn andere ADC-Werte kommen, passiert rein mathematisch nichts "schlimmes". Die Zielkoordinaten sind dann einfach woanders, aber nicht unendlich.

Im grossen und ganzen funktionierts ja, und wenn man weiss, dass man unendliche Werte abfangen/ignorieren muss, dann isses eh perfekt.

mare_crisium
24.12.2008, 10:36
Jaecko,

Na, das ist doch eine schöner Baum - sogar mit ein bisschen Schneegestöber (vor allem auf der rechten Seite) :-) !

Um einen pile-up-Effekt noch sicherer auszuschliessen, würde ich die Berechnung der unveränderlichen Grössen (z.B. der Determinante) nur einmal, nämlich beim Kalibrieren des Touchscreens, ausführen und sie in globalen Variablen speichern. Das verringert die Rechenzeit für TPAD_Get_PosPrecise und beugt etwelchen pile-ups vor. Statt des Wertes D der Determinante würde ich (1/D) speichern, so dass in der Routine nur multipliziert werden muss.

Mathematisch gesehen, wird die Determinante nur dann Null, wenn das Eingabeviereck echt krank verzerrt ist, z.B. so, dass zwei Seiten zusammenfallen oder dass eine Seite fast auf Null zusammengeschnurrt ist. Bei Werten, die im normalen Betrieb auftreten, sind die beiden Elemente in der Hauptdiagonalen immer grösser als Null und immer deutlich grösser als die beiden anderen - das sind optimale Bedingungen für endliche Lösungen.

Ciao,

mare_crisium

thewulf00
30.12.2008, 10:14
Also ich muss sagen: mare_crisium: RESPEKT! Es funktioniert sogar. Danke für Deine Zeit, ich werde sicher auch davon profitieren.

Jaecko
30.12.2008, 13:20
So... hab nun noch etwas am Code rumgebastelt.
Die Get-Funktion liefert nun neben der Position auch einen Rückgabewert, ob die Positionen verwertbar sind (return 1) oder ungültig (unendlich, ausserhalb des Displaybereichs etc; return 0).
Somit gibts nun eigentlich keine Fehlpositionen mehr (ausser man drückt zu lasch drauf, dass es zwischen den beiden Touchfolien keinen richtigen Kontakt gibt, aber da hilft dann auch kein noch so guter Algorithmus mehr).

Hier mal die relevanten Ausschnitte aus den Sourcefiles:

touchpad_cfg.h


#ifndef _TOUCHPAD_CFG_H_
#define _TOUCHPAD_CFG_H_

// Those can be determined by a calibration procedure (touch all 4 corners)
// Here they are loaded with default values
ui16_t r0[2] = { 101, 145 };
ui16_t r1[2] = { 867, 150 };
ui16_t r2[2] = { 848, 802 };
ui16_t r3[2] = { 102, 759 };


#define LCD_Width 128 // Display width in pixels
#define LCD_Height 64 // Display height in pixels
#define Iterations 5 // Iteration steps for determining the exact position
#define X 0 // Vector index for X-Coordinates
#define Y 1 // Vector index for Y-Coordinates


// select method for calculation with determinant:
//#define DETERMINANT_DIVISION
#define DETERMINANT_MULTIPLICATION

#ifdef DETERMINANT_DIVISION
#ifdef DETERMINANT_MULTIPLICATION
#error "Only one method for determinant allowed: MULTIPLICATION or DIVISION!"
#endif
#endif

#ifndef DETERMINANT_DIVISION
#ifndef DETERMINANT_MULTIPLICATION
#error "One method for determinant has to be chosen: MULTIPLICATION or DIVISION!"
#endif
#endif

#endif


touchpad.h


#ifndef _TOUCHPAD_H_
#define _TOUCHPAD_H_

#define POSITION_VALID 1
#define POSITION_INVALID 0

ui8_t TPAD_Pressed(void);
ui8_t TPAD_GetPosPrecise(ui8_t *xp, ui8_t *yp);
void TPAD_Calibrate(void);
#endif




touchpad.c


#include "touchpad.h"
#include "touchpad_cfg.h"

// variables for precise algorithm; declared here to save stack memory
ui16_t r_raw[2]; // raw value vector
double W = 0; // Iteration parameter; Start value = 0
i16_t r1_r0[2]; // solution vector for r1 - r0
i16_t r3_r0[2]; // solution vector for r3 - r0
i16_t rraw_r0[2]; // solution vector for rraw - r0
i32_t D; // determinant
double D_inv; // 1 / determinant;
//i32_t D_part[2]; // partial solution for determinant
double factor[2]; // solution vector factors
i16_t r01_r32[2]; // solution vector for (r0 - r1) - (r3 - r2)
double solVec[2]; // soluton vector
double D_XY[2]; // determinant D_X, D_Y


static inline void _delay4Cycles(ui16_t __count)
{
if (__count == 0)
{
__asm__ __volatile__("rjmp 1f\n 1:");
}
else
{
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
}

#define delay(us) _delay4Cycles(((F_CPU / 4000)*us)/1000)

void TPAD_Calibrate(void)
{
// The used delay-command is needed to minimize pipeline-effects
// and therefore to prevent calculation errors.

// Constant values, needed for calculation; constant for an iteration:
// r1-r0
r1_r0[X] = r1[X] - r0[X];
delay(1);
r1_r0[Y] = r1[Y] - r0[Y];
delay(1);

// r3-r0
r3_r0[X] = r3[X] - r0[X];
delay(1);
r3_r0[Y] = r3[Y] - r0[Y];
delay(1);

// Determinant
D = ((i32_t) r1_r0[X] * (i32_t) r3_r0[Y]) - ((i32_t) r1_r0[Y] * (i32_t) r3_r0[X]);
delay(1);

#ifdef DETERMINANT_MULTIPLICATION
D_inv = (double) 1 / (double) D;
delay(1);
#endif

// (r0 - r1) - (r3 - r2)
r01_r32[X] = (r0[X] - r1[X]) - (r3[X] - r2[X]);
delay(1);
r01_r32[Y] = (r0[Y] - r1[Y]) - (r3[Y] - r2[Y]);
delay(1);
}


ui8_t TPAD_GetPosPrecise(ui8_t *xp, ui8_t *yp)
{
// Thanks to mare_crisium for providing the mathematical algorithm

ui8_t step;
ui8_t retval;

TPAD_GetPos(&r_raw[X], &r_raw[Y]); // get raw values via 'old' method (ADC-Values)

// r_raw - r0
rraw_r0[X] = r_raw[X] - r0[X];
rraw_r0[Y] = r_raw[Y] - r0[Y];

// Iteration loop
for (step = 0 ; step < Iterations ; step++)
{
// Solution vector
solVec[X] = (double) rraw_r0[X] - (W * (double) r01_r32[X]);
solVec[Y] = (double) rraw_r0[Y] - (W * (double) r01_r32[Y]);

// Determinant
D_XY[X] = -(((double) r3_r0[X] * solVec[Y]) - ((double) r3_r0[Y] * solVec[X]));
D_XY[Y] = ((double) r1_r0[X] * solVec[Y]) - ((double) r1_r0[Y] * solVec[X]);

// factor
#ifdef DETERMINANT_DIVISION
factor[X] = (double) D_XY[X] / (double) D;
factor[Y] = (double) D_XY[Y] / (double) D;
#endif

#ifdef DETERMINANT_MULTIPLICATION
factor[X] = (double) D_XY[X] * (double) D_inv;
factor[Y] = (double) D_XY[Y] * (double) D_inv;
#endif

// New iteration parameter:
W = factor[X] * factor[Y];
}

*xp = (i16_t) (factor[X] * ((double) (LCD_Width - 1)));
*yp = (i16_t) (factor[Y] * ((double) (LCD_Height - 1)));

// check if values are valid
if ((*xp > (LCD_Width - 1)) || (*yp > (LCD_Height - 1)))
{
// values invalid: return 0
retval = POSITION_INVALID;
}
else
{
// values valid: return 1
retval = POSITION_VALID;
}
return(retval);
}



Von der Anwendung her siehts dann z.B. so aus:


...
ui8_t x;
ui8_t y;
...
if (TPAD_Pressed()) // Funktion zum Prüfen, ob die AD-Werte > 0 sind.
{
if(TPAD_GetPosPrecise(&x, &y))
{
if ((x > 0) && (x < 15) && (y > 10) && (y < 26))
{
mach wat;
}
}
}
...

michiE
31.12.2008, 00:25
Ein anderer Ansatz wäre das Gram-Schmidtsche Orthogonalisierungsverfahren gewesen.
(Könnte auch sein dass hier sowas schon erwähnt wurde,bin bissle müde und verpeilt) aber hier gibts mal nen kleinen Link zum Thema:

http://de.wikipedia.org/wiki/Gram-Schmidtsches_Orthogonalisierungsverfahren

lg
Michi