Quantcast
Channel: Engineering(DIY)
Viewing all articles
Browse latest Browse all 20

Raspberry PI, Raspbian, XBMC and eGalax 7 inch touchscreen

$
0
0
Hello!

I have spent some time lately trying to find a solution to get my 7 inch eGalax touchscreen to work with  Raspbian(Debian Wheezy) in XBMC 12 Frodo and finally got it working as I wanted.

My Setup
  • Raspberry PI model B: ~30$
  • 7 inch display with touchscreen for car rear view camera, from eBay(touchscreen is connected to one USB port): 80$
  • HDMI male to HDMI male connector(from eBay): <2$
  • 4GB SDHC class 4 card
  • 12V(500mA) AC to DC adapter for powering the display
  • 5V(1A) microUSB AC to DC converter for powering the PI
  • USB keyboard


Edit:  I have uploaded my image with XBMC 12 build with eGalax touchscreen support(download it from here, with md5sum c59330154143d9e5e43217322bbd92ce). It seems that you need to request permission and I will give you access. The account is pi and password: a.

Here is what you need to do in order to have a system with Raspberry PI, Raspbian OS and XBMC 12 Frodo stable with eGalax touchscreen working correctly(which means axes calibrated and click working with just one tap&release action):


1. Get latest Raspbian image from here and flash it to an SD card.

2. Build your own kernel with eGalax touchscreen support, like in this post(you will only need to replace kernel.img file and /lib/modules and /lib/firmware folders on the SD card).

3. Build XBMC 12 on Raspberry PI using this tutorial.
Note: After downloading XBMC archive, get this archive and unpack it anywhere.
Apply patches to xbmc files:
cd <patches_folder>
patch -p1 <path_to_xbmc>/xbmc/input/linux/LinuxInputDevices.cpp < LinuxInputDevices_cpp.patch
patch -p1 <path_to_xbmc>/xbmc/input/MouseStat.cpp < MouseStat_cpp.patch
patch -p1 <path_to_xbmc>/xbmc/input/MouseStat.h < MouseStat_h.patch
4. Touchscreen calibration.
Copy the eGalaxCalibration folder from the archive(downloaded above) to /usr/share/ on Raspberry PI. Here, you should have the file touchscreen_axes_calib. It contains four values for the axes calibration and one value for swapping axes.
The simplest way to swap axes is to switch the four wires cable plug's orientation which comes from the touchscreen to the touch controller.

Here is how the calibration was done.

the original behavior(no calibration)

In the picture above, we see that "touch panel values frame" differs from "touch panel physical size frame". When we are pressing the touch we are moving in the "touch panel physical size frame" but when the touch screen is not calibrated the arrow from XBMC is in another place.
  • "touch panel physical size frame" is the screen starting from (0,0) on the left top corner and going to (width, height) in the right bottom corner.
  • "touch panel values frame" is the frame which contains all the number the touch controller is giving.
We see that these frames differs a lot. Our main scope is to overlap the "touch panel values frame" to the "touch panel physical size frame".

In order to do this we need to do three steps(the third one is done in software):
a. Scale the value read from the touch driver x and y) in order to fit 0->width range and respectively 0->height range of the "touch panel physical size frame" the scale value for x axis is:
                       "touch panel physical size frame" width
calib_x_fact = -------------------------------------------------
                            "touch panel values frame" width


                       "touch panel physical size frame" height
calib_y_fact = -------------------------------------------------
                            "touch panel values frame" height

"touch panel values frame" width and height are coming from your XBMC resolution(I have height=1280 and height=720).
"touch panel physical size frame" width and height are a little more trickier to find but nothing hard. In step 2 above, you have calibrated the touchscreen in XFCE. You got some values returned by xinput_calibrator, something like:
Section "InputClass"
    Identifier   "calibration"
    MatchProduct    "eGalax Inc. USB TouchController"
    Option    "Calibration"    "1977 32 1893 131"
EndSection
In my case,
"touch panel physical size frame" width is 1977 - 32 = 1945
"touch panel physical size frame" height is 1893 - 131 = 1762
Now, compute the values and put them in /usr/share/eGalaxCalibration/touchscreen_axes_calib file

b. Translate the "touch panel values frame" to the left and up, to match "touch panel physical size frame".
I didn't find a logical method to do this, because we don't know exactly "where is" the "touch panel values frame", so, in order to find calib_x_d and calib_y_d you have to first set them both to zero and then start XBMC. Now, put some sharp pointer on the screen and observe the distances between the cursor on the screen and your pointer's position. Try to approximate these x and y deviations(measured in pixels) and put them in the /usr/share/eGalaxCalibration/touchscreen_axes_calib file.

c. Revert direction of axes. This is done in the software(from patches).

4. Math behind.
To accomplish these transformations the following formula was implemented in the file
xbmc/input/linux/LinuxInputDevices.cpp
pointer.x = screen_width - value_read.x * calib_x_fact - calib_x_d;
pointer.y = screen_height - value_read.y * calib_y_fact - calib_y_d;

After I have successfully calibrated the touchscreen I have discovered that single click was not possible from the touchscreen, just double click. After digging through the code, I have found that this was caused by drag action which was triggered because the previous values of the touch were far(more than 5 pixels) from a new press. For example, at the start of the program, cursor is set at 0,0 coordinates; if user is trying to press a button, let's say at 100, 300, the program will calculate the distance between these two points and will find out that this is greater than 5.
(100-0)x(100-0) + (300 - 0)x(300-0) is greater than 5x5
This works when you double click, because the previous point in the second click action is very close to the second click point. This also works for mouses, because the previous value of the pointer is always very close to the new value of the pointer(because mouse's pointer drags on the screen and it doesn't jump).

I have developed an algorithm to avoid this issue:
When the user is pressing the screen(x,y), the touch values are being set to (screen_width+1, screen_height+1 -> outside of the visible screen) just at the first event read(which is BTN_TOUCH PRESS).
After this event, the program will receive multiple X and Y absolute values events. The first two events, one for X and one for Y are used to set the previous X value, respectively previous Y value to the current X respective current Y values. And from now on distance is measured and this is preventing no unwanted drag action.
The user's finger/pointer will not stay at a single point, because the touchscreen's lack of precision, so it will move around 5-6 pixels in x and y directions.
I have also set the click distance to 7. You can change this by changing click_confines value in xbmc/input/MouseStat.h. Originally it was set to 5, but this is not very good for touch screens(I had to click with a sharp pointer and with my nail always, but with a value of 7 I can click with my finger with a slight touch -> really nice).

Enjoy!


Viewing all articles
Browse latest Browse all 20

Trending Articles