这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【Let'sdo第3期-拾色播放器DIY】活动-03-成果贴1

共1条 1/1 1 跳转至

【Let'sdo第3期-拾色播放器DIY】活动-03-成果贴1

专家
2025-12-06 13:06:34     打赏

  完成开发环境的搭建,下面开始第一个实验,具体详细步骤如下:  

首先是硬件的连接,开发板的硬件引脚带有芯片模块一面的图片如下所示:

开发板正面.png

带有显示屏幕一面的引脚图如下所示:

开发板反面.png

颜色传感器模块的硬件介绍如下:

颜色传感器的原理图.png

开发板和颜色传感器的连接为:

颜色传感器                开发板

VDD----------------    3.3V

GND----------------   GND

S0-------------------    D3

S1-------------------    D4

S2-------------------    D5

S3-------------------    D6

OUT-----------------    D9

连接效果如下所示:

微信图片_20251206125243_51_368.jpg

确认连接没有问题,特别注意电源的正负极要正确之后,完成硬件的连接,即可连接到电脑供电进行后续的程序开发。

由于程序中需要引用到库文件adafruit_display_text,因此需要首先准备好次库文件。

首先,需要官网下载官方的库,下载地址如下:

https://circuitpython.org/libraries

我下载的库是adafruit-circuitpython-bundle-10.x-mpy-20251004,

下载之后解压,找到里面lib文件夹下的adafruit_display_text文件夹,把这个这个文件夹复制到开发板在电脑上显示的盘符下的lib文件加下,效果如下:

3966044e-4fa0-4cb6-9ed3-9d0c325fd3aa.png

至此,完成程序中用到的库文件的安装。

然后,打开Mu编辑器,点击顶部的有向上箭头的“加载”按钮,打开了一个文件打开的对话框,找到开发板在电脑上对应的盘符,并打开,选中里面的“code.py”,并点击选择打开,可打开开发板的编程文件,里面有“Hello World”入门简单程序,删除此程序,然后把下面的程序复制到里面:

import time  

import board  

import digitalio  

import displayio  

import terminalio  

from adafruit_display_text import label  

import neopixel  

  

# -----------------------  

# TCS3200 传感器类  

# -----------------------  

class TCS3200:  

    def __init__(self, s0, s1, s2, s3, out_pin):  

        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.white_r = 1.0  

        self.white_g = 1.0  

        self.white_b = 1.0  

         

        # 颜色校正参数  

        self.color_threshold = 0.15  # 颜色阈值,低于此值的颜色分量将被设为0  

        self.calibration_mode = False  # 校准模式标志  

  

    def set_frequency(self, freq_mode):  

        if freq_mode == 0:  # 2%  

            self.s0.value = False  

            self.s1.value = False  

        elif freq_mode == 1:  # 20%  

            self.s0.value = False  

            self.s1.value = True  

        elif freq_mode == 2:  # 100%  

            self.s0.value = True  

            self.s1.value = False  

        else:  

            self.s0.value = True  

            self.s1.value = True  

  

    def set_color_channel(self, color):  

        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  

     

    def calibrate_white(self, out_pin):  

        """执行白平衡校准,获取白色表面的RGB频率值"""  

        text_label.text = "White balance calibration...\nPoint sensor at white surface"  

        display.refresh()  

        time.sleep(2)  

         

        # 测量白色表面的RGB频率  

        self.set_color_channel('R')  

        time.sleep(0.2)  

        self.white_r = measure_frequency(out_pin)  

         

        self.set_color_channel('G')  

        time.sleep(0.2)  

        self.white_g = measure_frequency(out_pin)  

         

        self.set_color_channel('B')  

        time.sleep(0.2)  

        self.white_b = measure_frequency(out_pin)  

         

        print(f"White balance calibration complete: R={self.white_r}, G={self.white_g}, B={self.white_b}")  

         

    def frequency_to_rgb(self, freq_r, freq_g, freq_b):  

        """将频率值转换为RGB(0-255)值"""  

        # 避免除以0  

        if self.white_r <= 0: self.white_r = 1  

        if self.white_g <= 0: self.white_g = 1  

        if self.white_b <= 0: self.white_b = 1  

         

        # 计算相对值并转换为0-255范围  

        r = min(255, int(255 * freq_r / self.white_r))  

        g = min(255, int(255 * freq_g / self.white_g))  

        b = min(255, int(255 * freq_b / self.white_b))  

         

        # 颜色校正:增强颜色饱和度,减少偏色  

        # 找出最大值  

        max_val = max(r, g, b)  

        if max_val > 0:  

            # 计算阈值,低于阈值的颜色分量设为0  

            threshold = max_val * self.color_threshold  

            if g < threshold: g = 0  

            if b < threshold: b = 0  

            if r < threshold: r = 0  

         

        return (r, g, b)  

     

    def adjust_color_threshold(self, delta):  

        """调整颜色阈值参数"""  

        self.color_threshold = max(0.05, min(0.5, self.color_threshold + delta))  

        print(f"Color threshold adjusted to: {self.color_threshold:.2f}")  

        return self.color_threshold  

  

  

# -----------------------  

# 频率测量  

# -----------------------  

NUM_CYCLES = 10  

  

def measure_frequency(out_pin):  

    timestamps = []  

    last = out_pin.value  

    while len(timestamps) < NUM_CYCLES:  

        current = out_pin.value  

        if current != last:  

            timestamps.append(time.monotonic_ns())  

            last = current  

  

    periods = []  

    for i in range(2, len(timestamps), 2):  

        period = timestamps[i] - timestamps[i-2]  

        periods.append(period)  

  

    avg_period = sum(periods) / len(periods)  

    return 1_000_000_000 / avg_period  

  

  

# -----------------------  

# TFT 显示设置  

# -----------------------  

display = board.DISPLAY  

splash = displayio.Group()  

display.root_group = splash  

  

text_label = label.Label(  

    font=terminalio.FONT,  

    text="Initializing...",  

    color=0xFFFFFF,  

    scale=1,  

    x=10,  

    y=30  

)  

splash.append(text_label)  

  

# 用于显示颜色的矩形块  

color_bitmap = displayio.Bitmap(60, 60, 1)  

color_palette = displayio.Palette(1)  

color_palette[0] = 0x000000  # 初始黑色  

  

color_tilegrid = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=150, y=20)  

splash.append(color_tilegrid)  

  

  

# -----------------------  

# 硬件引脚分配  

# -----------------------  

s0 = digitalio.DigitalInOut(board.D3)  

s1 = digitalio.DigitalInOut(board.D4)  

s2 = digitalio.DigitalInOut(board.D5)  

s3 = digitalio.DigitalInOut(board.D6)  

out_pin = digitalio.DigitalInOut(board.D9)  

  

# 校准按键 (D1) - 按下时为高电平  

calibrate_button = digitalio.DigitalInOut(board.D1)  

calibrate_button.direction = digitalio.Direction.INPUT  

# 不需要上拉电阻,因为按键按下时为高电平  

  

# 调整颜色阈值按键 (D2) - 按下时为高电平  

adjust_button = digitalio.DigitalInOut(board.D2)  

adjust_button.direction = digitalio.Direction.INPUT  

# 不需要上拉电阻,因为按键按下时为高电平  

  

sensor = TCS3200(s0, s1, s2, s3, out_pin)  

sensor.set_frequency(2)  # 100% 模式  

  

# 初始化NeoPixel  

pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)  

pixel.brightness = 0.3  

  

  

# -----------------------  

# 主循环  

# -----------------------  

# 启动时执行白平衡校准  

sensor.calibrate_white(out_pin)  

text_label.text = "Calibration complete\nStarting color recognition...\nPress D1 (HIGH) to recalibrate\nPress D2 (HIGH) to adjust color"  

display.refresh()  

time.sleep(1)  

  

# 主循环  

while True:  

    # 检查是否需要重新校准(带消抖)  

    if calibrate_button.value:  

        # 简单消抖:等待一小段时间确认按键仍然被按下  

        time.sleep(0.05)  

        if calibrate_button.value:  

            sensor.calibrate_white(out_pin)  

            text_label.text = "Calibration complete\nStarting color recognition...\nPress D1 (HIGH) to recalibrate\nPress D2 (HIGH) to adjust color"  

            display.refresh()  

            # 等待按键释放  

            while calibrate_button.value:  

                time.sleep(0.01)  

            time.sleep(0.5)  # 额外延迟防止重复触发  

     

    # 检查是否需要调整颜色阈值(带消抖)  

    if adjust_button.value:  

        # 简单消抖:等待一小段时间确认按键仍然被按下  

        time.sleep(0.05)  

        if adjust_button.value:  

            # 每次按下增加0.05的阈值  

            sensor.adjust_color_threshold(0.05)  

            # 等待按键释放  

            while adjust_button.value:  

                time.sleep(0.01)  

            time.sleep(0.5)  # 额外延迟防止重复触发  

     

    sensor.set_color_channel('R')  

    time.sleep(0.05)  

    freq_r = measure_frequency(out_pin)  

  

    sensor.set_color_channel('G')  

    time.sleep(0.05)  

    freq_g = measure_frequency(out_pin)  

  

    sensor.set_color_channel('B')  

    time.sleep(0.05)  

    freq_b = measure_frequency(out_pin)  

  

    # 将频率转换为RGB值  

    r, g, b = sensor.frequency_to_rgb(freq_r, freq_g, freq_b)  

  

    # 更新 TFT 色块为当前颜色  

    color_palette[0] = (r << 16) | (g << 8) | b  

  

    # 更新NeoPixel颜色  

    pixel.fill((r, g, b))  

  

    text_label.text = (  

        f"Frequency:   RGB Value\n"  

        f"R: {freq_r:6.1f}    {r:3}\n"  

        f"G: {freq_g:6.1f}    {g:3}\n"  

        f"B: {freq_b:6.1f}    {b:3}\n"  

        f"Threshold: {sensor.color_threshold:.2f}\n"  

        f"D1(HIGH):cal D2(HIGH):adj"  

    )  

  

    display.refresh()  

    time.sleep(0.1)  


这里要注意,由于要用到的板载的Neo颜色LED需要安装对应的驱动才能驱动起来,在这里可以在官网下载对应的例程,参考链接:https://learn.adafruit.com/esp32-s2-reverse-tft-feather/neopixel-led

把例程里面的库文件复制到开发板的程序库里面,完成后的效果如下:

edd82aa6-e7ce-418b-b908-0e23b562e5d0.png

完成Neo驱动库的添加。

完成后,点击顶部菜单里含有向下箭头的“保存”按钮,程序就自动下载到开发板了。

程序运行之后初始界面显示如下:

微信图片_20251206125820_54_368.jpg

提示按下D1进行自适应矫正,按下D2调整颜色阈值,在白光环境下按下D1进行自适应矫正,按下D2调整颜色阈值。

矫正之后的效果如下:

微信图片_20251206125818_52_368.jpg

用一个带有颜色物体放置到颜色传感器前面,效果如下:

微信图片_20251206125819_53_368.jpg

可以看到屏幕显示的颜色和物体颜色一致,开发板背面的颜色传感器也变换显示对应的颜色。


共1条 1/1 1 跳转至

回复

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