"拾颜播放器"通过颜色传感器检测物体的颜色,并根据检测到的颜色播放不同风格的音乐。项目将颜色识别与情感表达相结合,创造出独特的交互体验。
核心功能颜色检测:使用 TCS3200 传感器识别颜色,支持校准提高精度
情感映射:将颜色映射到不同的情感主题(热情、舒缓、自然、神秘等)
音乐播放:根据情感主题播放不同风格的经典旋律
显示屏反馈:实时显示检测到的颜色和当前情感状态
多种触发方式:接近传感器或 D1 按钮触发
音量控制:D0/D2 按钮调节音量
校准功能:支持白/红/绿/蓝四色校准,提高颜色识别精度
| 主控板 | ESP32-S3 Reverse TFT Feather |
| 开发语言 | CircuitPython |
| 传感器 | TCS3200 颜色传感器、Littelfuse 59001 干簧管 |
| 输出设备 | 蜂鸣器、ST7789 显示屏 (135x240) |
| 用户输入 | 3个按钮 (D0/D1/D2) |
一、硬件组成1.1 核心硬件清单
| 主控板 | ESP32-S3 Reverse TFT Feather | 1 | 核心控制器 |
| 颜色传感器 | DFRobot SEN0101 (TCS3200) | 1 | 检测物体颜色 |
| 接近传感器 | Littelfuse 59001 (干簧管) | 1 | 检测物体靠近 |
| 蜂鸣器 | DFRobot DFR0032 | 1 | 播放音乐 |
| 显示屏 | ST7789 (135x240) | 1 | 显示信息 |
| 彩色纸片 | 红、绿、蓝、白 | 4 | 测试校准用 |
| 磁铁 | 小型磁铁 | 1 | 触发接近传感器 |
ESP32-S3 Reverse TFT Feather ┌─────────────────────────────────────────────────────┐ │ │ │ ┌─────────┐ │ │ │ TCS3200 │ ┌──────────┐ │ │ │ │ │ 蜂鸣器 │ │ │ │ VCC→3V3 │────────►│ VCC→3V3 │ │ │ │ GND→GND │────────►│ GND→GND │ │ │ │ S0→D9 │ │ │ │ │ │ S1→D10 │ │ BUZZER→D5 │ │ │ S2→D11 │ └──────────┘ │ │ │ S3→D12 │ │ │ │ OUT→D13 │ │ │ │ LED→D18 │ │ │ └─────────┘ │ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ 59001 │ │ ST7789 │ │ │ │ │ │ (板载) │ │ │ │ Pin1→GND │ │ │ │ │ │ Pin2→D6 │ │ │ │ │ └──────────┘ └──────────┘ │ │ │ └─────────────────────────────────────────────────────┘1.3 详细引脚分配TCS3200 颜色传感器
| VCC | 3.3V 或 5V | 电源 |
| GND | GND | 地线 |
| S0 | D9 | 频率缩放 (HIGH=100%) |
| S1 | D10 | 频率缩放 (HIGH=100%) |
| S2 | D11 | 滤波器选择 |
| S3 | D12 | 滤波器选择 |
| OUT | D13 | 频率输出 |
| LED | D18 | LED控制 |
| Pin1 | GND | 地线 |
| Pin2 | D6 | 接近检测 (内部上拉) |
| 蜂鸣器 | D5 |
| 显示屏 | 板载 (board.DISPLAY) |
| D0 按钮 | 音量增加 (默认 HIGH,按下=LOW) |
| D1 按钮 | 触发按钮 (默认 LOW,按下=HIGH) |
| D2 按钮 | 音量减少 (默认 LOW,按下=HIGH) |
项目使用 OPPOSans 字体显示中文。字体文件需要从 TTF 转换而来。
| 原始字体 | fonts/OPPOSans-Medium.ttf | TTF 格式 (约 1.5MB) |
| 运行字体 | fonts/OPPOSans-M-16.pcf | PCF 格式 (50KB, 仅含项目用字符) |
需要将 TTF 转换为 CircuitPython 可用的 PCF 格式:
# 安装字体处理工具 pip install fonttools # 转换(需要 bdfconvert 工具) python3 tools/convert_font.py项目使用的中文字符
项目共使用 57个 中文字符:
| 显示文字 | 拾颜播放器靠近传感器开始等待中将彩色卡片检测到颜色播放中错误请重试颜色检测演示 |
| 情感名称 | 深海蓝炽热红清新绿温暖黄神秘紫中性灰 |
| 情感描述 | 舒缓热情自然活力梦幻平静 |
运行 tests/test_display.py 验证字体是否完整:
cd tests python3 test_display.py
测试会显示所有 90 个中文字符(含项目使用的 57 个),确保字体文件完整。
字体会证结果--- 测试:所有中文字符 --- 字体包含 90 个字符 显示 15 行,每行 6 列
如果显示缺失字符,需要更新字体文件(参考 CLAUDE.txt 中的字体转换工具)。
二、软件架构2.1 模块结构
color_player/ ├── code.py # 主程序入口 ├── color_sensor.py # 颜色传感器驱动 ├── proximity_sensor.py # 接近传感器驱动 ├── music_player.py # 音乐播放模块 ├── display_manager.py # 显示屏管理模块 ├── emotion_mapper.py # 颜色情感映射模块 ├── tests/ │ ├── test_color_sensor.py # 颜色传感器测试 │ ├── test_proximity.py # 接近传感器测试 │ ├── test_display.py # 显示屏测试(含字体验证) │ └── test_buzzer.py # 蜂鸣器测试 └── fonts/ └── OPPOSans-M-16.pcf # 中文字体文件 (与 test_display.py 一致)2.2 数据流
┌─────────────┐ │ 彩色物体 │ └──────┬──────┘ │ ▼ ┌─────────────┐ ┌─────────────┐ │ 接近传感器 │────►│ 主程序 │ │ (检测靠近) │ │ (code.py) │ └─────────────┘ └──────┬──────┘ │ ┌───────────────┼───────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │颜色传感器 │ │ 情感映射器 │ │显示屏管理│ │读取RGB │ │ 颜色→情感 │ │ 显示结果 │ └────┬─────┘ └──────┬───────┘ └──────────┘ │ │ │ ▼ │ ┌──────────────┐ │ │ 音乐播放器 │ │ │ 播放对应音乐 │ │ └──────────────┘ ▼ ┌─────────────────────────────────────┐ │ code.py 汇总各模块信息 │ │ 控制整体流程 │ └─────────────────────────────────────┘
三、模块详解3.1 颜色传感器 (color_sensor.py)功能说明
驱动 TCS3200 颜色传感器,读取物体的 RGB 值。
核心方法| get_raw() | 获取原始计数值 |
| get_rgb() | 获取归一化的 RGB 值 (0-255) |
| get_color_name() | 获取主导颜色名称 |
| read_all_channels() | 读取所有通道原始值 |
| calibrate() | 执行校准流程 |
| calculate_color_from_calibration() | 基于校准数据计算颜色 |
| get_calibrated_rgb() | 使用校准数据获取 RGB |
| get_calibrated_color_name() | 使用校准数据获取颜色名称 |
from color_sensor import ColorSensor
# 初始化(使用默认引脚)
color_sensor = ColorSensor()
# 获取 RGB 值
rgb = color_sensor.get_rgb()
if rgb:
r, g, b = rgb
print(f"R={r}, G={g}, B={b}")
# 获取原始数据
raw = color_sensor.get_raw()
print(f"原始值: {raw}")
# 使用校准数据获取
RGBrgb = color_sensor.get_calibrated_rgb()校准功能内置校准(推荐)在 code.py 中启动时:
同时按住 D0 + D2 超过 3 秒进入校准模式
依次将 白、红、绿、蓝 纸片放在传感器上
每张纸片放好后按 D1 确认,按 D2 跳过
校准完成后自动进入正常模式
运行 tests/test_color_sensor.py 进行交互式校准测试。
校准原理使用欧几里得距离匹配当前颜色与校准数据:
# 计算差异分数 diff = (R - R_cal)^2 + (G - G_cal)^2 + (B - B_cal)^2score = diff ** 0.5 # 开方得到距离
选择距离最小的校准颜色作为匹配结果。
3.2 接近传感器 (proximity_sensor.py)功能说明驱动 Littelfuse 59001 干簧管传感器,检测磁铁靠近。
核心方法| is_near() | 检测是否有物体靠近(带防抖) |
| get_state() | 获取原始状态 |
| wait_for_near() | 等待物体靠近 |
| wait_for_leave() | 等待物体离开 |
from proximity_sensor import ProximitySensor
# 初始化(使用默认引脚 D6)
proximity = ProximitySensor()
# 检测靠近
if proximity.is_near():
print("检测到物体靠近!")
# 等待靠近(带超时)
if proximity.wait_for_near(timeout=10):
print("物体靠近")防抖配置# 自定义防抖参数 proximity = ProximitySensor( debounce_threshold=5, # 连续稳定5次 debounce_delay=0.01 # 每次间隔10ms )3.3 音乐播放器 (music_player.py)功能说明
封装蜂鸣器 PWM 控制,支持播放旋律、音阶、和弦等。
核心方法| play_melody() | 播放旋律 |
| play_note() | 播放单个音符 |
| play_scale() | 播放音阶 |
| play_chord() | 播放和弦 |
| stop() | 停止播放 |
| play_success() | 播放成功提示音 |
| play_error() | 播放错误提示音 |
from music_player import MusicPlayer import pwmio # 初始化 buzzer = pwmio.PWMOut(board.D5, duty_cycle=0, frequency=440) player = MusicPlayer(buzzer) # 播放 C 大调音阶 scale = [261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25] durations = [0.3] * 8 player.play_melody(scale, durations) # 播放成功提示音 player.play_success()音量设置
VOLUME = 50 # 0-100,默认503.4 情感映射器 (emotion_mapper.py)功能说明
将 RGB 颜色值映射到情感主题,支持 6 种情感。
情感配置| passion | 炽热红 | 红色系 | 快节奏、大调 |
| sunshine | 温暖黄 | 黄色系 | 明亮、大调 |
| nature | 清新绿 | 绿色/青色 | 五声音阶 |
| calm | 深海蓝 | 深蓝色 | 慢节奏、小调 |
| mystery | 神秘紫 | 紫色系 | 蓝调风格 |
| neutral | 中性灰 | 低饱和度 | 平静和弦 |
from emotion_mapper import EmotionMapper
# 情感配置
EMOTIONS = {
"passion": {
"name": "炽热红",
"notes": [261.63, 329.63, 392.00], # C4, E4, G4
"durations": [0.15, 0.15, 0.3],
},
# ... 其他情感
}# 初始化
mapper = EmotionMapper(EMOTIONS)
# 获取情感
emotion = mapper.get_emotion(255, 0, 0) # 红色
print(f"情感: {emotion}") # 输出
# 获取完整情感信息
info = mapper.get_emotion_info(255, 0, 0)
print(f"名称: {info['name']}") # 输出: 炽热红3.5 显示屏管理 (display_manager.py)功能说明管理 ST7789 显示屏显示,支持中文字体。
核心方法| show_welcome() | 显示欢迎界面 |
| show_waiting() | 显示等待界面 |
| show_emotion() | 显示情感信息 |
| show_error() | 显示错误信息 |
| show_color_block() | 显示颜色块 |
| show_calibration() | 显示校准界面 |
| clear() | 清屏 |
from display_manager import DisplayManager
# 初始化
display = DisplayManager()
# 显示欢迎界面
display.show_welcome()time.sleep(2)
# 显示情感信息
display.show_emotion(
r=255, g=0, b=0,
emotion_key="passion",
emotion_info={
"name": "炽热红",
"description": "热情",
"bg_color": 0xFF0000,
"text_color": 0xFFAAAA
})四、主程序流程4.1 用户操作指南按钮功能
| D0 | 音量增加 | 按下(LOW)时音量+5%,最大100% |
| D2 | 音量减少 | 按下(HIGH)时音量-5%,最小0% |
| D1 | 触发按钮 | 按下(HIGH)触发颜色检测和播放 |
接近传感器触发(高优先级)
将磁铁靠近干簧管传感器
触发后检测颜色并播放音乐
移开磁铁后重置状态
D1 按钮触发(低优先级)
按下 D1 按钮触发检测
松开后重置状态
启动时同时按住 D0 + D2 超过 3 秒。
4.2 代码结构 (code.py)def main():
"""主程序入口"""
# 1. 初始化各模块
color_sensor = ColorSensor(...) # 颜色传感器
buzzer = pwmio.PWMOut(...) # 蜂鸣器
proximity = ProximitySensor(...) # 接近传感器
display = DisplayManager() # 显示屏
emotion_mapper = EmotionMapper(...) # 情感映射器
# 2. 显示欢迎界面
display.show_welcome()
time.sleep(1)
# 3. 检查是否进入校准模式(D0 + D2 按下3秒)
# ...
# 4. 主循环
was_near = False # 接近传感器状态
was_trigger_pressed = False # D1 按钮状态
has_triggered = False # 单次触发标志
current_emotion = "neutral"
while True:
# 读取按钮状态
vol_up_state = btn_vol_up.value # D0
vol_down_state = btn_vol_down.value # D2
trigger_state = btn_trigger.value # D1
# 音量控制
if not vol_up_state and VOLUME < 100: # D0 按下
VOLUME = min(100, VOLUME + 5)
if vol_down_state and VOLUME > 0: # D2 按下
VOLUME = max(0, VOLUME - 5)
# 检测接近状态
is_proximity = proximity.is_near()
is_trigger_button_pressed = trigger_state # D1 按下为 HIGH
# 触发逻辑:接近传感器优先(单次触发模式)
if is_proximity:
# 接近传感器触发(高优先级)
if not was_near:
print("
我要赚赏金
