SU-03T语音模块实战:如何用单片机+温度传感器打造智能语音播报系统(附完整代码)
最近在捣鼓一个智能家居的小玩意儿,想给家里的鱼缸做个温度监控,还得能“说话”的那种。市面上成品要么太贵,要么功能死板,索性自己动手。核心就是让一个语音模块听懂我的问题,然后去问单片机要温度数据,再播报出来。折腾了一圈,发现SU-03T这个国产语音识别模块性价比真不错,配合常见的单片机(比如STM32、Arduino)和DS18B20这类温度传感器,就能搭出一个挺像样的系统。整个过程涉及硬件连线、串口协议“对话”、语音触发逻辑设计,虽然有些细节需要注意,但整体思路清晰后,实现起来并不复杂。这篇文章,我就把从零搭建这个智能语音温度播报系统的完整过程、踩过的坑以及可以直接用的代码,分享给同样喜欢动手的硬件开发者和物联网爱好者。
1. 项目核心:理解系统架构与通信逻辑
在动手焊接和写代码之前,我们得先搞清楚这个系统里几个“角色”是怎么“对话”的。这决定了我们后续硬件连接和软件编写的方向。
整个系统的核心工作流程,可以想象成一次简短的问答。用户说出预设的唤醒词和命令词(例如:“小智小智,当前温度多少?”),SU-03T语音模块负责“听见”并理解这句话。一旦识别成功,它不会自己去测温,而是通过串口(UART)向单片机(MCU)发送一个特定的指令代码,比如0xA1。这个代码就像是一封短信,内容是:“嘿,单片机,用户想知道温度,快把数据发给我。”
单片机一直在监听串口。收到0xA1后,它立刻去询问连接在其GPIO引脚上的温度传感器(如DS18B20),读取当前的温度数值。获取到数据(假设是25.5℃)后,单片机需要按照事先和SU-03T约定好的数据格式,将温度值封装成一帧数据,通过串口发回给SU-03T。
最后,SU-03T收到这帧包含温度数据的信息,调用其内置的语音合成(TTS)功能,将数字“25.5”转换为自然流畅的语音播报出来:“当前温度为二十五点五摄氏度”。至此,一次完整的交互完成。
注意:SU-03T模块本身集成了语音识别(ASR)和语音合成(TTS)功能,我们无需在单片机上处理复杂的音频算法,大大降低了开发难度。我们的工作重心是正确配置SU-03T的识别词条和串口响应逻辑,以及编写单片机端的数据采集与串口通信程序。
这里的关键在于双重的串口通信协议:
- SU-03T -> 单片机:语音触发指令。格式简单,通常就是一个字节或几个字节的命令码。
- 单片机 -> SU-03T:传感器数据回传。格式需要严格遵守SU-03T“串口输入触发”功能所要求的协议,通常包含帧头、地址码、数据、帧尾等部分。
理解了这个“一问一答,中转上报”的架构,后面的硬件连接和软件配置就都有了明确的目标。
2. 硬件准备与电路连接
工欲善其事,必先利其器。我们先来清点一下需要的硬件,并把它们正确地连接起来。
所需硬件清单:
- SU-03T语音识别模块x1
- 单片机开发板x1(本文以常见的Arduino Uno为例,STM32等平台原理相通)
- 数字温度传感器x1(推荐使用单总线DS18B20,精度高、接口简单)
- USB转TTL串口模块x1(用于配置SU-03T)
- 杜邦线若干
- 麦克风与扬声器(或直接使用SU-03T的集成版本)
- 电源(确保能为所有模块提供稳定电压,SU-03T和Arduino通常需要5V)
电路连接示意图与说明:
连接分为两个主要部分:SU-03T与单片机的通信链路,以及单片机与温度传感器的数据链路。
SU-03T与Arduino的串口连接:SU-03T的
TX引脚应连接到Arduino的RX(引脚0),RX引脚连接到Arduino的TX(引脚1)。切记,在连接和上传代码时,如果使用了Arduino的硬件串口(Serial),需要暂时断开这两根线,避免冲突。也可以使用SoftwareSerial库指定其他引脚作为软串口与SU-03T通信,这样更灵活。此外,还需连接VCC(5V) 和GND。DS18B20与Arduino的连接:DS18B20的三个引脚分别为:
VDD(电源正极)、DQ(数据线)、GND(电源负极)。将VDD接至5V,GND接至地。DQ引脚接至Arduino的一个数字引脚(例如引脚2),同时必须在DQ与5V之间连接一个4.7kΩ的上拉电阻,这是单总线通信正常工作的必要条件。
为了方便查阅,我将核心连接关系整理成下表:
| 设备/模块 | 引脚 | 连接至 | 说明 |
|---|---|---|---|
| SU-03T | TX | Arduino RX (Pin 0) | 发送数据给单片机 |
| RX | Arduino TX (Pin 1) | 接收来自单片机的数据 | |
| VCC | 5V | 电源正极 | |
| GND | GND | 电源地 | |
| DS18B20 | VDD | 5V | 电源正极 |
| DQ | Arduino Digital Pin 2 | 数据线,需加4.7kΩ上拉至5V | |
| GND | GND | 电源地 |
连接完成后,建议先分别测试各个模块是否工作正常:给Arduino上电看指示灯,用串口监视器测试SU-03T的通信,用单独的示例代码读取DS18B20温度。确保基础功能无误,再进行整合。
3. 配置SU-03T:在智能公元平台创建语音技能
SU-03T的强大之处在于其配套的智能公元在线开发平台。我们不需要编写复杂的语音识别模型,而是通过图形化界面配置命令词和响应动作。这是项目中最关键的一步。
注册与创建产品:访问智能公元官网,注册账号。在“产品开发”中创建一个新产品,选择SU-03T型号。你会获得一个唯一的Product ID,后续需要烧录到模块中。
设计语音交互逻辑:在我们的温度播报系统中,需要配置两个核心的“触发-响应”行为:
行为一:语音命令触发,向单片机发送指令。
- 触发类型:选择“命令词触发”。在命令词列表中添加你想要的唤醒词和问句,例如“当前温度”、“温度多少度”等。
- 响应动作:选择“串口输出”。这里就是配置当识别到上述命令词后,SU-03T主动从TX引脚发送什么数据给单片机。我们将其设置为一个简单的十六进制命令,比如
A1。这意味着,当你说“温度多少度”,SU-03T会通过串口发送0xA1给Arduino。
行为二:串口输入触发,播报收到的温度数据。
- 触发类型:选择“串口输入触发”。这是配置SU-03T如何解读从单片机发来的数据帧。
- 协议配置:这是最容易出错的地方。平台通常要求你定义数据帧结构。一个常见且简单的自定义协议格式如下:
帧头 (AA 55) | 信息号/地址码 (01) | 数据区 (例如 1A 表示26度) | 帧尾 (55 AA) - 信息号的作用:
信息号(或叫地址码)至关重要。假设你的系统未来还要播报湿度、光照强度,那么单片机发送湿度数据时,信息号可以设为02,光照设为03。SU-03T根据不同的信息号,可以触发不同的播报内容(例如“当前湿度是百分之六十”)。在我们的单温度系统中,可以固定设为01。 - 响应动作:关联到“语音播报”。你需要设置播报的模板,例如“当前温度为
[数据区]度”。平台会自动将数据区的内容(十六进制1A)转换为十进制数字(26)并合成语音。
生成固件与烧录:配置完成后,平台会生成一个最终的固件文件(.bin或.voice)。使用USB转TTL模块连接SU-03T的烧录口(注意不是通信串口),通过专用的烧录工具将这个固件烧录到模块中。烧录时,确保模块进入烧录模式(通常需要按住某个按键再上电)。
提示:在智能公元平台上仔细检查“串口输入触发”的数据帧格式定义,务必与你后续单片机程序中发送的数据格式完全一致,包括字节顺序、帧头帧尾。一个字节的差异都会导致SU-03T无法正确触发播报。
4. 单片机端程序开发:数据采集与协议封装
SU-03T配置好后,就变成了一个“黑盒”,它只按照我们设定的规则收发数据。接下来,我们要让单片机(Arduino)扮演好“数据采集员”和“协议打包员”的角色。
程序的核心任务有两个:
- 持续监听串口,当收到特定指令(
0xA1)时,触发温度读取。 - 读取DS18B20的温度值,并按照SU-03T要求的格式,封装成一帧完整的数据发送回去。
下面是一个基于Arduino的示例代码框架,包含了详细的注释:
#include <OneWire.h> #include <DallasTemperature.h> // 定义DS18B20数据引脚 #define ONE_WIRE_BUS 2 // 初始化单总线和DS18B20库 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); // 定义SU-03T通信的协议常量 const byte FRAME_HEADER[2] = {0xAA, 0x55}; const byte FRAME_TRAILER[2] = {0x55, 0xAA}; const byte INFO_CODE = 0x01; // 信息号,与SU-03T配置中的“信息号”对应 void setup() { Serial.begin(9600); // 初始化串口,波特率需与SU-03T匹配(通常9600) sensors.begin(); // 初始化温度传感器库 } void loop() { // 任务1:监听串口指令 if (Serial.available() > 0) { byte incomingByte = Serial.read(); // 读取一个字节 if (incomingByte == 0xA1) { // 判断是否为请求温度的指令 getAndSendTemperature(); // 如果是,则执行温度获取与发送函数 } // 可以在此添加其他指令的判断,如0xA2请求湿度等 } // 其他主循环任务... delay(100); } // 任务2:获取温度并封装发送 void getAndSendTemperature() { sensors.requestTemperatures(); // 向所有传感器发送温度转换请求 float tempC = sensors.getTempCByIndex(0); // 获取第一个传感器的摄氏温度值 // 将浮点数温度转换为整数(例如25.6°C -> 256,即0x0100) // 根据SU-03T数据区长度定义,可能需要发送两个字节 int tempInt = (int)(tempC * 10); // 放大10倍保留一位小数 byte dataHigh = (tempInt >> 8) & 0xFF; // 高字节 byte dataLow = tempInt & 0xFF; // 低字节 // 按照协议格式,通过串口发送完整数据帧 Serial.write(FRAME_HEADER, 2); // 发送帧头 Serial.write(INFO_CODE); // 发送信息号 Serial.write(dataHigh); // 发送温度数据高字节 Serial.write(dataLow); // 发送温度数据低字节 Serial.write(FRAME_TRAILER, 2); // 发送帧尾 // 可选:在串口监视器中打印调试信息 // Serial.print("Temperature sent: "); // Serial.println(tempC); }代码关键点解析:
- 指令判断:
loop()函数中不断检查串口是否有数据,并判断是否为0xA1。这里使用了最简单的单字节判断,实际应用中可以根据需要扩展为多字节的复杂指令。 - 温度读取:使用了成熟的
DallasTemperature库来操作DS18B20,简化了单总线通信的时序控制。 - 数据封装:这是与SU-03T通信成败的关键。
getAndSendTemperature()函数严格按照在智能公元平台上定义的格式组装数据帧:AA 55 | 01 | 温度高字节 | 温度低字节 | 55 AA。务必确保字节顺序、长度与平台配置绝对一致。 - 数据类型转换:温度值从浮点数转换为整数,再拆分为高低字节进行传输,避免了浮点数传输的复杂性和歧义。
将这段代码编译上传到Arduino后,整个系统的软件部分就准备就绪了。记得上传代码时,断开Arduino与SU-03T的TX/RX连接,上传完成后再接回去。
5. 系统联调与常见问题排查
硬件连好了,SU-03T固件烧录了,单片机程序也上传了,现在到了最激动人心也最可能让人头疼的环节——系统联调。
标准调试流程:
- 独立供电:确保所有模块稳定上电。
- 语音触发测试:对着麦克风清晰说出命令词“当前温度多少度”。观察SU-03T的指示灯是否有识别反馈(例如闪烁)。
- 逻辑分析仪或串口监听:这是最有效的调试手段。在SU-03T的TX线与单片机RX线之间,或者单片机TX线与SU-03T的RX线之间,接入一个逻辑分析仪或使用另一个USB转TTL模块监听,可以清晰地看到线上实际传输的每一个字节。
- 当你说话后,应该看到SU-03T发出
A1。 - 紧接着,应该看到单片机回复一帧6字节的数据
AA 55 01 XX XX 55 AA(XX为温度数据)。
- 当你说话后,应该看到SU-03T发出
- 结果验证:如果数据流看起来完全正确,但SU-03T没有播报,问题很可能出在SU-03T的“串口输入触发”配置上,特别是数据区解析部分。如果播报的温度值错误,则是单片机端数据转换或SU-03T数据区格式映射有误。
常见问题与解决方案:
问题:SU-03T毫无反应,指示灯不亮。
- 排查:检查电源电压和电流是否足够。测量VCC和GND之间电压是否为稳定的5V。确认模块是否已成功烧录固件。
问题:SU-03T指示灯亮,但说命令词不识别。
- 排查:确认麦克风连接正常。在智能公元平台检查命令词是否录入成功、是否过于生僻或音节太短。在安静环境下,距离适中(30-50厘米)重新尝试。检查模块是否进入了唤醒状态(有些模块需要先说出唤醒词)。
问题:SU-03T识别成功(指示灯变化),但单片机没反应。
- 排查:使用串口监听工具,检查SU-03T的TX脚是否有
0xA1发出。如果没有,检查智能公元平台上“串口输出”动作配置是否正确。如果有,检查单片机端的RX线连接是否牢固,单片机串口初始化波特率是否与SU-03T发送波特率一致(均为9600)。
- 排查:使用串口监听工具,检查SU-03T的TX脚是否有
问题:单片机收到了
0xA1,但SU-03T没有播报温度。- 排查:监听单片机的TX脚输出。确认其发送的数据帧格式、帧头帧尾、信息号每一个字节都与智能公元平台上“串口输入触发”中定义的协议完全匹配。这是最高发的错误点。特别注意字节顺序(大端/小端)。
问题:SU-03T播报的温度值完全错误,比如“当前温度为一百二十八度”。
- 排查:这通常是数据解析错误。检查单片机程序中温度值转换为字节的过程,以及SU-03T平台上“数据区”的设置。例如,单片机发送了
0x80(十进制128),而SU-03T直接将其作为十进制数播报。需要确认SU-03T的数据区类型(如unsigned char, int)和解析方式是否与发送的数据格式对应。
- 排查:这通常是数据解析错误。检查单片机程序中温度值转换为字节的过程,以及SU-03T平台上“数据区”的设置。例如,单片机发送了
调试过程就是不断假设、验证、缩小问题范围的过程。保持耐心,善用工具,大部分问题都能迎刃而解。
当你说出“温度多少”,听到扬声器里传来准确的温度播报时,那种成就感是购买任何成品都无法替代的。这个项目麻雀虽小,五脏俱全,涵盖了物联网设备典型的感知、通信、交互环节。你可以在此基础上轻松扩展,比如增加湿度传感器,修改命令词为“室内环境怎么样”,让SU-03T播报“当前温度二十五度,湿度百分之六十”;或者将单片机换成ESP8266,加入Wi-Fi,把温度数据同步到手机App。SU-03T的灵活性和智能公元平台的便捷性,为你的创意提供了坚实的起点。