本次活动最主要的一个任务就是对TCS3200的驱动,做任务的小伙伴们要注意,CircuitPython并没有对TCS3200传感器的直接驱动的固件,有能力的喜欢探索的小伙伴可以尝试mpy或者arduino的方式进行开发,实际主控是ESP32-S3,可能大家都很熟悉了。
言归正传,我们对TCS3200进行一下学习,我们通过原理图查看可以了解很多基本信息: 

led = digitalio.DigitalInOut(board.D12) led.direction = digitalio.Direction.OUTPUT led.value = True s0_pin = digitalio.DigitalInOut(board.D5) s1_pin = digitalio.DigitalInOut(board.D6) s2_pin = digitalio.DigitalInOut(board.D9) s3_pin = digitalio.DigitalInOut(board.D10)
这里我们选择的数字输出的引脚,同时配置LED打开,具体引脚可参考如下:

对于TCS3200来说还要一个输出引脚,这里我们使用的是D11进行输入采集:
out_pin = digitalio.DigitalInOut(board.D11)接下来就是TCS3200的驱动配置函数了,这里我们单独写了一个py:
import time import digitalio import board class TCS3200: def __init__(self, s0, s1, s2, s3, out_pin): # 初始化TCS3200的控制引脚 self.s0 = s0 self.s1 = s1 self.s2 = s2 self.s3 = s3 self.out = out_pin # 设置引脚方向 self.s0.direction = digitalio.Direction.OUTPUT self.s1.direction = digitalio.Direction.OUTPUT self.s2.direction = digitalio.Direction.OUTPUT self.s3.direction = digitalio.Direction.OUTPUT self.out.direction = digitalio.Direction.INPUT # 设定频率选择为最大频率 self.set_frequency(2) def set_frequency(self, freq_mode): """ 设置传感器的频率控制(S0和S1)。 0: 2%频率 1: 20%频率 2: 100%频率 """ if freq_mode == 0: self.s0.value = False self.s1.value = False elif freq_mode == 1: self.s0.value = False self.s1.value = True elif freq_mode == 2: self.s0.value = True self.s1.value = False else: self.s0.value = True self.s1.value = True def set_color_channel(self, color): """ 设置S2和S3引脚来选择颜色通道 'R': Red 'G': Green 'B': Blue """ if color == 'R': self.s2.value = False self.s3.value = False elif color == 'G': self.s2.value = True self.s3.value = True elif color == 'B': self.s2.value = False self.s3.value = True这里基本上只有S0-S3的配置控制,实际上还应该包括PWM的采集,不过并没有找到对PWM频率采集的支持,一般我们通过pulseio可以获取的,不过这个板子用pulseio输出可以,输入采集没有成功,所以我们使用了一个笨方法进行采集:
# 配置采样次数 NUM_CYCLES = 10 # 测多少个周期 def measure_frequency(): timestamps = [] last_state = out_pin.value while len(timestamps) < NUM_CYCLES: current_state = out_pin.value if current_state != last_state: # 发生边缘变化 timestamps.append(time.monotonic_ns()) last_state = current_state # 计算周期 periods = [] for i in range(2, len(timestamps), 2): period_ns = timestamps[i] - timestamps[i - 2] # 一个完整周期(两个边缘) periods.append(period_ns) avg_period_ns = sum(periods) / len(periods) frequency = 1_000_000_000 / avg_period_ns # 转换成 Hz return frequency
大家也可以进一步优化一下,我们配置一个通道后调用这个函数采集一下频率就可以获得原始数据,我们看一下几种颜色的频率输出(这里都是以纸上的颜色作为基本色进行采集)。
白色:

蓝色:







黑色:

我们可以看到数值上还是有明显的差异的,不过这里只是基本的输出,实际输出每个人可能都不一样,比如LED不开启的时候,受环境光的影响导致技术处差异非常大,我们建议开启LED,还要把握好距离,这里的所有注意事项都因为实际影响的参数是单通道的进光量。
接下来我们还要进行一下频率与RGB值的转化,这里就需要注意了,实现开始之前,如果能固定环境光和发光等因素,可以通过采集白色作为各通道最高值(实际上白纸的白色并不是纯正的白色,并且表面也不光滑,仅作为参考),进行白平衡调整,我们目前来看采集的值只能说是趋势是一定的。
我们大致将18000作为三原色256对应的值,进行算法的转化:
RGB = frequency/(18000/256) if int(RGB) >= 255: RGB = 255
效果:黄色主要是有红和绿组成,不过实际环境中还是存在蓝色分量的

接下来可以通过对板载的RGB灯进行控制,使其输出颜色和采集颜色保持一致,这里用的主要是NeoPixel库,这个库还是非常常见使用的,我们直接配置使用个就可以了:
import neopixel pixel = neopixel.NeoPixel(board.NEOPIXEL, 1) pixel.brightness = 0.3 pixel.fill((r, g, b))
由于我们纸上画的都是比较混合,我们使用屏幕进行一下反馈,注意关闭LED辅助,屏幕本省光强就比较大:



我要赚赏金
