244浏览
查看: 244|回复: 12

[项目] 【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

[复制链接]
【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

ESP32-CYD(2432S028)液晶2.8寸屏开发板使用ESP32-WROOM-32模块作为主控,主控是一款双核MCU,集成了Wi-Fi和蓝牙功能,主频可达240MHz,具有520KB的SRAM、448KB的ROM,闪存容量为4MB+4MB,显示分辨率为240x320,采用电阻式触控式屏幕。该模块包括LCD显示器、背光控制电路、触控式屏幕控制电路、扬声器驱动电路、光敏电路和RGB LED控制电路。支持TF卡界面、序列界面、温湿度感测器界面(DHT11界面)和保留的IO口界面,该模块支持在Arduino IDE、ESP IDE、MicroPython和Mixly中进行开发。

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 14:54:33

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

安装TFT_eSPI、XPT2046_Touchscreen、BasicLinearAlgebra和LVGL库
网址:
TFT_eSPI库的网址:https://github.com/Bodmer/TFT_eSPI
XPT2046_Touchscreen库的网址: https://github.com/PaulStoffregen/XPT2046_Touchscreen
BasicLinearAlgebra库:https://github.com/tomstewart89/BasicLinearAlgebra

要正确使用 TFT_eSPI 库,需要根据不同开发板与TFT屏幕正确配置User_Setup.h和lv_conf.h文件。

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 14:55:52

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 14:57:26

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

大多数情况下,默认情况下,您的触摸屏可能没有精确校准,这是正常的。

通常,x 轴和 y 轴只偏离几个像素,例如,当使用较大的小部件(例如大按钮)时,这不会很明显。但是,当需要更高的精度时,例如使用具有较小键的键盘时,校准是一个关键方面。

校准方法

校准触摸屏涉及确定六个不同系数的值,然后将这些系数用于校准方程式中,以确定 (x,y) 坐标的实际值。

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 15:43:07

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
  项目实验之二十:ESP32 CYD液晶2.8寸开发板电阻式触摸屏校准

实验开源代码

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
  4.   项目实验之二十:ESP32 CYD液晶2.8寸开发板电阻式触摸屏校准
  5. */
  6. #include <lvgl.h>                 // 引入LVGL图形库
  7. #include <TFT_eSPI.h>             // 引入TFT_eSPI库,用于驱动TFT显示屏
  8. #include <XPT2046_Touchscreen.h>  // 引入XPT2046触摸屏库
  9. #include <BasicLinearAlgebra.h>   // 引入线性代数库,用于计算触摸屏校准参数
  10. // Touchscreen pins
  11. #define XPT2046_IRQ 36   // T_IRQ
  12. #define XPT2046_MOSI 32  // T_DIN
  13. #define XPT2046_MISO 39  // T_OUT
  14. #define XPT2046_CLK 25   // T_CLK
  15. #define XPT2046_CS 33    // T_CS
  16. unsigned long delay_start = 0;
  17. #define DELAY_1S 1000
  18. #define DELAY_5S 5000
  19. SPIClass touchscreenSPI = SPIClass(VSPI);
  20. XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
  21. #define SCREEN_WIDTH 240
  22. #define SCREEN_HEIGHT 320
  23. String s;
  24. int ts_points[6][2];
  25. /* define the screen points where touch samples will be taken */
  26. const int scr_points[6][2] = { {13, 11}, {20, 220}, {167, 60}, {155, 180}, {300, 13}, {295, 225} };
  27. struct point {
  28.   int x;
  29.   int y;
  30. };
  31. /* pS is a screen point; pT is a resistive touchscreen point */
  32. struct point aS = {scr_points[0][0], scr_points[0][1] };
  33. struct point bS = {scr_points[1][0], scr_points[1][1] };
  34. struct point cS = {scr_points[2][0], scr_points[2][1] };
  35. struct point dS = {scr_points[3][0], scr_points[3][1] };
  36. struct point eS = {scr_points[4][0], scr_points[4][1] };
  37. struct point fS = {scr_points[5][0], scr_points[5][1] };
  38. struct point aT;
  39. struct point bT;
  40. struct point cT;
  41. struct point dT;
  42. struct point eT;
  43. struct point fT;
  44. /* coefficients for transforming the X and Y coordinates of the resistive touchscreen
  45.    to display coordinates... the ones with the "pref_" prefix are retrieved from NVS   */
  46. float alphaX, betaX, deltaX, alphaY, betaY, deltaY;
  47. float pref_alphaX, pref_betaX, pref_deltaX, pref_alphaY, pref_betaY, pref_deltaY;
  48. #define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
  49. uint32_t draw_buf[DRAW_BUF_SIZE / 4];
  50. // If logging is enabled, it will inform the user about what is happening in the library
  51. void log_print(lv_log_level_t level, const char * buf) {
  52.   LV_UNUSED(level);
  53.   Serial.println(buf);
  54.   Serial.flush();
  55. }
  56. // Declare function to get the Raw Touchscreen data
  57. void touchscreen_read_pts(bool, bool, int, int);
  58. /* Declare function to display a user instruction upon startup */
  59. void lv_display_instruction(void);
  60. /* Declare function to display crosshair at indexed point */
  61. void display_crosshair(int);
  62. /* Declare function to display crosshairs at given coordinates */
  63. void display_crosshairs(int, int);
  64. /* Declare function to display 'X's at given coordinates */
  65. void display_xs(int, int);
  66. /* Declare function to compute the resistive touchscreen coordinates to display coordinates conversion coefficients */
  67. void ts_calibration (
  68.   const point, const point,
  69.         const point, const point,
  70.         const point, const point,
  71.   const point, const point,
  72.         const point, const point,
  73.         const point, const point);
  74. void gather_cal_data(void) {
  75.   //Function to draw the crosshairs and collect data
  76.   bool reset, finished;
  77.   int x_avg, y_avg;
  78.   for (int i = 0; i < 6; i++) {
  79.     lv_obj_clean(lv_scr_act());
  80.     //lv_draw_cross(i);
  81.     display_crosshair(i);
  82.     reset = true;
  83.     x_avg = 0;
  84.     y_avg = 0;
  85.    
  86.     touchscreen_read_pts(reset, &finished, &x_avg, &y_avg);
  87.     reset = false;
  88.     while (!finished) {
  89.       touchscreen_read_pts(reset, &finished, &x_avg, &y_avg);
  90.       /* found out the hard way that if I don't do this, the screen doesn't update */
  91.       lv_task_handler();
  92.       lv_tick_inc(10);
  93.       delay(10);
  94.     }
  95.     lv_obj_clean(lv_scr_act());
  96.     lv_task_handler();
  97.     lv_tick_inc(10);
  98.     delay(10);
  99.     ts_points[i][0] = x_avg;
  100.     ts_points[i][1] = y_avg;
  101.     String s = String("x_avg = " + String(x_avg) + " y_avg = " + String(y_avg) );
  102.     Serial.println(s);
  103.     delay(1500);
  104.   }
  105. }
  106. void compute_transformation_coefficients(void) {
  107.   /* finished collecting data, now compute correction coefficients */
  108.   /* first initialize the function call parameters */
  109.   aT = { ts_points[0][0], ts_points[0][1] };
  110.   bT = { ts_points[1][0], ts_points[1][1] };
  111.   cT = { ts_points[2][0], ts_points[2][1] };
  112.   dT = { ts_points[3][0], ts_points[3][1] };
  113.   eT = { ts_points[4][0], ts_points[4][1] };
  114.   fT = { ts_points[5][0], ts_points[5][1] };
  115.   /* compute the resisitve touchscreen to display coordinates conversion coefficients */
  116.   ts_calibration(aS, aT, bS, bT, cS, cT, dS, dT, eS, eT, fS, fT);
  117. }
  118. void check_calibration_results(void) {
  119.   int x_touch, y_touch, x_scr, y_scr, error;
  120.   /* if we did our job well, the screen points computed below should match
  121.      aS, bS, and cS defined near the top */
  122.   for (int i = 0; i < 6; i++) {
  123.     /* define some touch points and translate them to screen points */
  124.     x_touch = ts_points[i][0];
  125.     y_touch = ts_points[i][1];
  126.     /* here's the magic equation that uses the magic coefficients */
  127.     /* use it to convert resistive touchscreen points to display points */
  128.     x_scr = alphaX * x_touch + betaX * y_touch + deltaX;
  129.     y_scr = alphaY * x_touch + betaY * y_touch + deltaY;
  130.     display_crosshairs(scr_points[i][0], scr_points[i][1]);
  131.     display_xs(x_scr, y_scr);
  132.     s = String("x_touch = " + String(x_touch) + " y_touch = " + String(y_touch) );
  133.     Serial.println(s);
  134.     s = String("x_scr = " + String(x_scr) + " y_scr = " + String(y_scr) );
  135.     Serial.println(s);
  136.     error = (int) sqrt( sq(x_scr - scr_points[i][0]) + sq(y_scr - scr_points[i][1]) );
  137.     s = String("error = " + String(error) );
  138.     Serial.println(s);
  139.     Serial.println();
  140.   }
  141.   Serial.println("******************************************************************");
  142.   Serial.println("******************************************************************");
  143.   Serial.println("USE THE FOLLOWING COEFFICIENT VALUES TO CALIBRATE YOUR TOUCHSCREEN");
  144.   s = String("Computed X:  alpha_x = " + String(alphaX, 3) + ", beta_x = " + String(betaX, 3) + ", delta_x = " + String(deltaX, 3) );
  145.   Serial.println(s);
  146.   s = String("Computed Y:  alpha_y = " + String(-alphaY, 3) + ", beta_y = " + String(-betaY, 3) + ", delta_y = " + String(SCREEN_WIDTH-deltaY, 3) );
  147.   Serial.println(s);
  148.   Serial.println("******************************************************************");
  149.   Serial.println("******************************************************************");
  150. }
  151. void setup() {
  152.   String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
  153.   Serial.begin(115200);
  154.   Serial.println(LVGL_Arduino);
  155.   
  156.   // Start LVGL
  157.   lv_init();
  158.   // Register print function for debugging
  159.   lv_log_register_print_cb(log_print);
  160.   // Start the SPI for the touchscreen and init the touchscreen
  161.   touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  162.   touchscreen.begin(touchscreenSPI);
  163.   // Set the Touchscreen rotation in landscape mode
  164.   // Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 0: touchscreen.setRotation(0);
  165.   touchscreen.setRotation(2);
  166.   // Create a display object
  167.   lv_display_t * disp;
  168.   // Initialize the TFT display using the TFT_eSPI library
  169.   disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
  170.   lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
  171.   lv_display_instruction();
  172.   delay_start = millis();
  173.   while ((millis() - delay_start) < DELAY_5S) {
  174.     lv_task_handler();
  175.     lv_tick_inc(10);
  176.     delay(10);   
  177.   }
  178.   /* display crosshairs and have the user tap on them until enough samples are gathered */;
  179.   gather_cal_data();
  180.   /* crunch the numbers to compute the touchscreen to display coordinate transformation equation coefficients */
  181.   compute_transformation_coefficients();
  182.   /* display stored correction data and display generated vs measured screen points */
  183.   check_calibration_results();
  184. }
  185. void loop() {
  186.   lv_task_handler();  // let the GUI do its work
  187.   lv_tick_inc(5);     // tell LVGL how much time has passed
  188.   delay(5);           // let this time pass
  189. }
  190. /* Function to read a number of points from the resistive touchscreen as the user taps
  191.    a stylus on displayed crosshairs.  Once the samples have been collected, they are
  192.    filtered to remove outliers and then averaged and the average x & y are returned to the caller. */
  193. void touchscreen_read_pts(bool reset, bool *finished, int *x_avg, int *y_avg) {
  194.   /* nr_samples = samples taken; good_samples = samples used, samples = array of 100 samples */
  195.   static int i, nr_samples, good_samples;
  196.   static uint32_t samples[100][2];
  197.   /* coordinates to shift and rotate touch screen coordinates to display coordinates */
  198.   static float mean_x, mean_y, filt_mean_x, filt_mean_y, stdev_x, stdev_y;
  199.   /* caller resets the sample run at each new displayed crosshair */
  200.   if (reset) {
  201.     nr_samples = 0;
  202.     *x_avg = 0;
  203.     *y_avg = 0;
  204.     *finished = false;
  205.   }
  206.   // Checks if Touchscreen was touched, and prints X, Y
  207.   if(touchscreen.tirqTouched() && touchscreen.touched()) {
  208.     // Get Touchscreen points
  209.     TS_Point p = touchscreen.getPoint();
  210.     samples[nr_samples][0] = p.x;
  211.     samples[nr_samples][1] = p.y;
  212.    
  213.     s = String("x, y = " + String(samples[nr_samples][0]) + ", " + String(samples[nr_samples][1]) );
  214.     Serial.println(s);
  215.     nr_samples++;
  216.     /* first compute the x & y averages of all the samples */
  217.     if (nr_samples >= 100) {
  218.       mean_x = 0;
  219.       mean_y = 0;
  220.       for (i = 0; i < 100; i++) {
  221.         mean_x += (float)samples[i][0];
  222.         mean_y += (float)samples[i][1];
  223.       }
  224.       mean_x = mean_x / (float)nr_samples;
  225.       mean_y = mean_y / (float)nr_samples;
  226.       s = String("Unfiltered values:  mean_x = " + String(mean_x) + ", mean_y = " + String(mean_y));
  227.       Serial.println(s);
  228.       /* now compute the x & y standard deviations of all the samples */
  229.       stdev_x = 0;
  230.       stdev_y = 0;
  231.       for (i = 0; i < 100; i++) {
  232.         stdev_x += sq((float)samples[i][0] - mean_x);
  233.         stdev_y += sq((float)samples[i][1] - mean_y);
  234.       }
  235.       stdev_x = sqrt(stdev_x / (float)nr_samples);
  236.       stdev_y = sqrt(stdev_y / (float)nr_samples);
  237.       s = String("stdev_x = " + String(stdev_x) + ", stdev_y = " + String(stdev_y));
  238.       Serial.println(s);   
  239.       /* now average the samples that are less than one standard deviation from the mean */
  240.       /* this filtering is called "outlier rejection," and is included because outliers were observed in testing */
  241.       good_samples = 0;
  242.       filt_mean_x = 0;
  243.       filt_mean_y = 0;
  244.       for (i = 0; i < 100; i++) {
  245.         if ((abs((float)samples[i][0] - mean_x) < stdev_x) && (abs((float)samples[i][1] - mean_y) < stdev_y)) {
  246.           filt_mean_x += (float)samples[i][0];
  247.           filt_mean_y += (float)samples[i][1];
  248.           good_samples++;
  249.         }        
  250.       }
  251.       s = String("Good samples = " + String(good_samples));
  252.       Serial.println(s);      
  253.       filt_mean_x = filt_mean_x / (float)good_samples;
  254.       filt_mean_y = filt_mean_y / (float)good_samples;
  255.       s = String("Filtered values:  filt_mean_x = " + String(filt_mean_x) + ", filt_mean_y = " + String(filt_mean_y));
  256.       Serial.println(s);
  257.       Serial.println();
  258.       *x_avg = (int)mean_x;
  259.       *y_avg = (int)mean_y;
  260.       *finished = true;
  261.     }
  262.   }
  263.   else {
  264.     // nada
  265.   }
  266. }
  267. /* Function to display a user instruction on startup */
  268. void lv_display_instruction(void) {
  269.   // Create a text label aligned center: https://docs.lvgl.io/master/widgets/label.html
  270.   lv_obj_t * text_label = lv_label_create(lv_screen_active());
  271.   lv_label_set_text(text_label, "Tap each crosshair until it disappears.");
  272.   lv_obj_align(text_label, LV_ALIGN_CENTER, 0, 0);
  273.   // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html
  274.   static lv_style_t style_text_label;
  275.   lv_style_init(&style_text_label);
  276.   lv_style_set_text_font(&style_text_label, &lv_font_montserrat_14);
  277.   lv_obj_add_style(text_label, &style_text_label, 0);
  278. }
  279. /* function to display crosshair at given index of coordinates array */
  280. void display_crosshair(int cross_nr) {
  281.   static lv_point_precise_t h_line_points[] = { {0, 0}, {10, 0} };
  282.   static lv_point_precise_t v_line_points[] = { {0, 0}, {0, 10} };
  283.   static lv_style_t style_line;
  284.   lv_style_init(&style_line);
  285.   lv_style_set_line_width(&style_line, 2);
  286.   lv_style_set_line_color(&style_line, lv_palette_main(LV_PALETTE_RED));
  287.   lv_style_set_line_rounded(&style_line, true);
  288.   // Create crosshair lines
  289.   lv_obj_t* crosshair_h = lv_line_create(lv_screen_active());
  290.   lv_obj_t* crosshair_v = lv_line_create(lv_screen_active());
  291.   lv_line_set_points(crosshair_h, h_line_points, 2); // Set the coordinates for the crosshair_h line
  292.   lv_obj_add_style(crosshair_h, &style_line, 0);
  293.   lv_line_set_points(crosshair_v, v_line_points, 2); // Set the coordinates for the crosshair_h line
  294.   lv_obj_add_style(crosshair_v, &style_line, 0);
  295.   lv_obj_set_pos(crosshair_h, scr_points[cross_nr][0] - 5, scr_points[cross_nr][1]);
  296.   lv_obj_set_pos(crosshair_v, scr_points[cross_nr][0], scr_points[cross_nr][1] - 5);
  297. }
  298. /* function to display crosshairs at given coordinates */
  299. void display_crosshairs(int x, int y) {
  300.   static lv_point_precise_t h_line_points[] = { {0, 0}, {10, 0} };
  301.   static lv_point_precise_t v_line_points[] = { {0, 0}, {0, 10} };
  302.   static lv_style_t style_line;
  303.   lv_style_init(&style_line);
  304.   lv_style_set_line_width(&style_line, 2);
  305.   lv_style_set_line_color(&style_line, lv_palette_main(LV_PALETTE_BLUE));
  306.   lv_style_set_line_rounded(&style_line, true);
  307.   // Create crosshair lines
  308.   lv_obj_t* crosshair_h = lv_line_create(lv_screen_active());
  309.   lv_obj_t* crosshair_v = lv_line_create(lv_screen_active());
  310.   lv_line_set_points(crosshair_h, h_line_points, 2); // Set the coordinates for the crosshair_h line
  311.   lv_obj_add_style(crosshair_h, &style_line, 0);
  312.   lv_line_set_points(crosshair_v, v_line_points, 2); // Set the coordinates for the crosshair_h line
  313.   lv_obj_add_style(crosshair_v, &style_line, 0);
  314.   lv_obj_set_pos(crosshair_h, x - 5, y);
  315.   lv_obj_set_pos(crosshair_v, x, y - 5);
  316. }
  317. /* function to display 'X's at given coordinates */
  318. void display_xs(int x, int y) {
  319.   static lv_point_precise_t u_line_points[] = { {0, 0}, {10, 10} };  //upsloping
  320.   static lv_point_precise_t d_line_points[] = { {0, 10}, {10, 0} };  //downsloping
  321.   static lv_style_t style_line;
  322.   lv_style_init(&style_line);
  323.   lv_style_set_line_width(&style_line, 2);
  324.   lv_style_set_line_color(&style_line, lv_palette_main(LV_PALETTE_RED));
  325.   lv_style_set_line_rounded(&style_line, true);
  326.   // Create crosshair lines
  327.   lv_obj_t* x_u = lv_line_create(lv_screen_active());
  328.   lv_obj_t* x_d = lv_line_create(lv_screen_active());
  329.   lv_line_set_points(x_u, u_line_points, 2); // Set the coordinates for the upsloping line
  330.   lv_obj_add_style(x_u, &style_line, 0);
  331.   lv_line_set_points(x_d, d_line_points, 2); // Set the coordinates for the downsloping line
  332.   lv_obj_add_style(x_d, &style_line, 0);
  333.   lv_obj_set_pos(x_u, x - 5, y - 5);
  334.   lv_obj_set_pos(x_d, x - 5, y - 5);
  335. }
  336. /* function to compute the transformation equation coefficients from resistive touchscreen
  337.    coordinates to display coordinates...
  338.   This was based on the Texas Instruments appnote at:
  339.   https://www.ti.com/lit/an/slyt277/slyt277.pdf
  340.   It implements Equation 7 of that appnote, which computes a least-squares set of coefficients. */
  341. void ts_calibration (
  342.         const point aS, const point aT,
  343.         const point bS, const point bT,
  344.         const point cS, const point cT,
  345.   const point dS, const point dT,
  346.         const point eS, const point eT,
  347.         const point fS, const point fT) {
  348.         bool defined;
  349.         uint16_t screenWidth, screenHeight;
  350.   BLA::Matrix<6, 3> A;
  351.   BLA::Matrix<3, 6> transA;
  352.   BLA::Matrix<6> X;
  353.   BLA::Matrix<6> Y;
  354.   BLA::Matrix<3, 3> B;
  355.   BLA::Matrix<3, 6> C;
  356.   BLA::Matrix<3> X_coeff;
  357.   BLA::Matrix<3> Y_coeff;
  358.   s = String("aS = " + String(aS.x) + ", " + String(aS.y));
  359.   Serial.println(s);
  360.   s = String("bS = " + String(bS.x) + ", " + String(bS.y));
  361.   Serial.println(s);
  362.   s = String("cS = " + String(cS.x) + ", " + String(cS.y));
  363.   Serial.println(s);
  364.   s = String("dS = " + String(dS.x) + ", " + String(dS.y));
  365.   Serial.println(s);
  366.   s = String("eS = " + String(eS.x) + ", " + String(eS.y));
  367.   Serial.println(s);
  368.   s = String("fS = " + String(fS.x) + ", " + String(fS.y));
  369.   Serial.println(s);
  370.   s = String("aT = " + String(aT.x) + ", " + String(aT.y));
  371.   Serial.println(s);
  372.   s = String("bT = " + String(bT.x) + ", " + String(bT.y));
  373.   Serial.println(s);
  374.   s = String("cT = " + String(cT.x) + ", " + String(cT.y));
  375.   Serial.println(s);
  376.   s = String("eT = " + String(dT.x) + ", " + String(dT.y));
  377.   Serial.println(s);
  378.   s = String("eT = " + String(eT.x) + ", " + String(eT.y));
  379.   Serial.println(s);
  380.   s = String("fT = " + String(fT.x) + ", " + String(fT.y));
  381.   Serial.println(s);
  382.   Serial.println();
  383.   struct f_point {
  384.     float x;
  385.     float y;
  386.   };
  387.   struct f_point faS, fbS, fcS, fdS, feS, ffS, faT, fbT, fcT, fdT, feT, ffT;
  388.   faS.x = (float)aS.x; fbS.x = (float)bS.x; fcS.x = (float)cS.x, fdS.x = (float)dS.x; feS.x = (float)eS.x; ffS.x = (float)fS.x;
  389.   faS.y = (float)aS.y; fbS.y = (float)bS.y; fcS.y = (float)cS.y; fdS.y = (float)dS.y; feS.y = (float)eS.y; ffS.y = (float)fS.y;
  390.   faT.x = (float)aT.x; fbT.x = (float)bT.x; fcT.x = (float)cT.x; fdT.x = (float)dT.x; feT.x = (float)eT.x; ffT.x = (float)fT.x;
  391.   faT.y = (float)aT.y; fbT.y = (float)bT.y; fcT.y = (float)cT.y; fdT.y = (float)dT.y; feT.y = (float)eT.y; ffT.y = (float)fT.y;
  392.   A = { faT.x, faT.y, 1,
  393.         fbT.x, fbT.y, 1,
  394.         fcT.x, fcT.y, 1,
  395.         fdT.x, fdT.y, 1,
  396.         feT.x, feT.y, 1,            
  397.         ffT.x, ffT.y, 1 };
  398.   X = { faS.x,
  399.         fbS.x,
  400.         fcS.x,
  401.         fdS.x,
  402.         feS.x,
  403.         ffS.x };
  404.   Y = { faS.y,
  405.         fbS.y,
  406.         fcS.y,
  407.         fdS.y,
  408.         feS.y,
  409.         ffS.y };
  410.   /* Now compute [AtA]^-1 * AtA * X and [AtA]^-1 * AtA * Y */
  411.   Serial.print ("A = ");
  412.   Serial.println(A);
  413.   transA = ~A;
  414.   Serial.print ("transA = ");
  415.   Serial.println(transA);
  416.   B = transA * A;
  417.   Serial.print ("Before inversion, B = ");
  418.   Serial.println(B);
  419.   if (!Invert(B) ) {
  420.     Serial.println("Singular matrix in computation of inverse of B = transA*A!");
  421.   }
  422.   Serial.print ("After inversion, B = ");
  423.   Serial.println(B);
  424.   C = B * transA;
  425.   Serial.print ("C = ");
  426.   Serial.println(C);
  427.   X_coeff = C * X;
  428.   Y_coeff = C * Y;
  429.   /* transfer the X and Y coefficients to the Greek-letter variables
  430.      Note that BLA requires round brackets while MatrixMath requires square ones */
  431.   alphaX = X_coeff(0); betaX = X_coeff(1); deltaX = X_coeff(2);
  432.   alphaY = Y_coeff(0); betaY = Y_coeff(1); deltaY = Y_coeff(2);
  433.   Serial.println();
  434. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 15:50:06

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

运行该程序后,您应该使用触控笔(显示屏随附的触控笔)在初始文本显示后一次显示一个的六个“+”号的中心重复并尽可能精确地点击每个符号的中心。

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 15:53:59

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

当 “+” 号消失时停止点击,并观察另一个 “+” 号的出现,“+” 号总共出现 6 次。

在草图处理完您用点击创建的电阻式触摸屏样本后,在校准程序之后,它将显示六个“+”符号,在它认为您点击的地方显示六个“×”。

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 15:57:17

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

实验串口返回情况

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 16:07:02

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

USE THE FOLLOWING COEFFICIENT VALUES TO CALIBRATE YOUR TOUCHSCREEN
Computed X:  alpha_x = 0.000, beta_x = 0.092, delta_x = -39.506
Computed Y:  alpha_y = 0.066, beta_y = -0.001, delta_y = -14.610


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 16:08:42

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

  【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
  项目实验之二十一:ESP32 CYD液晶2.8寸开发板电阻式触摸屏使用校准方程来测试触摸屏
  (在运行代码之前,请确保修改代码以使用在上一个测试中获得的系数。)

实验开源代码

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
  4.   项目实验之二十一:ESP32 CYD液晶2.8寸开发板电阻式触摸屏使用校准方程来测试触摸屏
  5.   (在运行代码之前,请确保修改代码以使用在上一个测试中获得的系数。)
  6. */
  7. #include <lvgl.h>                 // 引入LVGL图形库
  8. #include <TFT_eSPI.h>             // 引入TFT_eSPI库,用于驱动TFT显示屏
  9. #include <XPT2046_Touchscreen.h>  // 引入XPT2046触摸屏库
  10. // Touchscreen pins
  11. #define XPT2046_IRQ 36   // T_IRQ
  12. #define XPT2046_MOSI 32  // T_DIN
  13. #define XPT2046_MISO 39  // T_OUT
  14. #define XPT2046_CLK 25   // T_CLK
  15. #define XPT2046_CS 33    // T_CS
  16. SPIClass touchscreenSPI = SPIClass(VSPI);
  17. XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
  18. #define SCREEN_WIDTH 240
  19. #define SCREEN_HEIGHT 320
  20. // Touchscreen coordinates: (x, y) and pressure (z)
  21. int x, y, z;
  22. #define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
  23. uint32_t draw_buf[DRAW_BUF_SIZE / 4];
  24. // If logging is enabled, it will inform the user about what is happening in the library
  25. void log_print(lv_log_level_t level, const char * buf) {
  26.   LV_UNUSED(level);
  27.   Serial.println(buf);
  28.   Serial.flush();
  29. }
  30. static lv_obj_t * text_label_touch;
  31. // Get the Touchscreen data
  32. void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data) {
  33.   // Checks if Touchscreen was touched, and prints X, Y and Pressure (Z)
  34.   if(touchscreen.tirqTouched() && touchscreen.touched()) {
  35.     // Get Touchscreen points
  36.     TS_Point p = touchscreen.getPoint();
  37.     // Advanced Touchscreen calibration, LEARN MORE » https://RandomNerdTutorials.com/touchscreen-calibration/
  38.     float alpha_x, beta_x, alpha_y, beta_y, delta_x, delta_y;
  39.     // REPLACE WITH YOUR OWN CALIBRATION VALUES » https://RandomNerdTutorials.com/touchscreen-calibration/
  40.     alpha_x = -0.000;
  41.     beta_x  =  0.092;
  42.     delta_x = -39.506;
  43.     alpha_y =  0.066;
  44.     beta_y =  -0.001;
  45.     delta_y = -14.610;
  46.     x = alpha_y * p.x + beta_y * p.y + delta_y;
  47.     // clamp x between 0 and SCREEN_WIDTH - 1
  48.     x = max(0, x);
  49.     x = min(SCREEN_WIDTH - 1, x);
  50.     y = alpha_x * p.x + beta_x * p.y + delta_x;
  51.     // clamp y between 0 and SCREEN_HEIGHT - 1
  52.     y = max(0, y);
  53.     y = min(SCREEN_HEIGHT - 1, y);
  54.     // Basic Touchscreen calibration points with map function to the correct width and height
  55.     //x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
  56.     //y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
  57.     z = p.z;
  58.     data->state = LV_INDEV_STATE_PRESSED;
  59.     // Set the coordinates
  60.     data->point.x = x;
  61.     data->point.y = y;
  62.     // Print Touchscreen info about X, Y and Pressure (Z) on the Serial Monitor
  63.     Serial.print("X = ");
  64.     Serial.print(x);
  65.     Serial.print(" | Y = ");
  66.     Serial.print(y);
  67.     Serial.print(" | Pressure = ");
  68.     Serial.print(z);
  69.     Serial.println();
  70.     // Print the coordinates on the screen
  71.     String touch_data = "X = " + String(x) + "\nY = " + String(y) + "\nZ = " + String(z);
  72.     lv_label_set_text(text_label_touch, touch_data.c_str());
  73.   }
  74.   else {
  75.     data->state = LV_INDEV_STATE_RELEASED;
  76.   }
  77. }
  78. void lv_create_main_gui(void) {
  79.   // Create a text label aligned center: https://docs.lvgl.io/master/widgets/label.html
  80.   text_label_touch = lv_label_create(lv_screen_active());
  81.   lv_label_set_text(text_label_touch, "Touch screen to test");
  82.   lv_obj_align(text_label_touch, LV_ALIGN_CENTER, 0, 0);
  83.   // Set font type and size. More information: https://docs.lvgl.io/master/overview/font.html
  84.   static lv_style_t style_text_label;
  85.   lv_style_init(&style_text_label);
  86.   lv_style_set_text_font(&style_text_label, &lv_font_montserrat_18);
  87.   lv_obj_add_style(text_label_touch, &style_text_label, 0);
  88. }
  89. void setup() {
  90.   String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
  91.   Serial.begin(115200);
  92.   Serial.println(LVGL_Arduino);
  93.   
  94.   // Start LVGL
  95.   lv_init();
  96.   // Register print function for debugging
  97.   lv_log_register_print_cb(log_print);
  98.   // Start the SPI for the touchscreen and init the touchscreen
  99.   touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  100.   touchscreen.begin(touchscreenSPI);
  101.   // Set the Touchscreen rotation in landscape mode
  102.   // Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 0: touchscreen.setRotation(0);
  103.   touchscreen.setRotation(2);
  104.   // Create a display object
  105.   lv_display_t * disp;
  106.   // Initialize the TFT display using the TFT_eSPI library
  107.   disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
  108.   lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
  109.    
  110.   // Initialize an LVGL input device object (Touchscreen)
  111.   lv_indev_t * indev = lv_indev_create();
  112.   lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  113.   // Set the callback function to read Touchscreen input
  114.   lv_indev_set_read_cb(indev, touchscreen_read);
  115.   // Function to draw the GUI with switches
  116.   lv_create_main_gui();
  117. }
  118. void loop() {
  119.   lv_task_handler();  // let the GUI do its work
  120.   lv_tick_inc(5);     // tell LVGL how much time has passed
  121.   delay(5);           // let this time pass
  122. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 16:19:21

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

实验串口返回情况

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 16:22:33

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

现在,当您触摸屏幕时,您应该会获得校准的 X 和 Y 值。

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 2024-11-10 16:23:56

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图1

【花雕学编程】Arduino动手做(238)--ESP32 CYD触摸屏校准图2
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail