项目背景
功能介绍
任务描述
- 可识别至少五种颜色
- 可在LCD上显示基本信息如当前识别颜色
- 可在LCD上用色块显示识别的颜色并大致接近
硬件介绍
十二指神探引脚接口
颜色传感器
LTR-381RGB-01传感器内部集成了环境光传感器 (ALS) 和颜色传感器 (CS) ,可将光线(红、绿、蓝和红外)强度转换为数字输出信号。
设计思路
主要困难
此小节主要分析功能需求,实现该项目会面临的困难。
从任务描述中可以看出,实现该任务有两个核心功能:
- 获取颜色数据,所以需求是确定通信协议,读取传感器数据。
- LCD展示颜色,所以需求是确定通信协议,驱动LCD,绘制颜色文本信息和颜色色块。
解决思路
此小节针对面临的困难,提出解决方案(拟使用的传感器及通信协议)。
核心功能一
主要使用传感器:接近传感器、颜色传感器(LTR-381RGB-01)。
打开传感器扩展板的原理图,查阅颜色传感器与带屏12指神探的连接图。
可以看到,颜色传感器的通信方式是IIC,其中I2C0_SDA连接到IO20,I2C0_SCL连接到IO21。
在micropython中,类machine.I2C用于配置iic外设连接引脚,故实例化该类,使用类提供的方法编写颜色传感器的驱动。
- 基础功能
阅读颜色传感器数据手册的Principle of Operation章节,其支持两种读协议和两种写协议,故使用类库提供的I2C.writeto、I2C.writeto_mem、I2C.readfrom方法来驱动。
- 配置传感器
阅读Register Set章节,首先配置传感器功能,设置传感器内部寄存器的值。这里设置3个寄存器:MAIN_CTRL Register、ALS_CS_MEAS_RATE Register和ALS_CS_GAIN Register,分别用于使能传感器,测量分辨率、测量速率,增益。
- 获取颜色
其次在获取颜色测量值时,需要分别读取R、G、B数据寄存器。
- 白平衡校准
根据实际的光照环境,将白色光置于传感器上方,使其当前RGB三个通道的ADC值除以255得到3个比例因子,从而使得任意颜色的RGB值按比例因子缩放到0-255区间内。为了方便起见,会将比例因子存入文件,放到设备中,以便下次运行时直接读取,避免相同光环境下重复校准。
除此之外,还需配置重置功能,将缩放因子置为1(即不缩放),以凸显白平衡校准的有效性。
白平衡校准和重置功能通过按键触发。
核心功能二
驱动屏幕,例程已经写好st7789的驱动程序,不做赘述。
但仍需实现绘制颜色文本信息和颜色色块的功能。这两个功能d1实现,修改例程中'display.text()'和'display.fll()'这两个方法即可。
- 绘制颜色文本信息
拟展示当前校准比例因子,传感器ADC实测值,颜色rgb值。
- 绘制颜色色块
ST7789使用RGB565编码来表示颜色,在RGB565编码中:
- 红色占 5 位,最大值为
0xF800
(十六进制)。 - 绿色占 6 位,最大值为
0x07E0
(十六进制)。 - 蓝色占 5 位,最大值为
0x001F
(十六进制)。
- 红色占 5 位,最大值为
所以需要将范围在0-255的RGB编码分别转换为RGB565编码,再显示颜色色块。
软件流程图
此小节主要描述解决方案的软件实现,提出实现项目功能的技术路线。
功能展示
核心代码片段及说明
配置传感器
def __init__(self):
...
self._i2cwrite(_ALS_CS_MEAS_RATE, 0x22) # default ALS/CS Resolution: 18 Bit, Conversion time = 100ms, ALS/CS Measurement Rate: 100ms
self._i2cwrite(_ALS_CS_GAIN, 0x01) # ALS/CS Gain Range, Gain Range: 3 (default)
self._i2cwrite(_MAIN_CTRL, 0x06) # 0x06 ALS active, CS mode
...
获取颜色ADC值
...
def red(self):
Rlsb = self._i2cread(_DATA_RED_0)
Rnorm = self._i2cread(_DATA_RED_1)
Rmsb = self._i2cread(_DATA_RED_2)
return (Rmsb << 16) | (Rnorm << 8) | Rlsb
def blue(self):
Blsb = self._i2cread(_DATA_BLUE_0)
Bnorm = self._i2cread(_DATA_BLUE_1)
Bmsb = self._i2cread(_DATA_BLUE_2)
return (Bmsb << 16) | (Bnorm << 8) | Blsb
def green(self):
Glsb = self._i2cread(_DATA_GREEN_0)
Gnorm = self._i2cread(_DATA_GREEN_1)
Gmsb = self._i2cread(_DATA_GREEN_2)
return (Gmsb << 16) | (Gnorm << 8) | Glsb
...
白平衡校准及重置
if buttonValueS == 0: # 开始白平衡校准
print("start white balance calibration...")
time.sleep_ms(5)
r = sensor.red()
time.sleep_ms(5)
g = sensor.green()
time.sleep_ms(5)
b = sensor.blue()
sensor.R_factor = 255 / r
sensor.G_factor = 255 / g
sensor.B_factor = 255 / b
sensor.write_file(sensor.R_factor, sensor.G_factor, sensor.B_factor)
print("R_factor = {}, G_factor = {}, B_factor = {}".format(sensor.R_factor, sensor.G_factor, sensor.B_factor))
display.text(font1, "Calibrating", 10, 160)
elif buttonValueM == 0: # 重置
sensor.R_factor = 1.00
sensor.G_factor = 1.00
sensor.B_factor = 1.00
display.text(font1, "Restore", 10, 160)
读写颜色校准配置文件
...
def write_file(self, *factors):
combined_floats = ','.join(map(str, factors))
with open('color_factor.txt', 'w') as f:
f.write(combined_floats)
def _read_file(self):
try:
with open('color_factor.txt', 'r') as file:
data_read = file.read()
print("loading...success")
return list(map(float, data_read.split(',')))
except OSError:
print("loading...fail")
return (1.00, 1.00, 1.00)
...
将标准RGB编码转换为RGB565编码
def convert_rgb565(red, green, blue):
red = int(red / 255 * _ST7789_R)
green = int(green / 255 * _ST7789_G)
blue = int(blue / 255 * _ST7789_B)
red = max(0, min(red, _ST7789_R))
green = max(0, min(green, _ST7789_G))
blue = max(0, min(blue, _ST7789_B))
res_rgb565 = (red << 11) + (green << 5) + blue
return res_rgb565
在LCD上展示颜色文本信息和色块
display.text(font2, "#%02X%02X%02X" % (r, g, b), 10, 200)
display.fill_rect(150, 180, 50, 50, display_sensor_color)
实现效果
OLED的显示布局效果如下图所示。
屏幕中显示了以下关键信息
- 电子森林的网址
- RGB各个颜色分量的经过白平衡校准后的缩放比例
- 颜色传感器读取到的RGB各个颜色分量的ADC大小
- 十六进制的颜色表示
- 当前识别颜色的可视化正方形显示色块
共实现了10种颜色的识别,具体测试效果可观看演示视频。
总结
本项目依托12指神探和传感器扩展板平台,完成白平衡校准功能及颜色识别功能。在此过程中阅读传感器数据手册和平台驱动代码,学习白平衡校准原理和颜色传感器的驱动方法,最终顺利完成任务。