[分享] 【Gravity: 中英文语音合成模块V2.0】04 播报环境信息

CoderX9527   2026-3-11 14:56 楼主
 

1. 背景
1.1 硬件
1.2 实物连接图
2. 代码
2.1 流程图
2.2 实际效果
3.总结

 

1.背景
Teensy4.1 通过 UART 驱动 DFR0760 语音合成器。
wd_145208jznk7uv07giingvy.png
1.1 硬件
Gravity 语音合成器配置,拨码开关从 I2C 拨到 UART。

Teensy4.1 语音合成器
(UART 接口)
SEK-SEN66传感器
(I2C 接口)
UART8_TX (Io35) RX --
UART8_RX (IO34) TX --
I2C1_SDA (IO18) -- SDA
I2C1_SCL (IO19) -- SCL


1.2 实物连接图
wd_145208jel63bzl3mtg3p6e.png

 

2.代码

Teensy4.1 基于 Arduino 框架开发的代码,先初始化 SEK-SEN66,然后初始化语音合成器,最后每隔1秒钟读取一次传感器数据,当传感器数据有效时每隔5秒钟语音播报一次温湿度和二氧化碳浓度信息。
增加了一点小趣味,代码中改变音效,例如 [e3] 是机器人音效,[e0] 是默认女声。
 
/**
 * [url=home.php?mod=space&uid=1307177]@File[/url] main.cpp
 * [url=home.php?mod=space&uid=1315547]@author[/url] LinTeX9527 (lintex9527@yeah.net)
 * [url=home.php?mod=space&uid=159083]@brief[/url] * [url=home.php?mod=space&uid=252314]@version[/url] 0.1
 * [url=home.php?mod=space&uid=311857]@date[/url] 2026-03-10
 *
 * @copyright Copyright (c) 2026
 *
 */

#include <Arduino.h>
#include <SensirionI2cSen66.h>
#include <Wire.h>
#include "DFRobot_SpeechSynthesis_V2.h"

/* SEK-SEN66 Sensor ------------------------------------------------------------*/

// macro definitions
// make sure that we use the proper definition of NO_ERROR
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0

/**
 * @brief 传感器无效的数据值
 * @{
 */
#define INVALID_PM1P0 (6553.50f)
#define INVALID_PM2P5 (6553.50f)
#define INVALID_PM4P0 (6553.50f)
#define INVALID_PM10P0 (6553.50f)
#define INVALID_NOX (3276.70f)
#define INVALID_CO2 (65535)
/**
 * @}
 */

SensirionI2cSen66 sen66_sensor;

static char errorMessage[64];
static int16_t error;

/* Gravity Speech ------------------------------------------------------------*/

#define ttsSerial Serial8 /* TX8--35, RX8--34 */

DFRobot_SpeechSynthesis_UART tts;

int effect_mode = 0; // 语音合成器音效

/* 局部函数 -------------------------------------------------------------------*/

void sen66_init(void)
{
    Wire.begin();
    sen66_sensor.begin(Wire, SEN66_I2C_ADDR_6B);

    error = sen66_sensor.deviceReset();
    if (error != NO_ERROR)
    {
        Serial.print("Error trying to execute deviceReset(): ");
        errorToString(error, errorMessage, sizeof errorMessage);
        Serial.println(errorMessage);
        return;
    }
    delay(1200);
    int8_t serialNumber[32] = {0};
    error = sen66_sensor.getSerialNumber(serialNumber, 32);
    if (error != NO_ERROR)
    {
        Serial.print("Error trying to execute getSerialNumber(): ");
        errorToString(error, errorMessage, sizeof errorMessage);
        Serial.println(errorMessage);
        return;
    }
    Serial.print("serialNumber: ");
    Serial.print((const char *)serialNumber);
    Serial.println();
    error = sen66_sensor.startContinuousMeasurement();
    if (error != NO_ERROR)
    {
        Serial.print("Error trying to execute startContinuousMeasurement(): ");
        errorToString(error, errorMessage, sizeof errorMessage);
        Serial.println(errorMessage);
        return;
    }
}

void tts_init(void)
{
    ttsSerial.begin(115200);
    tts.begin(ttsSerial);
    tts.setVolume(1);
    tts.setSpeed(5);
    tts.setTone(5);
    tts.setEnglishPron(tts.eWord);
}

void setup()
{
    Serial.begin(115200);
    while (!Serial)
    {
        delay(100);
    }

    sen66_init();
    tts_init();
}

unsigned long lastReadTime = 0;
unsigned long lastSpeechTime = 0;

void loop()
{
    unsigned long currentTime = millis();

    // 每隔1秒读取一次传感器数据并打印
    if (currentTime - lastReadTime >= 1000)
    {
        float mass_pm1p0 = 0.0;
        float mass_pm2p5 = 0.0;
        float mass_pm4p0 = 0.0;
        float mass_pm10p0 = 0.0;
        float humidity = 0.0;
        float temperature = 0.0;
        float vocIndex = 0.0;
        float noxIndex = 0.0;
        uint16_t co2 = 0;

        error = sen66_sensor.readMeasuredValues(
            mass_pm1p0, mass_pm2p5, mass_pm4p0,
            mass_pm10p0, humidity, temperature, vocIndex, noxIndex,
            co2);
        if (error != NO_ERROR)
        {
            Serial.print("Error trying to execute readMeasuredValues(): ");
            errorToString(error, errorMessage, sizeof errorMessage);
            Serial.println(errorMessage);
            lastReadTime = currentTime; // 更新时间以避免重复错误
            return;
        }

        Serial.print("mass_pm1p0: ");
        Serial.print(mass_pm1p0);
        Serial.print("\t");

        Serial.print("mass_pm2p5: ");
        Serial.print(mass_pm2p5);
        Serial.print("\t");

        Serial.print("mass_pm4p0: ");
        Serial.print(mass_pm4p0);
        Serial.print("\t");

        Serial.print("mass_pm10p0: ");
        Serial.print(mass_pm10p0);
        Serial.print("\t");

        Serial.print("humidity: ");
        Serial.print(humidity);
        Serial.print("  \t");

        Serial.print("temperature: ");
        Serial.print(temperature);
        Serial.print("\t");

        Serial.print("vocIndex: ");
        Serial.print(vocIndex);
        Serial.print("\t");

        Serial.print("noxIndex: ");
        Serial.print(noxIndex);
        Serial.print("  \t");

        Serial.print("co2: ");
        Serial.println(co2);

        lastReadTime = currentTime;

        // 检查数据是否有效
        bool isValidData = true;
        if ((mass_pm1p0 == INVALID_PM1P0) ||
            (mass_pm2p5 == INVALID_PM2P5) ||
            (mass_pm4p0 == INVALID_PM4P0) ||
            (mass_pm10p0 == INVALID_PM10P0) ||
            (noxIndex == INVALID_NOX) ||
            (co2 == INVALID_CO2))
        {
            isValidData = false;
        }

        // 每隔5秒语音播报一次有效数据
        if (currentTime - lastSpeechTime >= 5000 && isValidData)
        {

            // TTS语音播报
            char speechBuffer[256];
            snprintf(speechBuffer, sizeof(speechBuffer),
                     "温度 %.1f 摄氏度,湿度 %.1f%%,二氧化碳浓度 %u PPM",
                     temperature, humidity, co2);
            tts.speak(speechBuffer);

            // 切换音效
            effect_mode++;
            if (effect_mode > 6) {
                effect_mode = 0;
            }
            memset(speechBuffer, 0, sizeof(speechBuffer));
            snprintf(speechBuffer, sizeof(speechBuffer), "[e%d]", effect_mode);
            tts.speak(speechBuffer);

            // 等待TTS播报完成,避免连续播报冲突
            delay(2000); // 根据语音长度调整延迟时间

            lastSpeechTime = currentTime; // 只有播报成功后才更新时间
        }
    }

    // 让处理器处理其他任务
    yield();
}

 


2.1 流程图
wd_145208c91nonqhzdytq1t1.png
2.2 实际效果
视频演示如下。
VID_20260311_121335

 
 
3.总结
  1. 语音合成器供电电压是3.3V~5V。一般我先用 3.3V 供电,测试没问题。但是接入了SEK-SEN66 传感器之后,二者都使用 3.3V 供电,语音播报出现了问题,播报一段语音后卡住,且可能导致主控复位;
  2. 后来检查了下,SEN66 平均电流90mA,而语音合成器工作电流160mA,而 Teensy4.1 的 3.3V 引脚供电能力理论上可以提供250mA~300mA的电流,由于核心在 600MHz 运行时大约消耗100mA,因此还有 150mA~200mA 的余量供给传感器、显示屏或者无线模块;
  3. 我把语音合成器接到 5V 引脚供电,解决了问题。SEK-SEN66 传感器读数数据正常,Gravity 语音播报正常;

点个灯吧

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复