这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » Let'sdo2025年第3期—颜色拾取

共1条 1/1 1 跳转至

Let'sdo2025年第3期—颜色拾取

助工
2025-12-09 17:54:39     打赏

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

SEN0101_Web.pdf

根据手册,其引脚定义如下

image.png

推荐的接线方案如下

image.png

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

屏幕截图 2025-12-06 170056.png

结合颜色传感器文档的推荐接线方式,最终接线方式如下

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)  # 简单消抖与主循环节流

在画图软件里绘制一个色块图片

三颜色.png

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

屏幕截图 2025-12-06 175028.png

实现效果如下

7e7b78efce9c157ef38dab8b26c95179.gif

程序代码如下

task1.zip

接着尝试让板载的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)  # 简单消抖与节流

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

屏幕截图 2025-12-06 182612.png

实现效果如下

视频项目.gif

程序代码如下

task2.zip




关键词: 拾色播放器     颜色传感器     ESP32S3    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]