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

共1条 1/1 1 跳转至

Let'sdo2025第三期活动【拾色播放器DIY】(成果贴)-拾色发音

专家
2025-12-03 10:57:33     打赏

前面完成了所有相关模块的测试,本次以CPY方式完成最终成品:由颜色传感器获取颜色信息,根据颜色信息转换为合适的音符,由蜂鸣器播放出来。在这之前还得由CPY完成颜色识别、音符播放的测试。

再次附上开发板的引脚对照图:

图片1.png


GPIO7,GPIO42,GPIO40,GPIO41,GPIO45,GPIO35,GPIO36已经被用于TFT显示屏,GPIO0、GPIO1、GPIO2被用于按钮D0、D1、D2,估计GPIO38、GPIO39被用于串口。所以准备使用GPIO18、GPIO17、GPIO16、GPIO15、GPIO14用于颜色识别模块,GPIO3用于蜂鸣器。我把开发板、TCS3200颜色识别模块、蜂鸣器都固定在一个底板上,所以使用板载的WS2812用来合成TCS3200颜色识别模块检测出来的颜色就不现实了,板载的WS2812在开发板的另一侧,固定后看不见。而且实测中板载的WS2812显示效果也不好,所以我又追加了一个外置的WS2812模块,并使用GPIO4驱动。


整体的接线图:

TCS3200引脚        ESP32-S3引脚    无源蜂鸣器      外置WS2812

============================================================

VCC(电源)        3.3V                            Vcc

GND(地线)           GND

S0(输出频率缩放)    GPIO14

S1(输出频率缩放)    GPIO15

S2(光电二极管选择)GPIO16

S3(光电二极管选择)GPIO17

OUT(频率输出)    GPIO18

                    GPIO3           控制引脚

                    GPIO4                           DIO

                    GND             地             地

                    VBUS            电源            

============================================================

图片2.png

程序处理逻辑:

图片3.png

在WS2812上显示颜色的时候,我把合成颜色简单设置为几个常见的颜色,而且对于没有检测对象时获得的近似黑色的颜色,直接等效为关闭WS2812的显示,因此这个时候显示屏上显示的颜色与WS2812不一致。实际上其他颜色,也不完全一致,因为设置方式一样。

主程序代码:


import time
import board
import pwmio
import digitalio
import neopixel
import displayio
import terminalio
from adafruit_display_text import label
from TCS3200 import TCS3200
from Siren import Siren
# 定义按键变量
Button1_Value = 0
test_flag = 0
# 初始化PWM输出到蜂鸣器引脚
buzzer = pwmio.PWMOut(board.D3, duty_cycle=0, frequency=440, variable_frequency=True)
#使用蜂鸣器播放声调
def play_tone(frequency, duration):
    """播放指定频率和持续时间的音调"""
    if frequency == 0:
        # 静音
        buzzer.duty_cycle = 0
    else:
        # 设置频率并启动声音
        buzzer.frequency = frequency
        buzzer.duty_cycle = 32768  # 50%占空比
    time.sleep(duration)
    # 停止声音
    buzzer.duty_cycle = 0
    # 音符间短暂停顿
    time.sleep(0.05)
#不同的颜色发出不同的音调
yifu_f = [
    262,
    360,
    460,
    569,
    760,
    860,
    960,
    1060,
    1160,
    1260,
    1360,
    1460,
    1560,
    1660
]
# 创建警笛实例
siren = Siren(buzzer)
# 初始化板载按键D1
button1 = digitalio.DigitalInOut(board.D1)
button1.switch_to_input(pull=digitalio.Pull.DOWN)
# 初始化板载按键D2
button2 = digitalio.DigitalInOut(board.D2)
button2.switch_to_input(pull=digitalio.Pull.DOWN)
# First set some parameters used for shapes and text
BORDER = 20
FONTSCALE = 2
BACKGROUND_COLOR = 0x000000  # Bright Green
FOREGROUND_COLOR = 0xAA0088  # Purple
TEXT_COLOR = 0xFFFFFF
display = board.DISPLAY
# 整个背景
splash = displayio.Group()
display.root_group = splash
color_bitmap = displayio.Bitmap(display.width, display.height, 1)
color_palette = displayio.Palette(1)
color_palette[0] = BACKGROUND_COLOR
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=20)
splash.append(bg_sprite)
# 标题
text = "=== EEPW-DigiKey ==="
text_area = label.Label(terminalio.FONT, text=text, color=TEXT_COLOR)
text_width = text_area.bounding_box[2] * FONTSCALE
text_group = displayio.Group(
    scale=FONTSCALE,
    x=display.width // 2 - text_width // 2,
    #y=display.height // 2,
    y=20,
)
text_group.append(text_area)  # Subgroup for text scaling
splash.append(text_group)
block_width = display.width//3
# 红色标记快
block_r = displayio.Bitmap(block_width, 30, 1)
inner_palette_r = displayio.Palette(1)
inner_palette_r[0] = 0xFF0000
inner_sprite_r = displayio.TileGrid(block_r, pixel_shader=inner_palette_r, x=0, y=40)
splash.append(inner_sprite_r)
#TCS3200红色数据
text_area_r = label.Label(terminalio.FONT, text="", color=0xFFFF00, x=10, y=8)
text_group_r = displayio.Group(scale=FONTSCALE, x=0, y=40,)
text_group_r.append(text_area_r)
splash.append(text_group_r)
# 绿色标记快
block_g = displayio.Bitmap(block_width, 30, 1)
inner_palette_g = displayio.Palette(1)
inner_palette_g[0] = 0x00FF00
inner_sprite_g = displayio.TileGrid(block_g, pixel_shader=inner_palette_g, x=80, y=40)
splash.append(inner_sprite_g)
#TCS3200绿色数据
text_area_g = label.Label(terminalio.FONT, text="", color=0x000000, x=10, y=8)
text_group_g = displayio.Group(scale=FONTSCALE, x=80, y=40,)
text_group_g.append(text_area_g)
splash.append(text_group_g)
# 蓝色色标记快
block_b = displayio.Bitmap(block_width, 30, 1)
inner_palette_b = displayio.Palette(1)
inner_palette_b[0] = 0x0000FF
inner_sprite_b = displayio.TileGrid(block_b, pixel_shader=inner_palette_b, x=160, y=40)
splash.append(inner_sprite_b)
#TCS3200蓝色数据
text_area_b = label.Label(terminalio.FONT, text="", color=0xFFFFFF, x=10, y=8)
text_group_b = displayio.Group(scale=FONTSCALE, x=160, y=40,)
text_group_b.append(text_area_b)
splash.append(text_group_b)
#动态颜色合成区域
block_hc = displayio.Bitmap(display.width, 30, 1)
inner_palette_hc = displayio.Palette(1)
inner_palette_hc[0] = 0x000000
inner_sprite_hc = displayio.TileGrid(block_hc, pixel_shader=inner_palette_hc, x=0, y=80)
splash.append(inner_sprite_hc)
# 创建TCS3200驱动对象
txs3200 = TCS3200(
    s0_pin=board.D14,
    s1_pin=board.D15,
    s2_pin=board.D16,
    s3_pin=board.D17,
    out_pin=board.D18
)
# 三色灯初始化,板载的显示不明显,使用外置的WS2812,占用D4引脚
#pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
pixel = neopixel.NeoPixel(board.D4, 1)
pixel.brightness = 0.8
# 主循环
for f in yifu_f:
    play_tone(f, 0.1)
# 主循环
while True:
    # 按键D1
    if button1.value:
        test_flag = 0
        # 调用白平衡校准
        txs3200.calibrate_white_balance()
        # 更新显示
        text_area_r.text = "{:.3f}".format(txs3200.r_scal)
        text_area_g.text = "{:.3f}".format(txs3200.g_scal)
        text_area_b.text = "{:.3f}".format(txs3200.b_scal)
    # 按键D2
    if button2.value:
        test_flag = 1
    if test_flag:
        # 读取并显示TCS3200颜色传感器的RGB值
        if txs3200 is not None:
            try:
                # 调用read_rgb方法读取颜色值
                R_Val, G_Val, B_Val = txs3200.read_rgb()
                # 更新显示
                text_area_r.text = "{:3d}".format(R_Val)
                text_area_g.text = "{:3d}".format(G_Val)
                text_area_b.text = "{:3d}".format(B_Val)
                print("RGB: #{:02X}{:02X}{:02X}".format(R_Val, G_Val, B_Val))
                #播放声音
                print("Sound:\n")
                yf = txs3200.getYinfuByColor(R_Val, G_Val, B_Val)
                print("Yinfu = #{:2d} f={:2d}\n".format(yf, yifu_f[yf]))
                if (yf > 0):
                    pixel.fill((R_Val, G_Val, B_Val))
                else:
                    pixel.fill((0, 0, 0))
                play_tone(yifu_f[yf], 0.2)
                #去掉动态标签
                splash.pop()
                #追加新的
                block_hc = displayio.Bitmap(display.width, 30, 1)
                inner_palette_hc = displayio.Palette(1)
                inner_palette_hc[0] = R_Val*256*256 + G_Val*256 + B_Val
                inner_sprite_hc = displayio.TileGrid(block_hc, pixel_shader=inner_palette_hc, x=0, y=80)
                splash.append(inner_sprite_hc)
            except Exception as e:
                print(f"处理异常: {e}")
                #报警
                siren.siren(2)
        else:
            # 更新显示屏
            text_area_r.text = "{:3d}".format(R_Val)
            text_area_g.text = "{:3d}".format(G_Val)
            text_area_b.text = "{:3d}".format(B_Val)
            #text_area_h.text = "#: {:02X}{:02X}{:02X}".format(R_Val, G_Val, B_Val)
    time.sleep(0.05)


最终装置的模样:

图片4.png

运行效果:





共1条 1/1 1 跳转至

回复

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