Also ich muss sagen: mare_crisium: RESPEKT! Es funktioniert sogar. Danke für Deine Zeit, ich werde sicher auch davon profitieren.
Druckbare Version
Also ich muss sagen: mare_crisium: RESPEKT! Es funktioniert sogar. Danke für Deine Zeit, ich werde sicher auch davon profitieren.
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
touchpad.hCode:#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
Code:#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
Code:#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:
Code:...
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;
}
}
}
...
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-Sc...rungsverfahren
lg
Michi