实现板载RGB的全彩控制,实时显示当前获取的颜色;
1、硬件


TCS3200是一款基于光频转换技术的颜色传感器,通过内置的8×8光电二极管阵列,含红、绿、蓝及透明滤波器,检测光线颜色。每个滤波器对应16个光电二极管,可单独选择以测量特定颜色光强。传感器将光强转换为频率信号50%占空比方波,频率与光强成线性关系,便于微控制器处理。
ESP32原理图

电源与滤波
功能:为整个系统提供稳定的电源,通过滤波电路去除电源中的噪声和干扰,确保各模块获得纯净的电源供应。
重要性:稳定的电源是电子设备正常工作的基础,滤波电路能有效减少电源波动对系统性能的影响。
功能:电源开关用于控制整个系统的电源通断,重置电路可在系统出现异常时,通过硬件触发使系统恢复到初始状态。
重要性:方便用户对设备进行开关机操作,以及在系统死机等情况下进行复位操作,提高设备的可靠性。
USB - C接口与电源管理
功能:USB - C接口不仅用于数据传输,还可为设备充电。电源管理芯片负责管理电池的充电过程,确保充电安全高效,同时为系统提供合适的电压。
重要性:满足设备的充电需求,实现数据交互,同时保护电池和系统电路。
LIPO充电管理(LIPO CHARGING)
功能:专门针对锂聚合物电池(LIPO)的充电管理模块,能够根据电池状态自动调整充电电流和电压,实现恒流 - 恒压充电过程,防止电池过充、过放和过流。
重要性:延长锂聚合物电池的使用寿命,保障电池安全,避免因不当充电导致的电池损坏甚至危险。
ESP32 - S3主控芯片
功能:作为整个系统的核心,ESP32 - S3是一款集成了Wi - Fi和蓝牙功能的微控制器。它负责处理各种数据,控制其他模块的工作,实现系统的各种功能,如与外部设备通信、处理传感器数据等。
重要性:是系统的大脑,决定了系统的性能和功能扩展能力。
NEOPIXEL接口
功能:用于连接NEOPIXEL LED灯带或其他兼容的智能LED产品。通过该接口,主控芯片可以控制LED的颜色、亮度和显示效果。
重要性:为设备添加了丰富的灯光显示功能,可用于状态指示、装饰等。
按键输入
功能:提供用户与设备交互的接口,用户可以通过按下按键向系统发送指令,如确认、返回、切换模式等。
重要性:增强了设备的操作性和用户体验,使设备能够根据用户的输入做出相应的响应。
TFT显示屏接口
功能:用于连接反向TFT显示屏,主控芯片通过该接口向显示屏发送图像数据,控制显示屏显示各种内容,如文字、图片、图形界面等。
重要性:实现设备的可视化输出,是用户获取信息的重要途径。
通用SPI TFT接口(Generic SPI TFT)
功能:提供了一种通用的SPI(串行外设接口)连接方式,用于连接支持SPI协议的TFT显示屏,扩展了显示屏的兼容性。
重要性:使设备能够适配更多类型的显示屏,提高了硬件的通用性和灵活性。
引脚扩展接口
功能:提供额外的引脚接口,方便用户扩展其他功能模块,如传感器、执行器等,增强了系统的可扩展性。
重要性:使设备能够根据不同的应用需求进行功能扩展,满足多样化的使用场景。
二、代码
import time
import board
import digitalio
import displayio
import terminalio
from adafruit_display_text import label
import neopixel
import pwmio
初始化NeoPixel
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
pixel.brightness = 0.3
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
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频率
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"白平衡校准完成: R={self.white_r:.1f}, G={self.white_g:.1f}, B={self.white_b:.1f}")
def frequency_to_rgb(self, freq_r, freq_g, freq_b):
# 避免除以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:
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)
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
buzzer = pwmio.PWMOut(board.A0, 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
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]
八阶音符频率 (C4-C5 八度)
低音到高音: C4, D4, E4, F4, G4, A4, B4, C5
对应的颜色映射: 红, 橙, 黄, 绿, 青, 蓝, 紫, 白
note_frequencies = [262, 294, 330, 349, 392, 440, 494, 523] # 单位: Hz
QUARTER_NOTE = 0.2 # 四分音符时长
EIGHTH_NOTE = 0.1 # 八分音符时长
def get_note_for_color(r, g, b):
"""根据RGB值确定要播放的音符和时长"""
# 确定主色调
max_val = max(r, g, b)
if max_val == 0:
return 0, QUARTER_NOTE # 黑色,无声
# 计算颜色比例
r_ratio = r / max_val
g_ratio = g / max_val
b_ratio = b / max_val
# 根据颜色确定音符
if r_ratio > 0.8 and g_ratio < 0.3 and b_ratio < 0.3: # 红色
return note_frequencies[0], QUARTER_NOTE
elif r_ratio > 0.8 and g_ratio > 0.5 and b_ratio < 0.3: # 橙色/黄色
return note_frequencies[1], QUARTER_NOTE
elif r_ratio > 0.7 and g_ratio > 0.7 and b_ratio < 0.3: # 黄色
return note_frequencies[2], QUARTER_NOTE
elif r_ratio < 0.3 and g_ratio > 0.8 and b_ratio < 0.3: # 绿色
return note_frequencies[3], QUARTER_NOTE
elif r_ratio < 0.3 and g_ratio > 0.8 and b_ratio > 0.8: # 青色
return note_frequencies[4], QUARTER_NOTE
elif r_ratio < 0.3 and g_ratio < 0.3 and b_ratio > 0.8: # 蓝色
return note_frequencies[5], QUARTER_NOTE
elif r_ratio > 0.7 and g_ratio < 0.3 and b_ratio > 0.7: # 紫色
return note_frequencies[6], QUARTER_NOTE
elif r_ratio > 0.7 and g_ratio > 0.7 and b_ratio > 0.7: # 白色/灰色
return note_frequencies[7], QUARTER_NOTE
else: # 其他颜色,根据亮度决定音符
# 亮度值映射到音符
brightness = (r + g + b) / 3
note_index = int((brightness / 255) * 7)
note_index = max(0, min(7, note_index))
duration = QUARTER_NOTE if brightness > 127 else EIGHTH_NOTE
return note_frequencies[note_index], duration
def play_melody(r, g, b):
"""播放八阶音符组成的旋律"""
# 获取基本音符
base_freq, base_duration = get_note_for_color(r, g, b)
if base_freq == 0: # 无声
time.sleep(base_duration)
return
# 播放简单的旋律:主音符 + 上方三度 + 主音符
# 计算三度音程
third_freq = int(base_freq * 1.25) # 大三度
# 播放旋律
play_tone(base_freq, base_duration)
play_tone(third_freq, base_duration * 0.5)
play_tone(base_freq, base_duration * 0.5)
TFT 显示设置 - 简化版
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] = 0x000000 # 初始黑色
color_tilegrid = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
splash.append(color_tilegrid)
s0 = digitalio.DigitalInOut(board.D12)
s1 = digitalio.DigitalInOut(board.D11)
s2 = digitalio.DigitalInOut(board.D10)
s3 = digitalio.DigitalInOut(board.D9)
out_pin = digitalio.DigitalInOut(board.D6)
校准按键 (D1)
calibrate_button = digitalio.DigitalInOut(board.D1)
calibrate_button.direction = digitalio.Direction.INPUT
sensor = TCS3200(s0, s1, s2, s3, out_pin)
sensor.set_frequency(2) # 100% 模式
def print_color_data(freq_r, freq_g, freq_b, r, g, b):
"""通过串口输出颜色信息"""
# 格式:频率值(Hz)和RGB值(0-255)
print(f"Frequency: R={freq_r:6.1f}Hz, G={freq_g:6.1f}Hz, B={freq_b:6.1f}Hz | RGB: ({r:3}, {g:3}, {b:3})")
开机启动音效 - 播放八阶音符
print("播放启动音效...")
for freq in note_frequencies:
play_tone(freq, 0.1)
time.sleep(0.5)
play_tone(note_frequencies[0], 0.2) # C4
play_tone(note_frequencies[2], 0.2) # E4
play_tone(note_frequencies[4], 0.2) # G4
play_tone(note_frequencies[7], 0.4) # C5
sensor.calibrate_white(out_pin)
time.sleep(1)
print("颜色识别系统启动,开始读取颜色...")
print("按D1按键可重新进行白平衡校准")
while True:
# 检查是否需要重新校准
if calibrate_button.value:
time.sleep(0.05)
if calibrate_button.value:
print("开始白平衡校准...")
sensor.calibrate_white(out_pin)
print("白平衡校准完成")
# 播放校准完成提示音
play_tone(note_frequencies[7], 0.2) # 高音C
play_tone(note_frequencies[4], 0.2) # G
play_tone(note_frequencies[0], 0.4) # 低音C
while calibrate_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)
# 串口输出颜色信息
print_color_data(freq_r, freq_g, freq_b, r, g, b)
# 更新显示颜色 - 全屏显示
color_palette[0] = (r << 16) | (g << 8) | b
pixel.fill((r, g, b))
# 立即刷新屏幕
display.refresh()
# 蜂鸣器播放八阶音符旋律
play_melody(r, g, b)
# 短暂延时
time.sleep(0.1)
三、连接实物图

四、实现效果



颜色校准系统
白平衡校准:在白色背景下读取RGB基准值,自动计算校准系数
Gamma校正:应用2.2次方的非线性映射,符合人眼视觉特性
动态范围压缩:通过map函数将传感器数据映射到0-255范围
实时性优化
10ms快速采样周期,确保颜色变化即时响应
硬件中断驱动:利用FreqCount库实现精确频率测量
双缓冲技术:避免显示闪烁,确保平滑过渡
我要赚赏金
