I just purchased the Learn LVGL: Build GUIs for ESP32 Projects course and today I received an ESP32-2432S028 module.
When I run the code in Section 1.9 – Testing the Touchscreen of the course,
With the protective screen cover removed and nothing touching the display, I get numbers like X = 356, Y = 17, Z = 450.
When I touch the screen with the included stylus in the upper left corner, I get numbers like X = 90, Y = 62, Z = 500. A hard press yields Z = 1950.
When I touch the screen with the included stylus in the lower right corner, I get numbers like X = 250, Y = 170, Z = 1000. A hard press yields Z = 2400.
It appears that the touchscreen on my module is not calibrated. The code in the course appears to be predicated on the touchscreen being calibrated.
Am I missing something here? Other than being overly optimistic about the Cheap aspect of Cheap Yellow Display?
Hi.
Can you double-check the specs of your display?
Our codes are only compatible with resistive touchscreens… Are you sure about the type of touchscreen of your display?
Regards,
Sara
I was going to come back and edit my question, but you beat me to it with your question. I found the XPT2046 chip (https://www.buydisplay.com/download/ic/XPT2046.pdf) on my CYD board adjacent to the BOOT switch. Because that chip is used with resistive touchscreens, I assume that’s what I have.
I have 3.3V on the XPT2046 pin 9, which is the reference voltage pin.
I note that Paul Stoffgren’s XPT2046_Touchscreen library sets the Z threshold at 400, but I’m seeing a value of around 450 without touching the screen. I might try changing that threshold to 500 in XPT2046_Touchscreen.cpp and seeing what happens.
My module may have a bad touchscreen, or a faulty interface between the touchscreen and the XPT2046, but it seemed to work with the demo code that came preloaded on the module.
It may be necessary to add touchscreen calibration to software designed to make use of the CYD modules, if enough people have the same problem I’m having. This library might be useful in that regard, but it needs to be updated quite a bit to better match the Stoffgren library on which it was based.
I have another module on order. When it comes, I’ll compare and report.
Hi.
We didn’t need to calibrate any of our displays. So, I thought all of them were like ours.
Does your display have the same size as the recommended one? Or is it a little bit bigger?
Have you tried changing the rotation as explained in that unit?
Changing the threshold value seems a good starting point. Try it and let me know the results.
Regards,
Sara
My display has a diagonal of about 8 cm inside the silver lines around the border. It has TPM408-2. 8 printed in the lower left corner of the display, when the display is oriented in landscape mode with the USB-C connector of the yellow board on the left..
Something has changed about the behavior of my CYD. I have physically handled the screen more than I had before I wrote my first post on this thread, and now the XPT2046_Touchscreen threshold of 400 defined in XPT2046_Touchscreen.cpp is working.
One thing I did is I “massaged” the touchscreen all over with my thumb, thinking that might spread the material between the two resistive layers more evenly.
Now I get the following values in the four corners and the approximate center using the example code from Section 1.9 of the course:
LL: x=17, y=244
UR: x=330, y=12
Approx. Center: x=167, y=127
UL: x=72, y=52
LR: x=270, y=185
It behaves as if the resistive touchscreen was atrtached at an angle.
Hi.
Try the following examples in the eBook and see if they work as expected.
Then, let me know the results.
Regards,
Sara
What are “the following examples” you want me to try? Do you mean the examples that follow the Section 1.9 example? Or do you mean specific examples? If the latter, please list them.
Bear in mind that it is a tedious process to try multiple examples, due to the length of time it takes to compile an example (or any ESP32 program) on my Windows 11 laptop with an i7-1195G7 @ 2.90GHz, 16 GB of RAM, and two SSDs, one mainly for programs and the other mainly for data, running Version 2.3.2 of the Arduino IDE.
One I’ve tried already is the Section 2.6 Button and Slider example. It sort of works, but I have to touch the screen with the stylus at an offset from the displayed positions of the button and slider, and I have to determine the offset by trial and error.
Regards,
Robert Fleming
Hi.
Yes, I was referring to other examples of the eBook.
As you mentioned, it seems that your touchscreen is not properly calibrated.
Have you tried changing the rotation of the touchscreen as explained in Unit 1.9?
Regards,
Sara
Yes, I’ve tried a couple of different rotation values, and it doesn’t seem to make much difference.
My current thinking is that I should attempt to implement touchscreen calibration and use your ESP32 Save Data Permanently using Preferences Library example to store the calibration values.
I’m having the same issue. I do have the correct board and have been able to load and test all the code in your Learn LVGL eBook.
To get the touch input to work I have to touch to the left of the item so looks like the touch screen is not calibrated. I’ve come across this issue before and the device provided a cross in each corner. You touched the center of each cross in order to calibrate the touch screen. I suggest that be made available.
I found this code for XTP2046 calibration, but when installed on the CYD it just repeatedly crashed.
https://github.com/ardnew/XPT2046_Calibrated/tree/master
Phil, I’m looking into that. There’s a somewhat helpful YouTube video at https://www.youtube.com/watch?v=QZbgPHvLfGw . The library you mention provides some useful material, but it hasn’t been updated in sync with XPT2046_Touchscreen and won’t work on the ESP32-2432S028 without a lot of editing. The TI paper is also a useful read.
Thank you for providing that calibration example…
Did you succeed with that?
Regards.
Hi Sara,
I’m in the middle of some debugging. I’ve got code that collects touchscreen data at known screen points, throws out outliers, and computes the alpha, beta, and delta calibration values and uses those values to translate the resistive touchscreen measurements to display points. X works, but Y doesn’t. My next step is to compare the equations from the calibration code in the XPT2046_Calibrated library with the TI appnote from which they were allegedly derived.Right now the code is a mess, because I’m trying to merge your Section 1.9 touchscreen test example with the calibration code from the XPT2046_Calibrated library, and add some stuff to tie it together. If you have my email address (Rui and I have corresponded in the past), please PM me for further info.
Edit: The problem with the Y axis computation appears to be incorrect parentheses. I probably introduced that when I converted all of the variables to floats.
Second edit: Yes, it was parentheses. Both X and Y work now.
This is how it works:
Draw three crosshairs on the screen, one at a time. They are at the coordinates specified in the XPT2046_Calibrated library:
aS = 13, 11
bS = 167, 214
cS = 312, 113
While each point is displayed, collect 100 resistive touchscreen points from the XPT2046. My experience has been that there will be some outliers, so I prune out x,y samples where either coordinate is more than one standard deviation from the mean for that axis.
When 100 resistive touchscreen points have been collected, filtered, and averaged at each of the three screen points (crosshair locations), call the XPT2046_Calibrated TS_Calibration::TS_Calibration() function to compute the correction coefficients alphaX, betaX, deltaX, alphaY, betaY, and deltaY.
As a test, apply the corrections to the averaged resistive touchscreen points for each of the three screen points listed above, using the following equations:
x_scr = alphaX * x_touch + betaX * y_touch + deltaX
y_scr = alphaY * x_touch + betaY * y_touch + deltaY
The computed coefficients for this test are:
X: alpha = 0.10, beta = 0.01, delta = -65.50
Y: alpha = 0.01, beta = 0.07, delta = -48.85
The results I got are:
x_touch = 715 y_touch = 700
x_scr = 13 y_scr = 11
x_touch = 2010 y_touch = 3270
x_scr = 167 y_scr = 214
x_touch = 3597 y_touch = 1605
x_scr = 312 y_scr = 113
Compare those screen coordinates (x_scr, y_scr) to the ones I listed earlier.
Right now, I’m just using the Serial Monitor in the Arduino IDE to watch what’s going on. The only thing displayed on the CYD is the crosshairs.
What I envision is that one could run the calibration sketch once upon receiving a new CYD, and have it save the alpha/beta/delta coefficients to flash using the Preferences Library. Other sketches would then retrieve the coefficients when they start up and use the equations above that compute x_scr and y_scr from x_touch and y_touch to compute the screen coordinates corresponding to the touch.
Regards,
RF
Phil, if you’re the Victor Kilo 6 guy, I’d be happy to send you the prototype code.
Thanks Robert. I actually found the same Youtube video that you have and agree it should be a good way to solve this issue.
And I am VK6.
Thanks
Phil…
Robert. There is some calibration code in File>Examples that saves the calibration in the Flash.
It’s from this video:
https://www.youtube.com/watch?v=rq5yPJbX_uk
at about 16 minutes.
Phil…
Got six point calibration working. See equation 7 in the TI app note. It uses the least squares algorithm to compute the resistive touch screen to display coordinate transformation coefficients. Added a feature to six-point calibration to display the ‘+’ signs on which the user taps to generate resistive touchscreen calibration algorithm input data alongside ‘X’ symbols that show where the algorithm “thinks” you tapped after it runs the calculations. See: picture of programmed display points vs computed points.
If you don’t like what you see on this display, maybe you didn’t tap exactly in the middle of the ‘+’ symbols during calibration. Hit the reset button on the back of the module and try again.
Im having same issue. Looks like the supplied code only applicable to one machine. I updated the Touchscreen test project to report the p.x and p.y values when touching each corner. By putting those values into the map commands (replacing the supplied values) as below Im getting better performance.
// Calibrate Touchscreen points with map function to the correct width and height
//x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
//y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
x = map(p.x, 286, 3840, 1, SCREEN_WIDTH); //min at left, max at right
y = map(p.y, 296, 3760, 1, SCREEN_HEIGHT); //min at top, max at bottom
This approach is only a workaround as it may need to be repeated for each device.
Maybe a guideline is to only use touch buttons large enough to handle a few counts of error between devices.
I received my second CYD today. The first one cost me US$3.56, and the second one cost US$10.99 (including shipping!).
Seems as though the price difference is worth it. The resistive touchscreen on the first one appeared offset and rotated, while the resistive touchscreen on the second one seems fairly well calibrated!
I’m just kidding about the price difference translating to a quality difference, of course. Probably just random selection.
While the second one seems to be fairly well calibrated, it is reporting X coordinates > 319, in fact, up to around 335, and Y coordinates up to and including at least 240. This makes something in the software complain via a print to the Serial Console. In my view, the software should clamp the X coordinates to the range [0..319] and the Y coordinates to the range [0..239].
This is what I got on the first attempt to calibrate the screen using my 6-point calibration sketch. The yellow ‘+’ symbols are the points you tap on with the stylus during the calibration process, and the blue ‘X’ symbols are where the software says it thinks you tapped after running the calculations. And that’s with the protective cover left on the screen.
This is a typical calibration result with my original CYD.
Hi.
Thanks for providing that information.
Currently, I’m out of the office, but I’ll take a look when I come back.
You can send the sketches to support@randomnerdtutorials.com
Thanks
Regards,
SAra
Apologi3s if i dont understand your cal process but itounds like you need to change the values in those map commands (do you use them in the cal data collect?). Parameters 2 and 3 are the expected range of raw inputs to be rescaled to the output 0-320 and 0-240. If you are averaging values use the max instead. If the range of values for any cal location is too wide declare a bad cal and restart.
Alex, the equations you’re referring to:
x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
are OK if all you need to do is scale the resistive touchscreen coordinates to the range of display coordinates.
But the first CYD I received had a resistive touchscreen that was rotated and offset from the display, so I had to resort to a more drastic solution, which is described in the TI appnote.
Regards,
Robert (Chip) Fleming
Yes that paper is interesting (in summary we need to generate a couple of matrix multiplies and an offset to transform the incoming p.x and p.y into x and y ).
Maybe that cheap device was a mfg reject ?
Wouldnt a translation and rotation error mean there are sections of the screen that cant be selected ? Maybe return/trash it ?
Do you think we need to run a cal/check every time an app that uses the touchscreen runs ?
I suppose a small set of algorithm parameters could be saved and used from a SPIFFS file by the app, and updated by a cal routine as needed but I suspect its making a mountain out of a molehill. Id expect a modern board design today should include calibration features that would be set during manufacturing/test obviating the need for any future external cal. Mobile phones have addressed this assue.
My original problem was that I had a large offset when selecting from the keyboard with the original map parameters. My updated map parameters work but I dont know how valid they are for multiple CYDs.
Its an interesting project but will be burdensome to check and recal the touchscreen whenever an app runs (or offer a CalTouch button on splashscreen ?).
Wouldnt a translation and rotation error mean there are sections of the screen that cant be selected ?
I haven’t found that to be the case. My first (cheaper) CYD’s touchscreen is responsive across the screen. And it calibrates to within a few display pixels, but not quite as well as my second one, which calibrates to within 0-2 pixels.
Do you think we need to run a cal/check every time an app that uses the touchscreen runs ?
No, just run the calibration sketch once, and save the coordinate transform equation coefficients using the Preferences library functions. Other sketches requiring calibrated touchscreen inputs would use the Preferences library to retrieve the coeffients and use them in Eqs. 1 & 2 of the TI appnote to transform touchscreen coordinates to display coordinates as needed.
Its an interesting project but will be burdensome to check and recal the touchscreen whenever an app runs…
Once the six coefficients are computed and stored, it takes one line of code to declare the variables for the coefficients, and 11 lines of code in my implementation to retrieve them, including a function call in setup() and a test to make sure the preferences namespace opened correctly and an error statement if it didn’t. It takes another couple of lines of code to include the Preferences library and declare the preferences object. And you replace the two lines of code that do the mapping function with two lines of code that do the coordinate transformation.
Hi -I am having a touch screen calibration issue also. In the Wi-Fi manager example, if I touch a keycap, the keycap to the right gets highlighted, For example, press “t” and a “y” is displayed. Press “p” and you get a backspace delete. To activate the “1#”, “ABC”, “_” keys I have to tap on the black border on the left of the screen.
I called Amazon and they replaced the CYD and I get the same error. What is strange is when you power up the CYD for the first time and use the keyboard in the vendor supplied example, the character selected matches the character displayed.
Might this be an LVGL compatibility setting?
For others following this thread, the product code (silk screened in gold) on the back of the unit is ESP32-2432S028. I am assuming it is the resistive screen. The product I have comes from DIYmall (via Amazon in the US) and the product codes on the cardboard box are X003POFHS9 and FZ5815.
I also found identical LDR issues in example 3.3. Even unsoldered the LDR to test it. I agree with other commentors that in the most recent batch the vendor probably replaced the LDR with a unit with different resistance specs. What a shame. Vendor changes their specs and your examples no longer work as expected.
Hi.
We were able to calibrate the display using Robert Fleming’s instructions.
We’ll update our eBook soon with the calibration procedure.
If you wish to receive the updated procedure and code now, please let us know by sending an email to support@randomnerdtutorials.com and I’ll send you the instructions.
Just mention you want to talk to me.
Regards,
Sara
Hi Sara,
I am early in the process of working through your Learn LVGL: Build GUIs for ESP32 Projects and need help with a teething problem. I’m not sure if its me or my inadvertently purchased USB2CYD with its alleged added complications but I am at an impasse trying to get your and Robert Fleming’s ESP32-2432S028R touch screen calibration tool working properly. My USB2CYD is actually working fine with your unchanged User_Setup.h file (using the ILI9341_2 Driver), and I haven’t found any issues with color inversion.
The touch screen is also working and the calibration sketch runs fine and provides the calibration values as described but when I apply them in the Touchscreen_Test_Calibrated sketch the x and y axes are swapped. I have tried every permutation and combination of touchscreen and display rotations in the calibration sketch and my best outcome has been achieved using SCREEN_WIDTH 240, SCREEN_HEIGHT 320, touchscreen.setRotation(1); and lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_90; (to give me a landscape screen that all 6 calibration points will actually display on). This gives me correct results except that the x and y axes are swapped with my display configured in the same 90 degrees rotation to the USB at right landscape aspect.
The data reported to the serial monitor by the calibration sketch all seems correct and the computed screen coordinates reported in the calibration sketch all line up within a couple of pixels of the calibration test points with no axis swapping.
-> aS = 13, 11
-> bS = 20, 220
-> cS = 167, 60
-> dS = 155, 180
-> eS = 300, 13
-> fS = 295, 225
-> aT = 319, 426
-> bT = 376, 3555
-> cT = 2030, 1125
-> eT = 1892, 2956
-> eT = 3518, 438
-> fT = 3475, 3627
->
-> A = [[319.00,426.00,1.00],[376.00,3555.00,1.00],[2030.00,1125.00,1.00],[1892.00,2956.00,1.00],[3518.00,438.00,1.00],[3475.00,3627.00,1.00]]
-> transA = [[319.00,376.00,2030.00,1892.00,3518.00,3475.00],[426.00,3555.00,1125.00,2956.00,438.00,3627.00],[1.00,1.00,1.00,1.00,1.00,1.00]]
-> Before inversion, B = [[32395648.00,23493784.00,11610.00],[23493784.00,36170036.00,12127.00],[11610.00,12127.00,6.00]]
-> After inversion, B = [[0.00,-0.00,-0.00],[-0.00,0.00,-0.00],[-0.00,-0.00,0.89]]
-> C = [[-0.00,-0.00,0.00,-0.00,0.00,0.00],[-0.00,0.00,-0.00,0.00,-0.00,0.00],[0.76,0.20,0.30,0.01,0.13,-0.41]]
->
-> Computed X: alpha = 0.089, beta = 0.000, delta = -14.603
-> Computed Y: alpha = 0.000, beta = 0.066, delta = -16.673
-> Stored X: alpha = 0.089, beta = 0.000, delta = -14.603
-> Stored Y: alpha = 0.000, beta = 0.066, delta = -16.673
->
-> x_touch = 319 y_touch = 426
-> x_scr = 13 y_scr = 11
-> error = 0 pixel(s)
->
-> x_touch = 376 y_touch = 3555
-> x_scr = 19 y_scr = 219
-> error = 1 pixel(s)
->
-> x_touch = 2030 y_touch = 1125
-> x_scr = 166 y_scr = 58
-> error = 2 pixel(s)
->
-> x_touch = 1892 y_touch = 2956
-> x_scr = 154 y_scr = 180
-> error = 1 pixel(s)
->
-> x_touch = 3518 y_touch = 438
-> x_scr = 299 y_scr = 13
-> error = 1 pixel(s)
->
-> x_touch = 3475 y_touch = 3627
-> x_scr = 295 y_scr = 225
-> error = 0 pixel(s)
Its only when applying the calibration values in the Touchscreen_Test_Calibrated sketch that the axes are switched and the screen coordinates displayed on the CYD are wrong. I don’t know why that is. I am using all the exact same library versions that you have specified and the same display driver (ILI9341_2). For the calibration sketch I used SCREEN_WIDTH 240, SCREEN_HEIGHT 320, touchscreen.setRotation(1); and lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_90); I know that swapping SCREEN_WIDTH and SCREEN_ HEIGHT away from the native hardware portrait configuration is wrong and just makes the right hand quarter of any landscape screen rotation unusable so that does not appear to be relevant to my problem.
I have “fudged” a solution that works for me with these calibration values by swapping the calibration triplet set that the x and y coordinate computations use, which effectively swaps the x and y axes, and then I also swap the computed coordinates in the ‘Set the coordinates’ lines: ie
// REPLACE WITH YOUR OWN CALIBRATION VALUES » https://RandomNerdTutorials.com/touchscreen-calibration/
alpha_x = 0.089;
beta_x = 0.000;
delta_x = -14.603;
alpha_y = 0.000;
beta_y = 0.066;
delta_y = -16.673;
// swap x and y to compute screen coordinates
y = alpha_y * p.x + beta_y * p.y + delta_y;
// clamp y between 0 and SCREEN_WIDTH – 1
y = max(0, y);
y = min(240 – 1, y);
x = alpha_x * p.x + beta_x * p.y + delta_x;
// clamp x between 0 and SCREEN_HEIGHT – 1
x = max(0, x);
x = min(320 – 1, x);
z = p.z;
data->state = LV_INDEV_STATE_PRESSED;
// Set the coordinates
// Swap computed screen coordinates x and y when setting
data->point.x = y;
data->point.y = x;
This works and the correct screen coordinates are then reported by the Touchscreen_Test_Calibrated sketch but I’d rather understand why I can’t get it right without this fudge and do it properly.
Despite swapping x and y and getting correct readings from the sketch, lvgl somehow still thinks x and y haven’t been swapped and sends a warning to the serial monitor whenever it thinks Y is > the vertical resolution in the rotated screen (240) ie anytime my new x is between 240 and 320 which always happens in the right hand quarter of the screen. This warning comes from the lvlg library’s indev_pointer_proc function so to block this warning I have substituted this limit check with the horizontal resolution (320) in the ‘sanity check’ code block in the relevant library src file (lv_indev.c) and these warnings have now ceased because new x (still remembered as y by lvgl) never exceeds 320.
/*Simple sanity check*/
if(data->point.x < 0) {
LV_LOG_WARN(“X is %d which is smaller than zero”, (int)data->point.x);
}
if(data->point.x >= lv_display_get_horizontal_resolution(i->disp)) {
LV_LOG_WARN(“X is %d which is greater than hor. res”, (int)data->point.x);
}
if(data->point.y < 0) {
LV_LOG_WARN(“Y is %d which is smaller than zero”, (int)data->point.y);
}
// fudge for me engineered touchscreen calibration axis swap – RW 260216
// if(data->point.y >= lv_display_get_vertical_resolution(i->disp)) {
if(data->point.y >= lv_display_get_horizontal_resolution(i->disp)) {
LV_LOG_WARN(“Y is %d which is greater than ver. res”, (int)data->point.y);
}
I haven’t yet figured out why lvgl believes y is still y and not new x and it no doubt thinks x is still x too but this doesn’t matter here as x is allowed to be any value up to 320. I think its probably coming from the same src file, which saves the values so they can be used again in a different function. I guess this fudge may come back to bite further into the course so solving the problem that got me to this is still important to me!?
Hopefully you or maybe Robert will be able to tell me why my calibrators are not working when applied as intended, probably due to some rookie error I have made. Meanwhile it has been a very time consuming source of great frustration.
Hi.
I would like to help, but I’m not sure of the reason of your uncalibrated touchscreen. It may be something related to the hardware that we don’t have control of…. or something else…
If it seems to be calibrated at the moment with your workaround, I recommend trying the examples that follow and see if they work correctly.
Regards,
Sara
Ok, Thanks Sara. i now don’t think its the calibration causing the problem. LVGL just doesnt seem to be switching the touchscreen coordinates properly, as it should do through lv_indev.c, when the display is rotated 90 degrees to landscape mode. I’ll keep going using my “fudge” fix and also keep trying to figure out why. The ILI9341 chip is configured in the correct normal rptation and the display and touchscreen sre perfectly aligned in portait mode when calibrated. Maybe I’ll get another CYD too and see what happens there.
Ok, Thanks Sara. i now don’t think its the calibration causing the problem. LVGL just doesnt seem to be switching the touchscreen coordinates properly, as it should do through lv_indev.c, when the display is rotated 90 degrees to landscape mode. I’ll keep going using my “fudge” fix and also keep trying to figure out why. The ILI9341 chip is configured in the correct normal rptation and the display and touchscreen sre perfectly aligned in portait mode when calibrated. Maybe I’ll get another CYD too and see what happens there.