跳过正文

Rust 驱动 Touch - 触摸板

·1332 字
Rust Esp32 Rust Esp32
rust-esp32 - 这篇文章属于一个选集。
§ 15: 本文

参考: https://docs.espressif.com/projects/espressif-esp-iot-solution/zh_CN/latest/input_device/touch_panel.html

在实际应用中,电阻触摸屏必须在使用前进行校准,而电容触摸屏则一般由控制芯片完成该工作,无需额外的校准步骤。驱动中已经集成了电阻触摸屏的校准算法,校准过程使用了三个点来校准,用一个点来验证,当最后验证的误差大于某个阈值将导致校准失败,然后自动重新进行校准,直到校准成功。

调用校准函数 calibration_run() 将会在屏幕上开始校准的过程,校准完成后,参数将 保存在 NVS 中用于下次启动,避免每次使用前的重复校准。

触摸屏按下:不论是电阻还是电容触摸屏,通常的触摸屏控制芯片会有一个用于 通知触摸事件的中断引脚 。但是驱动中没有使用该信号,一方面是因为对于有屏幕的应用需要尽量节省出 IO 给其他外设;另一方面是触摸控制器给出的该信号 不如程序通过寄存器数据判断的准确性高 。对于电阻触摸屏来说,判断按下的依据是 Z 方向的压力大于配置的阈值;对于电容触摸屏则是判断至少有一个触摸点存在。

触摸屏的旋转:触摸屏具有与显示屏一样的 8 个方向 ,定义在 touch_panel_dir_t 中。这里的旋转是通过软件换算来实现的,通常把二者的方向设置为相同。但这并不是一成不变的,例如:在使用电容触摸屏时,有可能触摸屏固有的方向与显示屏原始显示方向不一致,如果简单的将这两个方向设置为相同后,将无法正确的点击屏幕内容,这时需要根据实际情况调整。

触摸屏的分辨率设置也是很重要的,因为触摸屏旋转后的换算依赖于触摸屏的宽和高分辨率大小,设置不当将无法得到正确的旋转效果。

电阻触摸:需要校正;

电容触摸:不需要校正,支持多点触摸,而且有些支持固定速率的触摸按钮。

NS2009 电阻触摸:提供 press + position 功能; FT6X36: 电容触摸:只能提供 position 功能;

初始化:

// https://docs.espressif.com/projects/espressif-esp-iot-solution/zh_CN/latest/input_device/touch_panel.html#id5
touch_panel_driver_t touch; // a touch panel driver

i2c_config_t i2c_conf = {
    .mode = I2C_MODE_MASTER,
    .sda_io_num = 35,
    .sda_pullup_en = GPIO_PULLUP_ENABLE,
    .scl_io_num = 36,
    .scl_pullup_en = GPIO_PULLUP_ENABLE,
    .master.clk_speed = 100000,
};
i2c_bus_handle_t i2c_bus = i2c_bus_create(I2C_NUM_0, &i2c_conf);

touch_panel_config_t touch_cfg = {
    .interface_i2c = {
        .i2c_bus = i2c_bus,
        .clk_freq = 100000,
        .i2c_addr = 0x38,
    },
    .interface_type = TOUCH_PANEL_IFACE_I2C,
    .pin_num_int = -1,
    .direction = TOUCH_DIR_LRTB,
    .width = 800,
    .height = 480,
};

/* Initialize touch panel controller FT5x06 */
touch_panel_find_driver(TOUCH_PANEL_CONTROLLER_FT5X06, &touch);
touch.init(&touch_cfg);

/* start to run calibration */
touch.calibration_run(&lcd, false);

获取触摸屏是否按下及其触点坐标:

touch_panel_points_t points;
touch.read_point_data(&points);
int32_t x = points.curx[0];
int32_t y = points.cury[0];
if(TOUCH_EVT_PRESS == points.event) {
    ESP_LOGI(TAG, "Pressed, Touch point at (%d, %d)", x, y);
}

ESP32 Flappy Bird:https://github.com/Makerfabs/Project_ESP32-Flappy-Bird/tree/master

  1. LCD 3.5 inch Amorphous-TFT-LCD (Thin Film Transistor Liquid Crystal Display) for mobile-phone or handy electrical equipments.
  2. NS2009 is A 4-wire resistive touch screen control circuit with I2C interface, which contains A 12-bit resolution A/D converter.
  3. The FT6X36 Series ICs are single-chip capacitive touch panel controller IC with a built-in 16 bit enhanced Micro-controller unit (MCU).

touch controller 一般是通过 I2C/SPI 接口来读取的:

  • SPI 接口: 如 STMPE610 ,一般和 LCD SPI 接口复用,通过 CS 信号来区分;

NS2009: https://github.com/Makerfabs/Project_Touch-Screen-Camera/blob/master/example/touch_draw_v2/NS2009.cpp

#include "NS2009.h"

//I2C receive
void ns2009_recv(const uint8_t *send_buf, size_t send_buf_len, uint8_t *receive_buf,
                 size_t receive_buf_len)
{
    Wire.beginTransmission(NS2009_ADDR);
    Wire.write(send_buf, send_buf_len);
    Wire.endTransmission();
    Wire.requestFrom(NS2009_ADDR, receive_buf_len);
    while (Wire.available())
    {
        *receive_buf++ = Wire.read();
    }
}

//read 12bit data
unsigned int ns2009_read(uint8_t cmd)
{
    uint8_t buf[2];
    ns2009_recv(&cmd, 1, buf, 2);
    return (buf[0] << 4) | (buf[1] >> 4);
}

//Press maybe not correct
int ns2009_get_press()
{
    return ns2009_read(NS2009_LOW_POWER_READ_Z1);
}

int ns2009_pos(int pos[2])
{
    int press = ns2009_read(NS2009_LOW_POWER_READ_Z1);

    int x, y = 0;

    x = ns2009_read(NS2009_LOW_POWER_READ_X);
    y = ns2009_read(NS2009_LOW_POWER_READ_Y);

    pos[0] = x * SCREEN_X_PIXEL / 4096; //4096 = 2 ^ 12
    pos[1] = y * SCREEN_Y_PIXEL / 4096;

    //pos[0] = x;
    //pos[1] = y;
    return press;
}

FT6236:

// https://github.com/Makerfabs/Makerfabs-ESP32-S3-Parallel-TFT-with-Touch/blob/main/example/touch_keyboard_v2/FT6236.cpp
#include "FT6236.h"

int readTouchReg(int reg)
{
    int data = 0;
    Wire.beginTransmission(TOUCH_I2C_ADD);
    Wire.write(reg);
    Wire.endTransmission();
    Wire.requestFrom(TOUCH_I2C_ADD, 1);
    if (Wire.available())
    {
        data = Wire.read();
    }
    return data;
}

/*
int getTouchPointX()
{
    int XL = 0;
    int XH = 0;

    XH = readTouchReg(TOUCH_REG_XH);
    XL = readTouchReg(TOUCH_REG_XL);

    return ((XH & 0x0F) << 8) | XL;
}
*/

int getTouchPointX()
{
    int XL = 0;
    int XH = 0;

    XH = readTouchReg(TOUCH_REG_XH);
    //Serial.println(XH >> 6,HEX);
    if(XH >> 6 == 1)
        return -1;
    XL = readTouchReg(TOUCH_REG_XL);

    return ((XH & 0x0F) << 8) | XL;
}

int getTouchPointY()
{
    int YL = 0;
    int YH = 0;

    YH = readTouchReg(TOUCH_REG_YH);
    YL = readTouchReg(TOUCH_REG_YL);

    return ((YH & 0x0F) << 8) | YL;
}

int ft6236_pos(int pos[2])
{
    int XL = 0;
    int XH = 0;
    int YL = 0;
    int YH = 0;

    XH = readTouchReg(TOUCH_REG_XH);
    if(XH >> 6 == 1)
    {
        pos[0] = -1;
        pos[1] = -1;
        return 0;
    }
    XL = readTouchReg(TOUCH_REG_XL);
    YH = readTouchReg(TOUCH_REG_YH);
    YL = readTouchReg(TOUCH_REG_YL);

    pos[0] = ((XH & 0x0F) << 8) | XL;
    pos[1] = ((YH & 0x0F) << 8) | YL;
    return 1;
}

Makerfabs ESP32-S3 Parallel TFT with Touch: https://github.com/Makerfabs/Makerfabs-ESP32-S3-Parallel-TFT-with-Touch

ESP32 3.5" TFT Touch with Camera: https://wiki.makerfabs.com/ESP32_3.5_TFT_Touch_with_Camera.html

大量 LCD+Touch 的例子:https://github.com/Makerfabs/Project_Touch-Screen-Camera

rust-esp32 - 这篇文章属于一个选集。
§ 15: 本文

相关文章

Rust 驱动 Audio - 播放和录音
·6323 字
Rust Esp32 Rust Esp32
Rust 驱动 Camera - 采集和播放
·7304 字
Rust Esp32 Rust Esp32
Rust 驱动 LCD - 显示中英文
·818 字
Rust Esp32 Rust Esp32
Rust 驱动 LCD - 显示图片
·4232 字
Rust Esp32 Rust Esp32