### 第15课 语音动感世界

#### 15.1 项目介绍

在前面的教程中，已经了解过SK6812模块、智能语音模块和无源蜂鸣器的工作原理和应用。

在本项目中，使用智能语音模块来控制SK6812RGB灯模块和无源蜂鸣器，实现自动化语音控制多彩灯光及蜂鸣器发出鸣叫声与播放美妙音乐。


#### 15.2 实验组件

|![](media/esp32.png)|![](media/SU-03T-1.png)|![](media/SK6812RGB.png)|![](media/4p.png)|
|-|-|-|-|
|ESP32 Plus主板 *1|智能语音模块 *1|SK6812RGB灯 *1|4p线 *1 |
|![](media/buzzer.png)|![](media/3p.png)|![](media/usb.png)| |
|无源蜂鸣器模块 *1|3P线 *2|USB线 *1| |

#### 15.3 模块接线图

智能语音模块、无源蜂鸣器和SK6812RGB灯模块的控制引脚：

|SK6812RGB灯（S引脚）|io26|
|-|-|
|无源蜂鸣器（S引脚）|io25|
|智能语音模块（TXD引脚）|io16|
|智能语音模块（RXD引脚）|io27|

⚠️ **特别注意：智能家居已经组装好了，这里不需要把智能语音模块、无源蜂鸣器和SK6812RGB灯模块拆下来又重新组装和接线，这里再次提供接线图，是为了方便您编写代码！**

![](media/pjt17.png)

#### 15.4 代码流程图

![](media/project15.png)

#### 15.5 实验代码

打开“Thonny”软件，点击“此电脑” → “D:” → “MicroPython资料” → “MicroPython_代码”。并鼠标左键双击“Project_15_voice_control_sk6812_buzzer.py”。

```Python
# 作者 : www.keyes-robot.com

from machine import Pin, PWM, UART
import neopixel
import time
import math

# 定义引脚
LED_PIN = 26
LED_COUNT = 4
BUZZER_PIN = 25
RX_PIN = 27
TX_PIN = 16

# 初始化NeoPixel
strip = neopixel.NeoPixel(Pin(LED_PIN), LED_COUNT)

# 初始化蜂鸣器
buzzer = PWM(Pin(BUZZER_PIN))
buzzer.duty(0)

# 初始化软件串口 (UART2)
uart = UART(2, baudrate=9600, rx=RX_PIN, tx=TX_PIN)

def color_wipe(color, wait):
    for i in range(len(strip)):
        strip[i] = color
        strip.write()
        time.sleep_ms(wait)

def theater_chase_rainbow(wait):
    first_pixel_hue = 0
    for a in range(30):
        for b in range(3):
            strip.fill((0, 0, 0))
            for c in range(b, len(strip), 3):
                hue = first_pixel_hue + c * 65536 // len(strip)
                rgb = hsv_to_rgb(hue / 65536.0, 1.0, 1.0)
                strip[c] = (int(rgb[0]), int(rgb[1]), int(rgb[2]))
            strip.write()
            time.sleep_ms(wait)
            first_pixel_hue += 65536 // 90

def hsv_to_rgb(h, s, v):
    if s == 0.0:
        return (v * 255, v * 255, v * 255)
    i = int(h * 6.0)
    f = (h * 6.0) - i
    p = v * (1.0 - s)
    q = v * (1.0 - s * f)
    t = v * (1.0 - s * (1.0 - f))
    i = i % 6
    if i == 0:
        return (v * 255, t * 255, p * 255)
    if i == 1:
        return (q * 255, v * 255, p * 255)
    if i == 2:
        return (p * 255, v * 255, t * 255)
    if i == 3:
        return (p * 255, q * 255, v * 255)
    if i == 4:
        return (t * 255, p * 255, v * 255)
    if i == 5:
        return (v * 255, p * 255, q * 255)

def play_tone(frequency, duration):
    if frequency == 0:
        buzzer.duty(0)
    else:
        buzzer.freq(frequency)
        buzzer.duty(512)
    time.sleep_ms(duration)
    buzzer.duty(0)

def birthday():
    tones = [
        (294, 250),  # D4
        (440, 250),  # A4
        (392, 250),  # G4
        (532, 250),  # C5
        (494, 250),  # B4
        (392, 250),  # G4
        (440, 250),  # A4
        (392, 250),   # G4
        (392, 250),  # G4
        (587, 250),  # D5
        (532, 250),  # C5  
        (392, 250),  # G4
        (784, 250), # G5
        (659, 250),  # E5
        (532, 250),  # C5  
        (494, 250),  # B4
        (440, 250),  # A4
        (698, 250),  # F5
        (659, 250),  # E5
        (532, 250),  # C5  
        (587, 250),  # D5
        (532, 500),  # C5-长时
        (0, 0),      # 关闭蜂鸣器
    ]
    for freq, dur in tones:
        play_tone(freq, dur)
        time.sleep_ms(50)

while True:
    if uart.any():
        command = uart.read(1)
        if command:
            cmd = ord(command)
            print("执行命令:", cmd) 
            
            if cmd == 11:
                birthday()
            elif cmd == 12:
                play_tone(0, 0)
            elif cmd == 13:
                color_wipe((255, 0, 0), 50)
            elif cmd == 14:
                color_wipe((0, 0, 0), 50)
            elif cmd == 15:
                color_wipe((0, 255, 0), 50)
            elif cmd == 16:
                color_wipe((0, 0, 0), 50)
            elif cmd == 17:
                color_wipe((0, 0, 255), 50)
            elif cmd == 18:
                color_wipe((0, 0, 0), 50)
            elif cmd == 36:
                theater_chase_rainbow(50)
            elif cmd == 37:
                color_wipe((0, 0, 0), 50)
            elif cmd == 38:
                play_tone(784, 250)
            elif cmd == 39:
                play_tone(0, 0)
            
            # 回声命令（可选）
            uart.write(str(cmd))
```
#### 15.6 实验结果

按照接线图接好线，将 ESP32 主控板通过Micro USB数据线与计算机相连供电，外接电源供电，然后单击按钮![](media/1305.png)，示例代码开始执行。

![](media/AB1.png)

示例代码开始执行之后，可以通过智能语音模块来控制无源蜂鸣器和SK6812RGB灯。

对着智能语音模块上的麦克风，使用唤醒词 “你好，小智” 或 “小智小智” 来唤醒智能语音模块，同时喇叭播放回复语 “有什么可以帮到您”；

智能语音模块唤醒后，对着麦克风说：“播放音乐” 等命令词时，喇叭播放对应的回复语 “已为您播放音乐”，同时蜂鸣器播放音乐；

对着麦克风说：“关闭音乐” 等命令词时，喇叭播放对应的回复语 “已为您停止音乐”，同时蜂鸣器停止播放音乐；

对着麦克风说：“打开红灯” 等命令词时，喇叭播放对应的回复语 “已为您打开红灯”，同时SK6812灯亮红色灯；

对着麦克风说：“关闭红灯” 等命令词时，喇叭播放对应的回复语 “已为您关闭红灯”，同时SK6812灯熄灭；

对着麦克风说：“打开绿灯” 等命令词时，喇叭播放对应的回复语 “已为您打开绿灯”，同时SK6812灯亮绿色灯；

对着麦克风说：“关闭绿灯” 等命令词时，喇叭播放对应的回复语 “已为您关闭绿灯”，同时SK6812灯熄灭；

对着麦克风说：“打开蓝灯” 等命令词时，喇叭播放对应的回复语 “已为您打开蓝灯”，同时SK6812灯亮蓝色灯；

对着麦克风说：“关闭蓝灯” 等命令词时，喇叭播放对应的回复语 “已为您关闭蓝灯”，同时SK6812灯熄灭；

对着麦克风说：“打开彩灯” 等命令词时，喇叭播放对应的回复语 “已为您打开彩灯”，同时SK6812灯亮彩色灯；

对着麦克风说：“关闭彩灯” 等命令词时，喇叭播放对应的回复语 “已为您关闭彩灯”，同时SK6812灯熄灭；

对着麦克风说：“打开蜂鸣器” 或 “蜂鸣器开始鸣叫”等命令词时，喇叭播放对应的回复语 “已打开蜂鸣器”，同时蜂鸣器开始鸣叫；

对着麦克风说：“关闭蜂鸣器” 或 “蜂鸣器停止鸣叫” 等命令词时，喇叭播放对应的回复语 “已关闭蜂鸣器”，同时蜂鸣器停止鸣叫。

![Img](../../media/image-15.gif)

单击![](media/1311.png)“停止/启动后端进程”退出程序。
