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

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 电源
============================================================

程序处理逻辑:

在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)最终装置的模样:

运行效果:
我要赚赏金
