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

共1条 1/1 1 跳转至

【Let'sdo第3期-拾色播放器DIY】过程贴-颜色蜂鸣器驱动实现

菜鸟
2025-12-14 20:08:57     打赏

#硬件连接图示:

蜂鸣器比较简单 三根线,分别是电源3.3V GND PWM输入,PWM接D4

颜色传感器 S0 -> D12 S1 -> D11 S2 -> D10 S3 -> D9 OUT -> D6 LED -> D5

image.png




#参考代码如下:

import boardimport digitalioimport timeimport displayioimport pwmioimport terminaliofrom adafruit_display_text import label
# 定义按键变量Button0_Value = 0Button1_Value = 0Button2_Value = 0
class TCS3200:    NUM_CYCLES = 10  # 测试多少个周期
    def __init__(self, s0_pin, s1_pin, s2_pin, s3_pin, out_pin):        # 初始化控制引脚        self.s0 = digitalio.DigitalInOut(s0_pin)        self.s1 = digitalio.DigitalInOut(s1_pin)        self.s2 = digitalio.DigitalInOut(s2_pin)        self.s3 = digitalio.DigitalInOut(s3_pin)        self.out = digitalio.DigitalInOut(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        # 设置频率缩放比为100% (最高精度)        self.set_frequency_scaling(100)        # 白平衡校准系数 (初始值为1,需要实际校准)        self.r_scal = 1.0        self.g_scal = 1.0        self.b_scal = 1.0
        print("TCS3200传感器初始化完成")
    def set_frequency_scaling(self, scaling):        """        设置传感器的频率缩放比例        # s0  s1        # L   L   关闭        # L   H   2%        # H   L   20%        # H   H   100%        """        if scaling == 2:       # 2%            self.s0.value = False            self.s1.value = True            # print("TCS3200传感器设置频率缩放比为:%2 -> s0,s1[0,1]")        elif scaling == 20:    # 20%            self.s0.value = True            self.s1.value = False            # print("TCS3200传感器设置频率缩放比为:%20 -> s0,s1[1,0]")        elif scaling == 100:   # 100%            self.s0.value = True            self.s1.value = True            # print("TCS3200传感器设置频率缩放比为:%100 -> s0,s1[1,1]")        else:                  # 关闭            self.s0.value = False            self.s1.value = False            # print("TCS3200传感器设置频率缩放比为:%0 -> s0,s1[0,0]")
        time.sleep(0.01)       # 短暂延时稳定频率缩放比例
    def set_color_filter(self, filter_type):        """        设置传感器的颜色滤波器        # s2  s3        # L   L   Red        # H   H   Green        # L   H   Blue        # H   L   Clear(no filter)        """        if filter_type == "Red":            self.s2.value = False            self.s3.value = False            # print("TCS3200传感器设置颜色滤波器为:Red -> s2,s3[0,0]")        elif filter_type == "Green":            self.s2.value = True            self.s3.value = True            # print("TCS3200传感器设置颜色滤波器为:Green -> s2,s3[1,1]")        elif filter_type == "Blue":            self.s2.value = False            self.s3.value = True            # print("TCS3200传感器设置颜色滤波器为:Blue -> s2,s3[0,1]")        else:  # "Clear"            self.s2.value = True            self.s3.value = False            # print("TCS3200传感器设置颜色滤波器为:Clear -> s2,s3[1,0]")
        time.sleep(0.01)       # 短暂延时稳定滤波器
    def measure_frequency(self):        # 测量频率,并转换单位为Hz        timestamps = []        last_state = self.out.value
        while len(timestamps) < self.NUM_CYCLES:            current_state = self.out.value            if current_state != last_state:  # 发生边缘变化                timestamps.append(time.monotonic_ns())                last_state = current_state
        # 计数周期        periods = []        for i in range(2, len(timestamps), 2):            period_ns = timestamps[i] - timestamps[i - 2]  # 一个完整周期(两个边缘)            periods.append(period_ns)
        avg_period_ns = sum(periods) / len(periods)        frequency = 1000000000 / avg_period_ns  # 转换为 Hz        # print(f"原始频率值 -> Frequency:{frequency:.3f}")
        return frequency
    def read_rgb_freq(self):        # 读取RGB三个通道的频率值        red_freq = 0        green_freq = 0        blue_freq = 0
        # 读取红色分量 (S2=0, S3=0)        self.set_color_filter("Red")        red_freq = self.measure_frequency()        # 读取绿色分量 (S2=1, S3=1)        self.set_color_filter("Green")        green_freq = self.measure_frequency()        # 读取蓝色分量 (S2=0, S3=1)        self.set_color_filter("Blue")        blue_freq = self.measure_frequency()
        # 清除绿色分量 (S2=1, S3=0)        # self.set_color_filter("Clear")
        # print(f"原始频率值 -> R:{red_freq:.3f}, G:{green_freq:.3f}, B:{blue_freq:.3f}")
        return red_freq, green_freq, blue_freq
    def calibrate_white_balance(self):        # 白平衡校准 - 将传感器对准白色参考物后调用此方法        print("正在进行白平衡校准...")        print("请将传感器对准白色参考物")
        # 读取白色参考物的原始频率        red, green, blue = self.read_rgb_freq()
        # 换算为RGB值 (18000/255 = 70)        red = red / 70 if red > 0 else 1.0        green = green / 70 if green > 0 else 1.0        blue = blue / 70 if blue > 0 else 1.0
        # 计算校准系数 (假设我们希望白色时RGB值接近255)        self.r_scal = 255.0 / red if red > 0 else 1.0        self.g_scal = 255.0 / green if green > 0 else 1.0        self.b_scal = 255.0 / blue if blue > 0 else 1.0
        print(f"校准完成 -> R:{self.r_scal:.3f}, G:{self.g_scal:.3f}, B:{self.b_scal:.3f}")
    def read_rgb(self):        # 读取RGB三个通道的频率值,应用白平衡,并转换为RGB        r = 0        g = 0        b = 0
        # 读取RGB三个通道的频率值        red_freq, green_freq, blue_freq = self.read_rgb_freq()
        # 应用白平衡校准 (18000/255 = 70)        r = int(red_freq / 70 * self.r_scal)        g = int(green_freq / 70 * self.g_scal)        b = int(blue_freq / 70 * self.b_scal)
        # 限制在0-255范围        r = max(0, min(255, r))        g = max(0, min(255, g))        b = max(0, min(255, b))
        return r, g, b

# 初始化板载按键D0/BOOT0,按下接地button0 = digitalio.DigitalInOut(board.BUTTON)button0.switch_to_input(pull=digitalio.Pull.UP)# 初始化板载按键D1,按下接VCCbutton1 = digitalio.DigitalInOut(board.D1)button1.switch_to_input(pull=digitalio.Pull.DOWN)# 初始化板载按键D2,按下接VCCbutton2 = digitalio.DigitalInOut(board.D2)button2.switch_to_input(pull=digitalio.Pull.DOWN)
# 初始化板载LEDled0 = digitalio.DigitalInOut(board.LED)# led0 = digitalio.DigitalInOut(board.D13)led0.direction = digitalio.Direction.OUTPUTled0.value = True
# 初始化颜色传感器LED补光灯led1 = digitalio.DigitalInOut(board.D5)led1.direction = digitalio.Direction.OUTPUTled1.value = False
# 初始化PWMOut,接蜂鸣器控制脚# pwm0 = digitalio.DigitalInOut(board.D4)# pwm0.direction = digitalio.Direction.OUTPUT# pwm0.value = Falsepwm0 = pwmio.PWMOut(board.D4, duty_cycle=0, frequency=1000, variable_frequency=True)# 8音阶频率(C4, D4, E4, F4, G4, A4, B4, C5)note_names = ['C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5']frequencies = [261, 293, 329, 349, 392, 440, 493, 523]# 音符播放控制函数def play_note(note):    if note in range(len(note_names)):        names = note_names[note]        freq = frequencies[note]        print(f"Playing {names} at {freq} Hz")        pwm0.frequency = int(freq)        pwm0.duty_cycle = 2 ** 15    else:        print(f"Note {names} is not valid in the scale")# 停止播放音符def stop_playing():    pwm0.duty_cycle = 0# 当前音符的索引note_index = 0# 记录音符播放开始的时间note_start_time = time.monotonic()
# 初始化显示屏display = board.DISPLAY# 创建显示组splash = displayio.Group()display.root_group = splash
# 创建DIY活动文本标签textdo = "Let's do##EEPW DIY"text_area_do = label.Label(terminalio.FONT, text=textdo, color=0xFFFF00, x=60, y=20)
# 创建文本标签用于显示RGB值text_area_r = label.Label(terminalio.FONT, text="R: ---", color=0xFF0000, x=10, y=50)text_area_g = label.Label(terminalio.FONT, text="G: ---", color=0x00FF00, x=10, y=70)text_area_b = label.Label(terminalio.FONT, text="B: ---", color=0x0000FF, x=10, y=90)text_area_h = label.Label(terminalio.FONT, text="#------", color=0xFFFFFF, x=10, y=120)
# 显示输出for text_area in (text_area_do, text_area_r, text_area_g, text_area_b, text_area_h):    splash.append(text_area)
# 创建TCS3200颜色传感器实体try:    # 创建TCS3200对象    color_sensor = TCS3200(        s0_pin=board.D12,        s1_pin=board.D11,        s2_pin=board.D10,        s3_pin=board.D9,        out_pin=board.D6    )    print("TCS3200实例创建成功")except Exception as e:    print(f"初始化TCS3200失败: {e}")    # 创建虚拟传感器用于测试    color_sensor = None
# 主循环while True:    led0.value = True    time.sleep(0.05)
    # 读取按键0    if not button0.value:        print("button0按下")        Button0_Value = 1        Button1_Value = 0        Button2_Value = 0    # 读取按键1    if button1.value:        print("button1按下")        Button0_Value = 0        Button1_Value = 1        Button2_Value = 0    # 读取按键2    if button2.value:        print("button2按下")        #Button0_Value = 0        #Button1_Value = 0        #Button2_Value = 1        Button2_Value = ~Button2_Value
    if Button0_Value:        Button0_Value = 0        # 调用白平衡校准        color_sensor.calibrate_white_balance()        # 更新显示        text_area_r.text = "R: {:.3f}".format(color_sensor.r_scal)        text_area_g.text = "G: {:.3f}".format(color_sensor.g_scal)        text_area_b.text = "B: {:.3f}".format(color_sensor.b_scal)        text_area_h.text = "#------"
    if Button1_Value:        # 读取并显示TCS3200颜色传感器的频率值        if color_sensor is not None:            try:                # 调用read_rgb_freq方法读取频率值                R_Val, G_Val, B_Val = color_sensor.read_rgb_freq()
                # 更新显示                text_area_r.text = "R: {:.3f}".format(R_Val)                text_area_g.text = "G: {:.3f}".format(G_Val)                text_area_b.text = "B: {:.3f}".format(B_Val)                text_area_h.text = "#: {:.3f},{:.3f},{:.3f}".format(R_Val, G_Val, B_Val)
                print("RGB: {:.3f},{:.3f},{:.3f}".format(R_Val, G_Val, B_Val))
            except Exception as e:                print(f"读取颜色传感器错误: {e}")                R_Val = 128                G_Val = 128                B_Val = 128
        else:            # 更新显示屏            text_area_r.text = "R: {:.3f}".format(R_Val)            text_area_g.text = "G: {:.3f}".format(G_Val)            text_area_b.text = "B: {:.3f}".format(B_Val)            text_area_h.text = "#: {:.3f},{:.3f},{:.3f}".format(R_Val, G_Val, B_Val)
    if Button2_Value:            # 停止当前音符(如果正在播放)        stop_playing()        # 播放下一个音符        play_note(note_index)        # 若达到最后一个音符则从头开始,切换到下一个音符        note_index = (note_index + 1) % len(note_names)        # 重置音符开始播放的时间        note_start_time = time.monotonic()        # 防抖处理        time.sleep(1)
        # 超过最大播放时长后,自动停止播放        if time.monotonic() - note_start_time > 0.5:            stop_playing()            # 记录下一个音符的开始时间            note_start_time = time.monotonic()
    else:        # 停止播放        stop_playing()
    led0.value = False    time.sleep(0.05)
//按下D1,进行白平衡校准,然后根据读取不同颜色 播放不同频率声音。





关键词: 拾色     TCS3200    

共1条 1/1 1 跳转至

回复

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