FireBeetle 给万用表增加语音功能
万用表是电子工程师最常用的调试工具。一些情况下,使用者只能专注于表笔本身而没有机会抬头去看读数,针对这种情况,这次使用 FireBeetle 来改造胜利86B万用表,给它添加一个语音功能。胜利 86B 这款万用表的特别之处在于带有 USB 接口,安装驱动程序和上位机程序之后可以在电脑上直接查看测量结果。这次的作品,就是通过 USB Host 来实现读取万用表发送过来的数据,然后解析之后通过语音模块将测量结果通过语音播报出来。硬件部分主要使用了如下三个元件:1. FireBeetle ,这次仍然使用基于 ESP32 的 FireBeetle 模块;
2. USB Host Shield,具体设计可以在这个贴子 https://mc.dfrobot.com.cn/thread-309553-1-1.html看到;
3. Gravity: 中英文语音合成模块(https://www.dfrobot.com.cn/goods-3014.html)
接下来,首先进行硬件设计。关于 USB Host Shield 的设计可以在前面提供的链接中看到。这次着重介绍用于三个模块彼此连接的底板,电路图如下,可以看到只有连接器件,并没有功能性元件。板子上有一个 USB 公头,可以用于供电,当然也可以直接通过 FireBeetle 上面的 USB 接口来为整个系统供电。途中 P1 是用于连接出发开关的接头,这次设计使用踏板作为开关触发语音;语音模块是通过 UART来和 FireBeetle 进行通讯的,使用 Serial2。
PCB 设计如下:
成品PCB 和安装之后的照片如下:
上面就是硬件设计的相关内容,接下来讲讲述软件部分。首先介绍如何从Victor86B 获得信号,前面提到它带有 USB 接口,从PC端查询 VID 和 PID 可以得知,内置了一个 CP2102 的串口芯片,因此,首要问题是 USB Host 如何同 CP2102进行通讯。在 https://github.com/henla464/USB_Host_Shield_Library_2.0 这里可以找到一个 USB Host 支持 CP2102 的代码。这样就能够获得Victor86B 发出的数据。接下来的问题是收到数据解析的问题,经过研究总结如下:
偏移位说明
BYTE0BIT高四位始终为1
BIT当前测量为交流(ACV:交流电压 ACA:交流电流)
BIT当前测量模式为直流(DCV:直流电压DCA:直流电流)
BIT当前为自动量程(AUTO)实验确定一下
BITUSB通讯打开(RS232)
BYTE1BIT高四位始终为2
BIT3正负号
BIT2千位数码管数值Bit6
BIT1千位数码管数值Bit5
BIT0千位数码管数值Bit4
BYTE2BIT高四位始终为3
BIT3千位数码管数值Bit3
BIT2千位数码管数值Bit2
BIT1千位数码管数值Bit1
BIT0千位数码管数值Bit0
BYTE3BIT高四位始终为4
BIT3百位数码管前面的小数点
BIT2百位数码管数值Bit6
BIT1百位数码管数值Bit5
BIT0百位数码管数值Bit4
BYTE4BIT高四位始终为5
BIT3百位数码管数值Bit3
BIT2百位数码管数值Bit2
BIT1百位数码管数值Bit1
BIT0百位数码管数值Bit0
BYTE5BIT高四位始终为6
BIT3十位数码管前面的小数点
BIT2十位数码管数值Bit6
BIT1十位数码管数值Bit5
BIT0十位数码管数值Bit4
BYTE6BIT高四位始终为7
BIT3十位数码管数值Bit3
BIT2十位数码管数值Bit2
BIT1十位数码管数值Bit1
BIT0十位数码管数值Bit0
BYTE7BIT高四位始终为8
BIT3个位数码管前面的小数点
BIT2个位数码管数值Bit6
BIT1个位数码管数值Bit5
BIT0个位数码管数值Bit4
BYTE8BIT高四位始终为9
BIT3个位数码管数值Bit3
BIT2个位数码管数值Bit2
BIT1个位数码管数值Bit1
BIT0个位数码管数值Bit0
BYTE9BIT高四位始终为0xA
BIT字符u(电流、电容数值下有效)
BIT字符n(只在电容数值下有效)
BIT字符K (频率、电阻数值下有效)
BIT二极管符号
BYTE10BIT高四位始终为0xB
BITm(电流数值下有效)
BIT占空比,单位是%(DUTY)
BITM(频率、电阻数值下有效)
BITBEEP
BYTE11BIT高四位始终为0xC
BIT当前读数为电容,显示符号F
BIT当前读数为电阻,显示符号Ω
BIT当前读数为相对测量值(REF)
BIT数据保持(HOLD)
BYTE12BIT高四位始终为0xD
BIT当前读数为电流,单位是 A
BIT当前读数为电压,单位是V
BIT当前读数为频率,单位 Hz
BIT当前电池欠压(BAT)
BYTE13BIT高四位始终为0xE
BIT保留未使用(确认)
BIT当前读数为电压,单位是 mV
BIT当前读数为温度,单位是 ℃
BIT保留未使用
结合实际数据进行解说,例如,Victor86B 发出的一组数据如下:
位置000102030405060708090A0B0C0D
数据17273D475D677D8F9EA0B8C0D4E8
Victor86B 上用于显示数据的数码管段位如下:
例如,实际数据上的Byte1,2分别为0x27和 0x3D,对于用户来说有效数据是 0x7D, 转化为二进制之后是 0x0111 1101 ,对应在上面数码管上,可以看到 Bit0/2/3/4/5/6 是点亮的,因此,用户看到的是0。同样的,百位十位都是0.
Byte7, Byte8给出的值是 0xFE 对应二进制位 0x1111 1110,用上述方法计算点亮值为6,因为 Bit7 为1,所以还要点亮最前的小数点 因此,前面完整数值是000.6.继续查看 Byte0xA Bit3 表示 m,Byte0xCBit2 表示 mV ,因此上述数值完整含义为 000.6mV。接下来就可以根据上述知识编写代码。特别需要注意的是:USBHost 无法保证每次完整收取指定长度的数据,比如,前面提到 Victor 86B 每次有效数据是14Bytes,但是使用 cp210x.RcvData() 函数有可能只接收到6Bytes,因此需要有一个拼接动作,只有接收到 14Bytes之后才进行解析。这个过程的流程图如下:
接下来介绍语音输出,首先需要注意的是这次使用串口,需要将 Gravity中英文语音合成模块上的开关波动到 UART位置。汉字是 Unicode 编码,每一个字占用 3Bytes。、在文件头部引用库#include "DFRobot_SpeechSynthesis.h"再声明一个对象DFRobot_SpeechSynthesis_UART ss;之后就可以使用 ss.speak(Buffer); 播放Buffer 中定义的中英文字符串。此外,还有一个需要注意的是:这个DFRobot_SpeechSynthesis库默认是同步播放。意思是调用播放函数后会处于这个函数中直到语音播放完成。这就造成了 USB 相关函数被阻挡,USB消息无法及时处理的问题。因此,会出现工作中 ESP32重启的问题。为了解决这个问题,我修改了 DFRobot_SpeechSynthesis 库,去掉了void DFRobot_SpeechSynthesis::wait() 函数的等待代码。这样即可将Speak 从同步修改为异步,当然响应的还有一个延时操作,保证不会出现一段语音没有播放完成就转去播放另外语音的情况。最终照片如下:
完整程序下载
支持 CP210X 的USB Host Library
修改后的的语音合成库
{:5_116:}语音合成喜欢
页:
[1]