vesperW · 2022年12月27日 · 广东

【聆思CSK6 视觉AI开发套件试用】触摸屏功能实现控制手势识别体验与PWM控制电机运行

概述

非常高兴参与极术社区和聆思科技举办的开发板申请试用活动并有机会试用,年前导入我们公司新项目上应用(PCB板上丝印文字的视觉AI应用),上手有了聆思科技工程师们编写的详细入门操作的文档,跑例程变得非常简单(设备树的开发模式优点非常多),与硬件的文档和例程配套完善。

聆思科技CSK6系列芯片搭载了安谋科技“星辰”STAR-MC1处理器,同时采用了多核异构的设计,运行 300MHz 和算力 128GOPS,实现以较低功耗满足音频、图像的AI应用需求,多达33个可配置的GPIO。板载CSK6核心模组以及上手开发常用的硬件外设(如LED、按键、调试器等),并将可用引脚全部引出至2.54mm 的排针上, 方便用户快速进行新应用开发与焊接到工程样机上验证,CSK6核心模组集成了CSK6系芯片及其外围最小电路的单元,支持直接用于量产。头肩识别的体验步骤在这不描述了(能机器学习了,练习样本就大有应用场景),重点触摸屏功能实现控制电机(后面会补上视觉 AI 电机联合工作的文章)。

LCD屏显示实现触摸功能

驱动320* 240 ST7789的SPI屏幕进行内容显示,显示文字和触控屏的基本使用;参考了:驱动模型中定义了可供上层应用调用的关键接口,如 读/写framebuffer 、开/关触控动作的操作画面 、获取屏幕设备信息 、 设置亮度/对比度/像素格式/方向等。

下图为触控屏的四个触控开/关四个电机的“按键”
图一 上电开机后显示.jpg
图一(上电开机后显示)

图二 1号电机工作.jpg
图二(1号电机工作)

图三 2号电机工作.jpg
图三(2号电机工作)

图四 3号电机工作.jpg
图四(3号电机工作)
图五 4号电机工作.jpg
图五(4号电机工作)

图六 等待操作的状态.jpg
图六(等待操作的状态)

显示触控屏的常用API接口

void display_get_capabilities(const struct device *dev, struct display_capabilities *capabilities)

参数说明
图七_屏的API接口参数说明.JPG
图七

操作是按https://docs.listenai.com/chips/600X/applicati n/modules/display_kscan,详细的显示驱动API接口请查阅zephyr官网Display Interface。

显示屏设备树配置

&csk6002_9s_nano_pinctrl{
            ...
            /* 显示屏SPI接口配置 */
            pinctrl_spi0_sclk_default: spi0_sclk_default {
                    pinctrls = < &pinmuxa 15 6 >;
            };
            pinctrl_spi0_mosi_default: spi0_mosi_default {
                    pinctrls = < &pinmuxa 10 6 >;
            };
            pinctrl_spi0_miso_default: spi0_miso_default {
                    pinctrls = < &pinmuxa 17 6 >;
            };
            pinctrl_spi0_cs_default: spi0_cs_default {
                    pinctrls = < &pinmuxa 12 6 >;
            }; 
};

触摸屏设备树配置

用到引脚:i2c0_scl(pb2)、i2c0_sda(pb3)。

在 csk6011a_nano.overlay中完成外设接口的配置,具体实现如下:
在app/boards/目录下的csk6002_9s_nano.overlay文件并添加如下设备树配置:
图八_overlay设备树配置.JPG
图八

&csk6002_9s_nano_pinctrl{
   // ...
    /* 触摸屏I2C接口配置 */
    pinctrl_i2c0_scl_default: i2c0_scl_default{
            pinctrls = <&pinmuxb 2 8>;
    };
    
    pinctrl_i2c0_sda_default: i2c0_sda_default{
            pinctrls = <&pinmuxb 3 8>;
    }; 
};

&i2c0 {
        status = "okay";
        pinctrl-0 = <&pinctrl_i2c0_scl_default &pinctrl_i2c0_sda_default>; 
        pinctrl-names = "default";
        ft5336@0 {
                compatible = "focaltech,ft5336";
                reg = <0x38>;
                label = "FT5336";
                status = "okay";
                int-gpios = <&gpioa 3 0>;
        };
};

日志串口设备树配置

本示例中将SDK默认的日志串口(GPIOA_2、GPIOA_3)中的GPIOA_3复用为触控屏的int使能脚,因此将日志输出串口配置为GPIOb_10 、GPIOb_11,具体如下:

&csk6002_9s_nano_pinctrl{  
            /* 日志串口配置 */
            pinctrl_uart0_rx_default: uart0_rx_default{
                    pinctrls = <&pinmuxb 10 2>;
            };
            
            pinctrl_uart0_tx_default: uart0_tx_default{
                    pinctrls = <&pinmuxb 11 2>;
            };
            ...
};

触摸屏组件配置

在prj.conf文件中打开触摸屏功能配置:

触摸配置
CONFIG_KSCAN=y
I2C功能配置
CONFIG_I2C=y
触摸屏屏驱动配置
CONFIG_KSCAN_BL6XXX=y

显示屏组件配置

在prj.conf文件中打开显示屏功能配置:

CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_LOG=y

GPIO功能配置
CONFIG_GPIO=y
显示功能配置
CONFIG_DISPLAY=y
spi功能配置
CONFIG_SPI=y
ST7789V显示屏驱动配置
CONFIG_ST7789V=y

LCD屏显示实现

void main(void)
{
    size_t x;
    size_t y;
    size_t rect_w;
    size_t rect_h;
    size_t h_step;
    size_t scale;
    size_t grey_count;
    uint8_t *buf;
    int32_t grey_scale_sleep;
    const struct device *display_dev;
    struct display_capabilities capabilities;
    struct display_buffer_descriptor buf_desc;
    size_t buf_size = 0;
    fill_buffer fill_buffer_fnc = NULL;

    LOG_INF("Display sample for %s", DISPLAY_DEV_NAME);
    
    /* kscan初始化 */
    kscan_init();
    
    /* 获取display设备实例 */
    display_dev = device_get_binding(DISPLAY_DEV_NAME);

    if (display_dev == NULL) {
        LOG_ERR("Device %s not found. Aborting sample.",
            DISPLAY_DEV_NAME);
        RETURN_FROM_MAIN(1);
    }
    
    /* 获取显示功能 */
    display_get_capabilities(display_dev, &capabilities);

    if (capabilities.screen_info & SCREEN_INFO_MONO_VTILED) {
        rect_w = 32;
        rect_h = 10;
    } else {
        rect_w = 2;
        rect_h = 1;
    }

    h_step = rect_h;
    scale = (capabilities.x_resolution / 8) / rect_h;

    rect_w *= scale;
    rect_h *= scale;

    if (capabilities.screen_info & SCREEN_INFO_EPD) {
        grey_scale_sleep = 10000;
    } else {
        grey_scale_sleep = 100;
    }

    buf_size = rect_w * rect_h;

    if (buf_size < (capabilities.x_resolution * h_step)) {
        buf_size = capabilities.x_resolution * h_step;
    }
    
    /* 色块配置 */
    switch (capabilities.current_pixel_format) {
    case PIXEL_FORMAT_ARGB_8888:
        fill_buffer_fnc = fill_buffer_argb8888;
        buf_size *= 4;
        break;
    case PIXEL_FORMAT_RGB_888:
        fill_buffer_fnc = fill_buffer_rgb888;
        buf_size *= 3;
        break;
    case PIXEL_FORMAT_RGB_565:
        fill_buffer_fnc = fill_buffer_rgb565;
        buf_size *= 2;
        break;
    case PIXEL_FORMAT_BGR_565:
        fill_buffer_fnc = fill_buffer_bgr565;
        buf_size *= 2;
        break;
    case PIXEL_FORMAT_MONO01:
    case PIXEL_FORMAT_MONO10:
        fill_buffer_fnc = fill_buffer_mono;
        buf_size /= 8;
        break;
    default:
        LOG_ERR("Unsupported pixel format. Aborting sample.");
        RETURN_FROM_MAIN(1);
    }

    buf = k_malloc(buf_size);

    if (buf == NULL) {
        LOG_ERR("Could not allocate memory. Aborting sample.");
        RETURN_FROM_MAIN(1);
    }
    
    (void)memset(buf, 0xFFu, buf_size);

    buf_desc.buf_size = buf_size;
    buf_desc.pitch = capabilities.x_resolution;
    buf_desc.width = capabilities.x_resolution;
    buf_desc.height = h_step;

    /*整屏填充白色背景*/
    for (int idx = 0; idx < capabilities.y_resolution; idx += h_step) {
        display_write(display_dev, 0, idx, &buf_desc, buf);
    }

    /*左上角填充红色块*/
    fill_buffer_fnc(TOP_LEFT, 0, buf, buf_size);
    x = 0;
    y = 0;
    display_write(display_dev, x, y, &buf_desc, buf);

    /*右上角填充绿色块*/
    fill_buffer_fnc(TOP_RIGHT, 0, buf, buf_size);
    x = capabilities.x_resolution - rect_w;
    y = 0;
    display_write(display_dev, x, y, &buf_desc, buf);

    /*右下角填充蓝色块*/
    fill_buffer_fnc(BOTTOM_RIGHT, 0, buf, buf_size);
    x = capabilities.x_resolution - rect_w;
    y = capabilities.y_resolution - rect_h;
    display_write(display_dev, x, y, &buf_desc, buf);
    
    /* 关闭显示消隐 */
    display_blanking_off(display_dev);

    grey_count = 0;
    x = 0;
    y = capabilities.y_resolution - rect_h;

    /*左下角灰色动态色块*/
    while (1) {
        fill_buffer_fnc(BOTTOM_LEFT, grey_count, buf, buf_size);
        display_write(display_dev, x, y, &buf_desc, buf);
        ++grey_count;
        k_msleep(grey_scale_sleep);
    }
}

触摸屏功能实现

Zephyr具备kscan(keyboard scan matrix)驱动模型,其驱动程序用于检测矩阵键盘或带有按钮的设备中的按键(用户触碰触摸屏本质上是生成一个行列坐标)。查阅zephyr官网Display Interface。
https://docs.zephyrproject.org/latest/doxygen/html/group__display__interface.html
图九_LCD点阵坐标触控1.JPG
图九

注册callback函数

/* 触摸回调函数,打印坐标 */
static void k_callback(const struct device *dev, uint32_t row, uint32_t col,
               bool pressed)
{
    ARG_UNUSED(dev);
    printk("row = %u col = %u, pressed:%s\n", row, col, pressed ? "TRUE" : "FLASE");
}

void kscan_init(void)
{   
    /* 获取kscan设备实例 */
    const struct device *kscan_dev = device_get_binding(DISPLAY_KSAN_DEV_NAME);

    if (!device_is_ready(kscan_dev)) {
        LOG_ERR("kscan device %s not ready", kscan_dev->name);
        return;
    }
    
    /* 注册回调,在k_callback中可看到对应的坐标与状态printk输出操作 */
    kscan_config(kscan_dev, k_callback);
    /* 使能回调 */
    kscan_enable_callback(kscan_dev);
}

void main(void)
{
    kscan_init();
    ...
}

编译的指令是:
lisa zep build

烧录的指令是:
lisa zep flash

结果

触控屏显示了四个触控开关符,分别触摸对应显示在(LED1符 LED2符 LED3符 LED4符的下面触控开关)。四个功能(GPIO) PWM 控制电机运行,后面补上(高发性的疫情过后,回公司上班补上,焊接上电机驱动板)。我们开发了一个PC上位机软件(视觉图分析用)。GC032A摄像头上传的图像以后可以在触控屏显(一个静态图)。
图十_图像LCD点阵坐标分析.JPG
图十

总结

非常感谢极术社区和聆思科技给予及时的试用机会(以前我们用TI开发视觉应用,芯片难买),通过连接显示屏的试用,开发者很便捷方便地配置硬件信息,体验了视觉例程demo简单的上手,以前在TI开发平台上是做不到这样简易的;后面会分几部分:

通过触摸屏编辑菜单的功能、视觉和电机(霍尔传感器、编码器)的应用综合在一起发文章出来。具体功能先先放在这,后面文章中有信息。

推荐阅读
关注数
5165
内容数
99
聆思科技官方专栏,专注AIOT芯片,持续分享有趣的解决方案。商务合作微信:listenai-csk 技术交流QQ群:825206462
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息