Can't solve wrong touch coordinates on a 3.5" screen

The transformation matrix values are floats so you should be able to compensate for a linear response.

Alright, I’ll fiddle around with the values later and come back with a result.

Edit: I think I first need to understand what’s going on under the hood, X11, 99-calibration.conf etc. Simply changing the numbers in the matrix in /zynthian/zynthian-sys/custom/display/PiScreen 3.5 (v2)/config/zynthian_custom_config.sh didn’t have any effect (not even flipping the axes) so need to look elsewhere.

1 Like

@hal80,

I just submitted a feature request for that :

In case you want to add some additionnal interesting inputs in the conversation.

2 Likes

If it helps any, this is what I do to get those screens working.

In the Zynthian Menu, add it as a Piscreen 3.5 (V2)

Open this file.
/zynthian/config/zynthian_custom_config.sh

And add this line to fix the screen issue.
DISPLAY=:0 xinput --set-prop ‘ADS7846 Touchscreen’ ‘Coordinate Transformation Matrix’ 1 0 0 0 -1 1 0 0 1

Reboot.

1 Like

Hi @Tubbritt, thanks for the reference to this second zynthian_custom_config.sh. Making changes there do actually affect the touch behaviour, as opposed to the file with the same name in /zynthian/zynthian-sys/custom/display/PiScreen 3.5 (v2)/config/.
At least now we know where to attack :slightly_smiling_face:.

For me, the matrix to start with is -1 0 1 0 -1 1 0 0 1. (x and y axes have correct orientation). When I do 1 0 0 0 -1 1 0 0 1 it results in a flipped x axis.
It’s just about picking the right values. As @wyleu pointed out these values are floats. According to my gut feeling the result should look something like -a1 0 a3 0 -b2 b3 0 0 1 with the constants around 1 ± something.

BTW, reboot is actually not necessary.
systemctl restart zynthian is quicker and keeps you logged in via ssh. For all who want to give it a try.

1 Like

Hi,

it is no so easy to see what is binary structure (exponent, significant field, sign, …) within these matrix values. So, it is not so intuitive to understand that these value are close to 1 ± something.

Could you elaborate ?

Hi, well, it’s just my gut feeling that comes from being a physicist :wink:
Let me just briefly explain. It’s about so called affine projections (you can google it) which are used to map a point or rather a vector (which defines that point by two coordinate numbers in space, i.e. in x-y-plane) to a new position.
Now, these 9 numbers which are written in a single row in the config file, actually make up a matrix which connects the output vector (new point, the point where we want the touch point to be) with the input vector (original point, the point where touch is recorded now) by means of matrix multiplication which in turn is composed of matrices for offset (translation), rotation and scaling. We need scaling and offset here.

In our special case, and according to the nomenclature given here https://wiki.archlinux.org/index.php/Calibrating_Touchscreen we can actually assign a meaning to these numbers.
We have the matrix

[ c0 0  c1 ]
[ 0  c2 c3 ]
[ 0  0  1  ]

which is equivalent to c0 0 c1 0 c2 c3 0 0 1 in our config file

where

  • c0 defines scale factor along x (horizontal) axis,
  • c2 defines scale factor along y (vertical) axis,
  • c1 defines x offset
  • c3 defines y offset.

All these numbers are defined relative to total width and total height according to the above link and this is why the new numbers should be close to 1. For example, introducing an offset to the right by 10 % of the total width (and c1 = 1) would result in the new c1 being 1.1. The nice thing about these matrix operations is that they do not only affect a single point in the x-y plane but all points that are thrown at it. You have to imagine it like pushing a sheet of paper around on a table (i.e. offset, translation), or like pulling on a stretchy piece of cloth on one end while the other end is fixed (i.e. scaling).

Just one remark about the minus signs - they come from the matrix operations for flipping and rotating the axes. As they appear in steps of 90 degrees these numbers are 1 or -1 or 0. It comes from the sin or cos function of the angle of rotation which yields 1, 0, -1 at multiples of 90 degrees but could also give any number inbetween at other angles. Which we don’t want :wink:

Now the only thing I’m uncertain about is, where is actually the corner (0,0).
Is it centered at (screen_witdh / 2, screen_height/2) or is it at screen pixel (0,0) (would that be upper left corner?) or does it have it’s own reference frame…

3 Likes

Thank you, it is very clear and it works.

“bash zynthian_custom_config.sh” allows testing values without restarting the UI.
Then trial and error can be done in the " * 5.7.1 XY-Controller" mode.

My only concern now is that zynthian_custom_config.sh doesn’t seem to be executed during boot sequence. Any clue ? Edit : If I go to webconf/hw-display and save then the change becomes permanent. :grinning:

hi guys…
After several tryouts and possible solutions, today misteriously worked this combination, mixing some random solutions here reported:
choosing waveshare 4A GPIO only and using this string:

dtoverlay=waveshare35a:rotate=90
display_rotate=1
My chinese display finally got right touch coordinates
For those who ask for lcd type:

actually could be one of thousands clone lcd of whatever kind or type :laughing:
it’s really a weird condition

4 Likes

Maybe someone still stuck with issues can check if this is really a possible solution (even changing dtoverlay. Honestly i continue to doubt i really succeded with a so simple solution… after hours of struggling (before writing this topic…)

I’ve fired up zynthian-touch.local . . .

image

and added

It’s reversed from what I completely personally treat as the normal way. ( Edge with no connectors down …) and the cursor tracks in the NW & SE corners but is reversed NE & SW…

but the whole element of describing this gets complicated !

1 Like

But a quick change of the rotate angle, (rotate=90 → rotate=270)

Puts it the right way up in my world ( not the main issue but, far easier for me to work with.)

Now we have SW& NE right with NW & SE reversed and a cross over point in the middle of the screen.

But the magic line doesnt seem as effective. . .
(Don’t forget the export DISPLAY=:.0 oherwise you will learn all about the X11 set up of the Putty window in your laptop!!)

root@zynthian-touch:~# export DISPLAY=:0.0
root@zynthian-touch:~# xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ ADS7846 Touchscreen id=6 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
root@zynthian-touch:~# xinput set-prop ‘ADS7846 Touchscreen’ ‘Coordinate Transformation Matrix’ 1 0 0 0 -1 1 0 0 1

So returning to the one I know is good for me . . .

I get the current settings . . . .

root@zynthian-touch:~# export DISPLAY=:0.0
root@zynthian-touch:~# xinput list-props ‘ADS7846 Touchscreen’
Device ‘ADS7846 Touchscreen’:
Device Enabled (113): 1
Coordinate Transformation Matrix (114): -1.000000, 0.000000, 1.000000, 0.000000, -1.000000, 1.000000, 0.000000, 0.000000, 1.000000
libinput Calibration Matrix (245): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
libinput Calibration Matrix Default (246): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
libinput Send Events Modes Available (247): 1, 0
libinput Send Events Mode Enabled (248): 0, 0
libinput Send Events Mode Enabled Default (249): 0, 0
Device Node (250): “/dev/input/event0”
Device Product ID (251): 0, 0

Now applying the command line fix. . .

root@zynthian-touch:~# xinput set-prop ‘ADS7846 Touchscreen’ ‘Coordinate Transformation Matrix’ 1 0 0 0 -1 1 0 0 1
root@zynthian-touch:~# xinput list-props ‘ADS7846 Touchscreen’
Device ‘ADS7846 Touchscreen’:
Device Enabled (113): 1
Coordinate Transformation Matrix (114): 1.000000, 0.000000, 0.000000, 0.000000, -1.000000, 1.000000, 0.000000, 0.000000, 1.000000
libinput Calibration Matrix (245): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
libinput Calibration Matrix Default (246): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
libinput Send Events Modes Available (247): 1, 0
libinput Send Events Mode Enabled (248): 0, 0
libinput Send Events Mode Enabled Default (249): 0, 0
Device Node (250): “/dev/input/event0”
Device Product ID (251): 0, 0

Everything is ok…

Sorry, I know this is nothing more than information about what’s already been said, but I have learnt a bit, especially make sure you have the DISPLAY variable set correctly!.

and trying that with that most effective of touch screen calibrators the step sea ( did you see what he did there … ? :smiley: )

Is the accuracy that goes in the extreme corners. … .

Now quite how we put a transformation matrix into the DTOVERLAY panel section of the webconf, is the bit that we really want to nail down, and I suspect we are going to actually have to work it out. Cos once we can put a transformation matrix in there that get recognised then we have enough control to solve this easily and flexibly.

2 Likes

https://wiki.ubuntu.com/X/InputCoordinateTransformation

So now lets see if we can get any actual values out of the touch screen . . . .

root@zynthian-touch:~# echo NW
NW
root@zynthian-touch:~# xinput query-state “ADS7846 Touchscreen” | grep val
valuator[0]=5071
valuator[1]=6224
valuator[2]=0
valuator[3]=0
root@zynthian-touch:~# echo NE
NE
root@zynthian-touch:~# xinput query-state “ADS7846 Touchscreen” | grep val
valuator[0]=62431
valuator[1]=7696
valuator[2]=0
valuator[3]=0
root@zynthian-touch:~# echo SW
SW
root@zynthian-touch:~# xinput query-state “ADS7846 Touchscreen” | grep val
valuator[0]=5855
valuator[1]=58624
valuator[2]=0
valuator[3]=0
root@zynthian-touch:~# echo SE
SE
root@zynthian-touch:~# xinput query-state “ADS7846 Touchscreen” | grep val
valuator[0]=62511
valuator[1]=59296
valuator[2]=0
valuator[3]=0
root@zynthian-touch:~# echo Midlands
Midlands
root@zynthian-touch:~# xinput query-state “ADS7846 Touchscreen” | grep val
valuator[0]=36383
valuator[1]=31536
valuator[2]=0

Now how do you do a scaled transform with matrixes …?

Calibrating Touchscreen - ArchWiki gives us a clue . . .

and we finally get a value that seems to behave as expected. . . .

xinput set-prop ‘ADS7846 Touchscreen’ ‘Coordinate Transformation Matrix’ 0.5 0 0 0 -0.5 1 0 0 1

This tracks consistently at half the position from the SW corner,
so in the SW it’s in the SW in the NE it’s positioned in the midlands and when in the midlands the pointer is a md way between the midlands and the SW.

So the float values DO work if you get them sensible. :smiley:

Perhaps we can get suitable values from xinput_calibrator. … ?

There seems to be a lack in information between the xinput_calibrator which outputs something like . . .

Calibrating standard Xorg driver “ADS7846 Touchscreen”
current calibration values: min_x=0, max_x=65535 and min_y=0, max_y=65535
If these values are estimated wrong, either supply it manually with the --precalib option, or run the ‘get_precalib.sh’ script to automatically get it (through HAL).
DEBUG: Found that ‘ADS7846 Touchscreen’ is a sysfs name.
DEBUG: Adding click 0 (X=38, Y=186)
DEBUG: Adding click 1 (X=203, Y=184)
DEBUG: Adding click 2 (X=38, Y=294)
DEBUG: Adding click 3 (X=198, Y=294)
→ Making the calibration permanent ←
DEBUG: Found that ‘ADS7846 Touchscreen’ is a sysfs name.
copy the snippet below into ‘/etc/X11/xorg.conf.d/99-calibration.conf’ (/usr/share/X11/xorg.conf.d/ in some distro’s)
Section “InputClass”
Identifier “calibration”
MatchProduct “ADS7846 Touchscreen”
Option “MinX” “1490”
Option “MaxX” “31072”
Option “MinY” “34167”
Option “MaxY” “63931”
Option “SwapXY” “0” # unless it was already set to 1
Option “InvertX” “0” # unless it was already set
Option “InvertY” “0” # unless it was already set
EndSection

and the transformation matrix which wants stuff like this:

xinput set-prop ‘ADS7846 Touchscreen’ ‘Coordinate Transformation Matrix’ 0.5 0 0 0 -0.5 1 0 0 1

quite how one turns one into the other which would mean you could do it all from xinput_calibrator values is what I’m trying to work out now. . . .

root@zynthian-touch:~# xrandr
xrandr: Failed to get size of gamma for output default
Screen 0: minimum 480 x 320, current 480 x 320, maximum 480 x 320
default connected 480x320+0+0 0mm x 0mm
480x320 0.00*

So to get suitable values for all this I 've developed a technique:

Firstly ignore the Y Values (N/S) and just concentrate on Y ( E/W)
This means we only care about the first line of the matrix, so set the Y unit defaults for the second line . . .

c0 0 c1
0 -1.0 1.0
0 0 1

Now adjust the X offset parameter so that the cursor and the touch point track each other on the left hand side of the screen accurately.

IN my case this is a value of -0.05 in position C1 . .

xinput set-prop ‘ADS7846 Touchscreen’ ‘Coordinate Transformation Matrix’ 1.0 0 -0.05 0 -1.0 1.0 0 0 1

with that set:

now adjust the C0 value ( the gain so to speak) so that the tracking on the right hand side of the screen os as accurate as you can make it.

xinput set-prop ‘ADS7846 Touchscreen’ ‘Coordinate Transformation Matrix’ 1.105 0 -0.05 0 -1.0 1.0 0 0 1

So that’s got the horizontal value correct. . . ( That didn’t half feel like lining up an analogue VCO :slight_smile: )

The vertical seems considerably more involved, can’t get any sense out of it at the moment . . .
They seem very interactive. . . Tea needed.

for those trying to temporary adjust using easier way i found:
Had to restart with a brand new zynthian image, and recalibrate screen again noticed

dtoverlay=waveshare35a:rotate=90
    display_rotate=1

to put on webconf hw-display is not enough.
Must add 99-calibration. conf to xorg.conf.d folder
with
Section “InputClass”
Identifier “calibration”
MatchProduct “ADS7846 Touchscreen”
Option “MinX” “3100”
Option “MaxX” “62000”
Option “MinY” “62000”
Option “MaxY” “3100”
Option “SwapXY” “1” # unless it was already set to 1
Option “InvertX” “0” # unless it was already set
Option “InvertY” “0” # unless it was already set
Option “TransformationMatrix” “0 -1 1 1 0 0 0 0 1”
EndSection

as described in one of your replies.
The only remaining issue is that weird pointer offset at edges…
i’m trying writing values on MinX, MaxX (etc…) in totally blind way :roll_eyes: :dizzy_face:

I downloaded the last stable version March 16th. I’m using a PiTFT 3.5 Resistive. I tried everything I red here and I’m still stuck with X and Y axes swept. How can I swap them ?

Did you calibrate screen using the admin menu option?

Thanks riban for your reply.

Yes I calibrated it with the admin menu option. Calibration seems ok. I just have the X and Y axes swept. When I move left-right the cursor move up-down and when I move up-down the cursor move left-right.

When I tried to change parameters in xorg.conf.d/99-calibrations.conf, in \zynthian\config or \zynthian\zynthian-sys and reboot… nothing change.

Hmmm… The calibrarion wizard is supposed to remove the need to edit files. Did you try the calibrarion wizard before editing any files? It is plausible that a change may be blocking the wizard from doing its job.

What is the exact model of the touch screen? What is your webconf configuration?

The first thing I did was to use the admin calibration tool alone, without changing any files myself. The LCD is a Adafruit PiTFT 3.5 Resistive.

Display:
PiTFT 3.5 Resistive

Config:
dtoverlay=pitft35-resistive,rotate=90,speed=32000000,fps=20

Width:
480

Height:
320

Frambuffer:
/dev/fb1

I found a solution to swap X and Y axes of the touchscreen with my PiTFT 3.5 Resistive.

I found in the source code that I have to change the file /ext/X11/xorg.conf.d/99-calibration.conf

The original TransformationMatrix was like this:

-1.094463 0.000000 1.046091 0.000000 1.108911 -0.026733 0.000000 0.000000 1.000000

I changed it like this:

0.000000 1.108911 -0.026733 -1.094463 0.000000 1.046091 0.000000 0.000000 1.000000

(exange values 1 to 3 with values 4 to 6). After the touchscreen works properly.