2024年寒假练 - 用搭配带屏12指神探的传感器扩展板 RGB颜色识别与校验
该项目使用了12指神探带传感器扩展板,实现了RGB颜色识别与校验的设计,它的主要功能为:识别颜色,校验后将颜色显示到屏幕上。
标签
2024寒假在家一起练
ltr381颜色传感器
pico2040
st7789屏幕
henry
更新2024-03-29
88

项目介绍

项目采用rp2040外接传感器来完成色彩识别并显示,可至少识别五种颜色以上。

板卡支持micropython 、c sdk,也支持circuitpython等很多种开发语言,本次使用的是开发环境c sdk,ide使用vscode。

环境搭建在官方有非常详细的指导,包括vscode下如何使用插件,编译以及各种demo,给开发带来非常多的便利。

官方介绍:https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

设计思路

项目主要用到的就是屏幕与rgb颜色传感器,另外没有调试功能,需要将串口打印功能打开,可以使用usb cdc的功能,将usb模拟为串口设备。

一、屏幕部分跑默认例程pio/st7789_lcd/st7789_lcd.c展示pico的图片logo

二、串口打印功能,根据demo:hello_world/usb/hello_usb.c,通过它开启开发板串口打印的功能,方便调试

三、i2c通信,通过hardware_i2c,硬件i2c,完成与rgb颜色传感器的调试。

将以上三个功能分别跑通后就可以进入最终的设计,将rgb传感器的颜色读出来,通过一系列的计算,将计算的结果转换为rgb565的屏幕色深,再通过屏幕全屏刷新展示出来。

办卡的演示在视频的33s处

屏幕

屏幕采用st7789这个经典芯片,在pico的c sdk中有他的例程,使用的是PIO(可编程IO)来驱动,具体位置在

pio/st7789_lcd/st7789_lcd.c

我们现将这个程序跑起来(例程可移植性很好,只需要改一点点内容就可以跑起来)

//修改Pin脚
#define PIN_DIN 3
#define PIN_CLK 2
#define PIN_CS 4
#define PIN_DC 1
#define PIN_RESET 0
// #define PIN_BL 5

//注释调不需要的引脚操作
gpio_init(PIN_CS);
gpio_init(PIN_DC);
gpio_init(PIN_RESET);
// gpio_init(PIN_BL);
gpio_set_dir(PIN_CS, GPIO_OUT);
gpio_set_dir(PIN_DC, GPIO_OUT);
gpio_set_dir(PIN_RESET, GPIO_OUT);
// gpio_set_dir(PIN_BL, GPIO_OUT);

gpio_put(PIN_CS, 1);
gpio_put(PIN_RESET, 1);
lcd_init(pio, sm, st7789_init_seq);
// gpio_put(PIN_BL, 1);

然后编译并将uf2放到板卡中,就驱动起来了。效果如下(旋转的rp2040 logo):

还记得官方在这里文档的描述很有意思,说别人驱动屏幕只是简单的显示,他们的是旋转

串口

使用c sdk貌似没有调试功能,这时候串口打印就尤为重要了,我们可以通过芯片usb的cdc模拟一个usb串口设备以在屏幕上打印日志。

具体可以参考hello_world/usb/hello_usb.c这个项目,非常经典的在串口打印Hello, world!,具体实现没有深究。


RGB颜色识别

驱动ltr381

颜色识别用的是ltr381这个传感器,它采用i2c接口,识别rgb颜色并存放在rgb三个寄存器中。参考了一个c++的lib:https://github.com/Rombutan/ltr381_pico_lib.git

也封装了获取r g b寄存器的函数(以red为例):

uint32_t ltr381_red() {
   uint32_t red = 0;

   uint8_t addr, buf;

   addr = 0x10;
   i2c_write_blocking(i2c_default, REG_DEVID, &addr, 1, true);
   i2c_read_blocking(i2c_default, REG_DEVID, &buf, 1, false);
   red = buf;

   addr = 0x11;
   i2c_write_blocking(i2c_default, REG_DEVID, &addr, 1, true);
   i2c_read_blocking(i2c_default, REG_DEVID, &buf, 1, false);
   red |= buf << 8;

   addr = 0x12;
   i2c_write_blocking(i2c_default, REG_DEVID, &addr, 1, true);
   i2c_read_blocking(i2c_default, REG_DEVID, &buf, 1, false);
   red |= buf << 16;

   return red;
}

颜色校准

实际上色彩识别是有很多门道的,比如光照强度,色温等等都会影响颜色,我们要做的只是忽略其他因素,识别颜色。

简单了解原理后就开始手动校准。

  1. 采样RGB颜色在一开始就有很大差异,g颜色值高很多,b又很低,首先将他们统一到一个尺度(屋内环境得到r近似120,让gb等比例放大到r)
    r = ltr381_red();
    g = ltr381_green() * 0.74;
    b = ltr381_blue() * 1.8;
  2. 亮度过高影响识别效果(设置采样颜色的上限与下限)
    r = fmin(120, r);
    g = fmin(120, g);
    b = fmin(120, b);

    if(r < 60 && g < 60 && b < 60) {
       printf("ingore\n");
       continue;
    }
  3. 将获取到的最亮的颜色作为基准,把其他颜色按照比例缩小,并按照rgb565格式的色深进行扩大。
    if ((r > g) && (r > b)) {
       rate = 31.0 / r;
       r = 31;
       g = g * rate * 2;
       b = b * rate;
    } else if ((g > r) && (g > b)) {
       rate = 31.0 / g;
       r = r * rate;
       g = 63;
       b = b * rate;
    } else {
       rate = 31.0 / b;
       r = r * rate;
       g = g * rate * 2;
       b = 31;
    }

    r = fmin(r, 31);
    g = fmin(g, 63);
    b = fmin(b, 31);

以上的校准纯属原创哈哈哈哈,肯定有更好的算法或识别模式,但在找这个芯片的资料的时候只能找到用来肤色识别的算法,无奈只能自己尝试,但识别效果感觉也还可以~

项目编译

采用vscode,与其他那些ide不同,c sdk采用cmake进行项目构建(虽然cmake比单纯的makefile负责了亿点点,但构建的方式也还是比采用其他自家ide那些更浮在表面,包括编译依赖等等),对于想了解构建过程还是很友好的。

因为没有其他ide的一键导入库,所以这里重点也讲一下编译的配置。

项目是基于hello_world/usb二次开发,CMakeLists.txt代码如下:

if (TARGET tinyusb_device)
   add_executable(hello_usb)

   pico_generate_pio_header(hello_usb ${CMAKE_CURRENT_LIST_DIR}/st7789_lcd.pio)

   # pull in common dependencies
   target_link_libraries(hello_usb pico_stdlib hardware_interp hardware_pio hardware_i2c)

   target_sources(hello_usb PRIVATE
      hello_usb.c
   )

   # enable usb output, disable uart output
   pico_enable_stdio_usb(hello_usb 1)
   pico_enable_stdio_uart(hello_usb 0)

   # create map/bin/hex/uf2 file etc.
   pico_add_extra_outputs(hello_usb)

   # add url via pico_set_program_url
   example_auto_set_url(hello_usb)
elseif(PICO_ON_DEVICE)
   message(WARNING "not building hello_usb because TinyUSB submodule is not initialized in the SDK")
endif()

其中屏幕采用可编程IO,因此导入st7789_lcd.pio(大概就是配置pio的fifo实现数据输出)这里值得深入研究。


    # enable usb output, disable uart output
  pico_enable_stdio_usb(hello_usb 1)
  pico_enable_stdio_uart(hello_usb 0)

短短两行就配置好了usb cdc 用于串口打印,非常便捷。

最后就是使用vscode cmake插件编译啦。

还有一些其他的库pico_stdlib hardware_interp hardware_pio hardware_i2c


未来计划

rp2040真的是一个很经典的设计,大量diy玩家用它作各种脑洞打开的创意,这个带屏的rp2040很精致,可拓展的功能也很多,很开心得到这样一块板卡,未来计划是将其中的各种传感器驱动,将信息显示到屏幕上,并研究pio相关知识,以及c sdk这个庞然大物却有很好用的构建方式。

附件下载
rgb.zip
hello_usb.uf2
可直接拖拽到板卡中执行~
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号