基于带屏12指神探与传感器扩展板制作的简易颜色识别器
1 项目简介
本项目是参加2024寒假在家一起练的项目。本次项目比较开放,可以完成多个基于传感器的设计。总各个方面因素,我决定选用MicroPython语言,通过编写颜色传感器的驱动,完成简单颜色采样,将数据进行整理处理之后,将RGB数据绘制至LCD屏幕上面。
本项目主要完成以下功能:
a)将传感器获取到的颜色RGB数值,显示在TFT LCD上。
b)根据颜色数值,区分颜色的名称,并将颜色名称显示显示在LCD上。
c)根据RGB数值,绘制与传感器获取到的颜色相同的色块。
2 整体设计思路
整体上根据设计要求,需要完成颜色识别器的功能。其中需要使用带显示屏的基于RP2040的多功能调试平台作为数据处理单元,使用传感器扩展板中的LT381环境光传感器作为传感单元。完成一个简易颜色识别器项目。下图为最终实现的使用效果。
图1
2.1 硬件部分简介
根据寒假一起练项目此项目的硬件,可以使用以下硬件平台来完成。主处理器部分使用带屏版12指神探板卡方便信息观察,还配备了白色外壳。
作为12指神探的传感器扩展板,接口完全适配,正确方向插入后即可使用。扩展板上面我们主要需要颜色传感器。型号为LTR-381。
图2
2.2 软件部分简介
通过分析项目的要求,本项目需要完成一个颜色识别器的功能。综合项目板卡的功能和硬件的能力,初步制定了软件功能模块如下:
a)读取传感器内部RGB三个传感器的数值。
b)通过数值运算将其进行数值修正,输出为0-255的RGB数值。
c)组合三位数值,输出至LCD对应位置显示三个数值。
d)通过判断数值范围,输出颜色名称。
e)根据RGB数值,绘制近似的色块。
3. 软件分模块详细介绍
软件部分主要使用MicroPython 语言进行编写。参考了带屏版12指神探内置的MicroPython 操作系统,使用Python语言,基于MicroPython驱动了传感器上的色彩传感器设备进行读取,并完成数据的处理。
3.1 软件设计简述
根据项目设计需求,软件需要设计以下功能模块。首先需要采样LTR-381色彩传感器,需要通过运算对传感器反馈的数据进行归一化处理。再完成数据发送到LCD屏幕的功能。
3.2 软件流程框图
图3
3.3 核心软件分模块分析
根据程序流程图,这里针对项目的软件分模块截图介绍如下
3.3.1 导入各个模块部分以及模块介绍
import test.st7789 as st7789
from test.fonts import vga2_8x8 as font1
from test.fonts import vga1_16x32 as font2
from machine import Pin, SPI, ADC,PWM ,I2C
import time, math,array
from utime import sleep_ms
from test.ltr381 import LTR381
这部分使用python导入了TFT LCD驱动,此部分驱动使用带屏版12指神探随机附带操作系统中st7789的micropython驱动.同时使用了导入了出厂系统内自带的8x8 16x32点阵字库。作为显示的字库使用。下半部分呢程序引入了必要的系统及定时器、数学函数库、延时函数库等。最下一行引入了LTR381的驱动程序。下面会详细介绍LTR381驱动函数库内的各部分的作用。
3.3.2 传感器驱动部分介绍
import utime
import math
from machine import Pin, I2C
# ========= Start LTR381 RGB IR sensor driver =============
ADDR = (0X53)
LTR381_MAIN_CTRL = (0x00) # Main control register
LTR381_MEAS_RATE = (0x04) # Resolution and data rate
LTR381_GAIN = (0x05) # ALS and UVS gain range
LTR381_PART_ID = (0x06) # Part id/revision register
LTR381_MAIN_STATUS = (0x07) # Main status register
LTR381_IRDATA = (0x0A) # ALS data lowest byte, 3 byte
LTR381_GREENDATA = (0x0D) # GREEN data lowest byte, 3 byte
LTR381_REDDATA = (0x10) # RED data lowest byte, 3 byte
LTR381_BLUEDATA = (0x13) # BLUE data lowest byte, 3 byte
LTR381_INT_CFG = (0x19) # Interrupt configuration
LTR381_INT_PST = (0x1A) # Interrupt persistance config
LTR381_THRESH_UP = (0x21) # Upper threshold, low byte, 3 byte
LTR381_THRESH_LOW = (0x24) # Lower threshold, low byte, 3 byte
此部分引入了系统定时库、I2C库 ,以及定义了LTR-381传感器、I2C基地址,以及IC内各部分常用的寄存器。
#RGB IR measurement resolution, Gain setting, measurement rate
RESOLUTION_20BIT_utime400MS = (0X00)
RESOLUTION_19BIT_utime200MS = (0X10)
RESOLUTION_18BIT_utime100MS = (0X20)#default
RESOLUTION_17BIT_utime50MS = (0x3)
RESOLUTION_16BIT_utime25MS = (0x40)
RESOLUTION_13BIT_utime12_5MS = (0x50)
RATE_25MS = (0x0)
RATE_50MS = (0x1)
RATE_100MS = (0x2)# default
RATE_200MS = (0x3)
RATE_500MS = (0x4)
RATE_1000MS = (0x5)
RATE_2000MS = (0x6)
# measurement Gain Range.
GAIN_1 = (0x0)
GAIN_3 = (0x1)# default
GAIN_6 = (0x2)
GAIN_9 = (0x3)
GAIN_18 = (0x4)
此部分,根据对应的寄存器以及预设的取值,定义了采样速度、采样精度、ADC增益等三部分的预定义数值。这样写代码时候,可以使用这部分的预定义的字串代表对应的参数。
class LTR381:
def __init__(self, address=ADDR):
self.i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=100000)
self.address = address
self.Write_Byte(LTR381_MAIN_CTRL, 0x06) # UVS in Active Mode
self.Write_Byte(LTR381_MEAS_RATE, RESOLUTION_18BIT_utime100MS | RATE_100MS)
self.Write_Byte(LTR381_GAIN, GAIN_3) # Gain Range=3.
def Read_Byte(self, cmd):
rdate = self.i2c.readfrom_mem(int(self.address), int(cmd), 1)
return rdate[0]
def Write_Byte(self, cmd, val):
self.i2c.writeto_mem(int(self.address), int(cmd), bytes([int(val)]))
这部分定义了基本的I2C寄存器读写协议,以及定义了传感器基础初始化寄存器,并设置基础参数。本次采用了18bit 采样精度,以及 100ms 采样速度。
def REDS(self):
Data1 = self.Read_Byte(LTR381_REDDATA)
Data2 = self.Read_Byte(LTR381_REDDATA + 1)
Data3 = self.Read_Byte(LTR381_REDDATA + 2)
ret = (Data3 << 16)| (Data2 << 8) | Data1
return ret
此处为三个读取彩色单元的寄存器,可以从LT381获取三个颜色的数值。这里代码展示了RED单色寄存器读取过程。其余两个颜色可以使用相类似的代码实现。
至此驱动层代码介绍完毕,通过直接调用LTR381的驱动可以很方便的获取RGB三个颜色的参数。
3.3. 数值计算、颜色分类部分
def CalcValue(value,minval,maxval):
if (value < minval):
value = minval
if (value >maxval):
value = maxval
calvalue = int( (value - minval) * 255 / (maxval - minval) )
return calvalue
def DetecColor(Rval,Gval,Bval):
if ((Rval>130)and(Gval<50)and(Bval<10) ):
return "Red "
if ((Rval<60)and(Gval>150)and(Bval<60) ):
return "Green "
if ((Rval<60)and(Gval<40)and(Bval>150) ):
return "Blue "
if ((Rval>170)and(Gval>170)and(Bval<60) ):
return "Yellow "
if ((Rval<60)and(Gval>170)and(Bval>170) ):
return "Cyan "
if ((Rval>150)and(Gval<100)and(Bval>180) ):
return "Magenta"
if ((Rval>200)and(Gval>200)and(Bval>200) ):
return "White "
if ((Rval<30)and(Gval<30)and(Bval<30) ):
return "Black "
else:
return " "
这部分为自定义的两个函数:
CalcValue函数主要用来计算输入的传感器数值。首先,对输入进来的数值去掉最小值,并将最大值纳入计算,最后将其归一化至0-255范围。这样做的原因主要是因为传感器敏感程度与人眼的敏感程度不尽相同。这样输出的是指的最大值、最小值以及感应程度也未必相同。此部分进行完最大值最小值转换以及归一化到0-255输出。
DetectColor函数主要完成根据颜色数值输出颜色名称的功能。此部分可以根据颜色成都将颜色分类为8个类别,并在后一步骤的最下面一行显示颜色名称。
3.3.4 LCD字符绘制、色块绘制
sensor = LTR381()
st7789_res = 0
st7789_dc = 1
disp_width = 240
disp_height = 240
CENTER_Y = int(disp_width/2)
CENTER_X = int(disp_height/2)
spi_sck=Pin(2)
spi_tx=Pin(3)
spi0=SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
display = st7789.ST7789(spi0, disp_width, disp_width,
reset=machine.Pin(st7789_res, machine.Pin.OUT),
dc=machine.Pin(st7789_dc, machine.Pin.OUT),
xstart=0, ystart=0, rotation=0)
display.fill(st7789.BLACK)
display.text(font2, "Color Meter 1.0", 0, 0)
display.text(font2, "by:tinySDR ", 0, 30)
display.text(font2, "EETREE Feb.2024", 0, 200)
display.text(font2, "R: ", 0, 70)
display.text(font2, "G: ", 0, 100)
display.text(font2, "B: ", 0, 130)
此部分完成RGB色彩数据的初始化、显示、刷新等工作。这部分是初始化,完成屏幕初始字符显示。
while True:
REDS = sensor.REDS()
GREENS = sensor.GREENS()
BLUES = sensor.BLUES()
REDH= CalcValue(REDS,60,300)
GREENH = CalcValue(GREENS,160,550)
BLUEH = CalcValue(BLUES,90,350)
display.text(font2, str(REDS)+" ", 48, 70)
display.text(font2, str(GREENS)+" ", 48, 100)
display.text(font2, str(BLUES)+" ", 48, 130)
display.fill_rect(160, 70, 80,120, st7789.color565(REDH,GREENH,BLUEH))
display.text(font2, "C: "+ DetecColor(REDH,GREENH,BLUEH), 0, 160)
这部分程序为主loop循环,每次循环先读取传感器数值,将其根据测量到的最小值、最大值进行归一化运算,将0-255范围的数值放入REDH\GREENH\BLUEH变量组内。下部分为会显示颜色原始数值、颜色名称、绘制色块的工作。至此完成整个项目所要求的采集与显示功能。
4 遇到的问题与后续改进点分析
通过实际测试,这段程序能够完成一个简易的颜色识别器的功能。其中需要使用带显示屏的基于RP2040的多功能调试平台作为数据处理单元,使用传感器扩展板中的LT381环境光传感器作为传感单元。在整个项目设计过程中,主要根据LTR-390传感器的驱动,移植了LTR-381的驱动程序,这部分也是占用比较多精力的地方。其他方面,针对采样的数据计算不够精确,也是一个缺陷。未来,对于嵌入式知识方面,还需要深入的去学习。
感谢硬禾学堂,希望能够再有机会参加下次的活动!