颜色的获取需要用到DFRobot 颜色传感器- 1738-1035-ND,其数据手册如下
根据手册,其引脚定义如下

推荐的接线方案如下

ESP32-S3 Reverse TFT Feather开发板引脚定义如下

结合颜色传感器文档的推荐接线方式,最终接线方式如下
VCC -> 5V
GND -> GND
S0 -> D5
S1 -> D6
S2 -> D9
S3 -> D10
OUT -> D12
其中LED引脚可以选择不接,如果接了高电平颜色传感器上的LED灯就会打开,这对于不会自己发光的物体的颜色识别是有效的
在程序中定义引脚
# ---------- 引脚映射 ---------- PIN_S0 = board.D5 PIN_S1 = board.D6 PIN_S2 = board.D9 PIN_S3 = board.D10 PIN_OUT = board.D12
设置引脚为输出模式
# 控制引脚设为输出 s0 = digitalio.DigitalInOut(PIN_S0); s0.switch_to_output(value=False) s1 = digitalio.DigitalInOut(PIN_S1); s1.switch_to_output(value=False) s2 = digitalio.DigitalInOut(PIN_S2); s2.switch_to_output(value=False) s3 = digitalio.DigitalInOut(PIN_S3); s3.switch_to_output(value=False)
设置按键
# 按键:D1高有效(按下为True),D2高有效用于切换输出模式 BTN_SAMPLE = digitalio.DigitalInOut(board.D1) BTN_SAMPLE.switch_to_input(pull=digitalio.Pull.DOWN) BTN_MODE = digitalio.DigitalInOut(board.D2) BTN_MODE.switch_to_input(pull=digitalio.Pull.DOWN)
设置频率计数器用于采样
# 频率计数器(上升沿) counter = countio.Counter(PIN_OUT, edge=countio.Edge.RISE)
TFT屏幕初始化显示,需要注意的是,字符显示需要用到adafruit_display_text,其下载链接为GitHub - adafruit/Adafruit_CircuitPython_Display_Text: Library to display text using displayio
# ---------- TFT 显示初始化 ---------- display = board.DISPLAY splash = displayio.Group() display.root_group = splash # 画面文字 title = label.Label(terminalio.FONT, text="TCS3200 Color Read", color=0xFFFF00) title.anchor_point = (0.0, 0.0) title.anchored_position = (4, 4) splash.append(title) text_line = label.Label(terminalio.FONT, text="", color=0xFFFFFF) text_line.anchor_point = (0.0, 0.0) text_line.anchored_position = (4, 24) splash.append(text_line) mode_line = label.Label(terminalio.FONT, text="Mode: Print+Display", color=0x00FF00) mode_line.anchor_point = (0.0, 0.0) mode_line.anchored_position = (4, 44) splash.append(mode_line) rgb_line = label.Label(terminalio.FONT, text="", color=0xFFFFFF) rgb_line.anchor_point = (0.0, 0.0) rgb_line.anchored_position = (4, 64) splash.append(rgb_line) out_text_color = 0xFFFFFF
将颜色传感器文档中提供的Arduino代码转换为CircuitPython代码,编写以下底层控制代码
# ---------- 低层控制函数 ----------
def set_scaling_20pct():
"""S0=H, S1=L -> 输出频率按20%比例"""
s0.value = True
s1.value = False
def select_filter(name: str):
"""设置S2/S3选择滤波器: 'R','G','B','C'"""
if name == 'R': # S2=L, S3=L
s2.value = False; s3.value = False
elif name == 'G': # S2=H, S3=H
s2.value = True; s3.value = True
elif name == 'B': # S2=L, S3=H
s2.value = False; s3.value = True
elif name == 'C': # S2=H, S3=L
s2.value = True; s3.value = False
else:
raise ValueError("Unknown filter")
def read_frequency(gate_ms=50):
"""在 gate_ms 毫秒内计数脉冲,返回 Hz"""
counter.reset()
time.sleep(gate_ms / 1000.0)
counts = counter.count
# 避免极端情形的整形溢出,简单转换为Hz
hz = counts * (1000.0 / gate_ms)
return hz
def sample_rgb():
"""依次测R/G/B三通道频率,返回三元组(Hz)"""
set_scaling_20pct()
select_filter('R')
fr = read_frequency()
select_filter('G')
fg = read_frequency()
select_filter('B')
fb = read_frequency()
return fr, fg, fb
def normalize_rgb(fr, fg, fb):
"""将频率简单归一化到 0..255(以最大值为参考),得到近似RGB"""
# 频率越高 -> 光强越大,这里用“值/最大值”做归一化
m = max(fr, fg, fb, 1.0)
r = int(min(255, max(0, (fr / m) * 255)))
g = int(min(255, max(0, (fg / m) * 255)))
b = int(min(255, max(0, (fb / m) * 255)))
return r, g, b在主循环中,按键按下识别颜色,并将颜色的RGB值显示在TFT屏幕上,字体的颜色跟随RGB值而改变
# ---------- 主循环 ----------
print_mode = True # True=串口打印 + TFT 显示;False=仅TFT显示
# 初始提示
text_line.text = "Press D1 to sample"
rgb_line.text = "R/G/B Hz & RGB shown here"
last_btn1 = False
last_btn2 = False
while True:
# 模式切换(D2 上升沿)
now_btn2 = BTN_MODE.value
if now_btn2 and not last_btn2:
print_mode = not print_mode
mode_line.text = "Mode: Print+Display" if print_mode else "Mode: Display only"
last_btn2 = now_btn2
# 采样(D1 上升沿)
now_btn1 = BTN_SAMPLE.value
if now_btn1 and not last_btn1:
fr, fg, fb = sample_rgb()
r, g, b = normalize_rgb(fr, fg, fb)
# 串口输出
if print_mode:
print("==== TCS3200 Sample ====")
print("Hz : R={:.1f} G={:.1f} B={:.1f}".format(fr, fg, fb))
print("RGB : ({:3d}, {:3d}, {:3d})".format(r, g, b))
# TFT 显示
text_line.text = "Hz: R={:.1f} G={:.1f} B={:.1f}".format(fr, fg, fb)
rgb_line.text = "RGB: ({:3d}, {:3d}, {:3d})".format(r, g, b)
# 以近似RGB改变文本颜色,直观看到颜色
out_text_color = (r << 16) | (g << 8) | b
rgb_line.color = out_text_color
last_btn1 = now_btn1
time.sleep(0.02) # 简单消抖与主循环节流在画图软件里绘制一个色块图片

执行代码得到串口输出内容如下

实现效果如下

程序代码如下
接着尝试让板载的RGB灯跟随获取的颜色变化,这需要用到neopixel库,下载链接为Releases · adafruit/Adafruit_CircuitPython_NeoPixel
在任务1的基础上加上NeoPixel根据读取到的RGB值更改颜色的函数
def update_outputs(fr, fg, fb, r, g, b, print_mode=True):
"""更新串口/TFT/NeoPixel显示"""
if print_mode:
print("==== Sample ====")
print("Hz : R={:.1f} G={:.1f} B={:.1f}".format(fr, fg, fb))
print("RGB : ({:3d}, {:3d}, {:3d})".format(r, g, b))
hz_line.text = "Hz: R={:.1f} G={:.1f} B={:.1f}".format(fr, fg, fb)
rgb_line.text = "RGB: ({:3d},{:3d},{:3d})".format(r, g, b)
rgb_line.color = (r << 16) | (g << 8) | b
swatch_palette[0] = (r << 16) | (g << 8) | b
pixel.fill((r, g, b))主循环内容如下
print_mode = True last_btn1 = False last_btn2 = False while True: # D2:模式切换(上升沿) now_btn2 = BTN_MODE.value if now_btn2 and not last_btn2: print_mode = not print_mode mode_line.text = "Mode: Print+Display" if print_mode else "Mode: Display only" last_btn2 = now_btn2 # D1:采样一次(上升沿) now_btn1 = BTN_SAMPLE.value if now_btn1 and not last_btn1: fr, fg, fb = sample_rgb_once() r, g, b = normalize_rgb(fr, fg, fb) update_outputs(fr, fg, fb, r, g, b, print_mode=print_mode) last_btn1 = now_btn1 time.sleep(0.02) # 简单消抖与节流
执行代码得到串口输出内容如下

实现效果如下

程序代码如下
我要赚赏金
