天空'之城头像
004基于语音识别的智能家居本地控制系统封面图

004基于语音识别的智能家居本地控制系统

目录

一、这个毕设是干什么的?

二、它解决什么问题?

三、核心功能?

四、用到哪些技术?

五、系统是怎么工作的?

六、大概怎么做?

七、硬件清单与接线

1、硬件清单

2、接线表

八、核心器件原理简述

1、离线语音识别模块(SU-03T)

2、继电器(Relay)

3、DHT11 温湿度 / 光敏电阻

九、语音词条配置与串口协议

1、用智能公元工具配置词条(离线方案)

2、串口帧格式(以 SU-03T 为例)

十、开发环境搭建

十一、软件设计(.h / .c 多文件工程)

1、工程文件结构

2、config.h —— 全局配置

3、voice.h / voice.c —— 语音识别模块

4、relay.h / relay.c —— 继电器控制模块

5、sensor.h / sensor.c —— 环境传感器模块

6、display.h / display.c —— OLED 显示模块

7、main.c —— 主程序

十二、代码要点讲解

十三、功能测试与验收

十四、能给你什么启发?

十五、开题报告 & 答辩要点

1、开题报告可直接改用的表述

2、答辩常见问题(参考回答要点)


难度定位:★★★☆☆(中等新颖型)|适合:有基础、想做「交互新颖 + 离线不依赖云端」选题、想突出差异化的同学|预估周期:3~4 周

一、这个毕设是干什么的?

一句话:做一套不用联网、喊一句就能控制家里电器的本地智能语音控制系统。

再展开说:你在家里说「开灯」,顶灯就亮;说「关风扇」,风扇就停;说「打开插座」,插在上面的设备就通电。这套系统用 ESP32 主控 + 离线语音识别模块,识别你的语音指令后直接驱动多路继电器开关电器,整个过程不需要 WiFi、不需要云平台、不需要手机,完全本地完成。同时它还会监测环境(温湿度、光照),比如温度高了自动开风扇、天暗了自动开灯,实现设备间的本地联动。

二、它解决什么问题?

  • 不想用手机、不想联网操作 → 动嘴就能控制,符合日常直觉,老人小孩也会用;

  • 依赖云端不稳 → 家里断网也能用,语音识别在本地完成,稳定性强、响应快;

  • 晚上懒得摸黑找开关 → 一句话开灯;

  • 环境自动调节 → 天热自动开风扇、天暗自动开灯,不用手动,体现智能联动。

本质是:把「手动开关 / 手机遥控」升级成「语音交互 + 本地联动」,突出「更自然的人机交互」和「不依赖外网的本地智能」,这正是智能家居从「远程控制」走向「主动服务」的方向。

三、核心功能?

功能说明
离线语音控制说「开灯/关灯/开风扇/关风扇/开插座/关插座」等,识别后控制对应电器
多路继电器2~4 路独立控制灯具、风扇、插座,互不影响
本地设备联动温度高自动开风扇、光照暗自动开灯(无需联网)
环境监测温湿度、光照实时采集并本地显示
本地显示OLED 屏显示设备状态与环境数据
无需联网语音识别、设备控制全部本地完成,断网可用

四、用到哪些技术?

类别具体作用
主控ESP32处理语音指令、驱动继电器、采集环境
语音识别离线语音识别模块(SU-03T / LD3320)本地识别语音词条,输出指令帧
执行多路继电器模块控制灯具、风扇、插座通断电
传感器DHT11 温湿度、光敏电阻环境监测、触发本地联动
显示SSD1306 OLED 屏本地显示状态与环境数据
通信串口(UART)ESP32 与语音模块通信
开发Arduino IDE + C 语言编写烧录程序

五、系统是怎么工作的?

语音输入(“开灯”)
   ↓
离线语音识别模块(本地识别词条)
   ↓ 串口指令帧
ESP32 主控(解析指令 → 驱动对应继电器)
   ↓
灯具 / 风扇 / 插座通电
   ↑
环境传感器(温度高 → 自动开风扇;光暗 → 自动开灯)

一句话串起来:说话 → 语音模块本地识别 → 串口发指令帧 → ESP32 解析 → 控制继电器开关电器;同时环境传感器数据驱动本地联动。

这套「本地语音识别 + 串口指令 + 继电器执行 + 传感器联动」的架构,是所有语音/离线控制类毕设的通用骨架,也可改造成语音控制窗帘、门锁等。

六、大概怎么做?

  1. 买齐硬件(ESP32 + 语音识别模块 + 2~4 路继电器 + DHT11 + 光敏 + OLED);

  2. 用语音模块配套工具配置词条(如「开灯」「关灯」「开风扇」「关风扇」);

  3. 接线:语音模块 TX/RX 接 ESP32 串口,继电器 IN 接控制脚,传感器接 GPIO;

  4. 用 Arduino IDE 写代码:接收串口指令 → 解析 → 驱动继电器;读取环境数据 → 本地联动;

  5. 上电说「开灯」,观察灯亮;捂热传感器验证温度联动开风扇;

  6. 断网(不连 WiFi)测试,确认完全本地可用,链路跑通即完成。

核心难点在于「语音模块词条配置 + 串口指令帧解析」,其余是简单控制逻辑。下面逐步展开。

七、硬件清单与接线

1、硬件清单

器件型号/规格数量
主控板ESP32 DevKitC1
语音识别模块SU-03T(离线,可自定义词条)1
继电器模块5V 4 路(或 2 路)1
温湿度传感器DHT111
光照传感器光敏电阻模块1
OLED 显示屏SSD1306 128×64 (I2C)1
负载台灯 / 风扇 / 排插1~4
电源5V 适配器 / 充电宝1
面包板 + 杜邦线—若干

2、接线表

ESP32 引脚连接器件说明
GPIO16 (RX2)SU-03T TX语音模块发送 → ESP32 接收
GPIO17 (TX2)SU-03T RXESP32 发送 → 语音模块接收(可不接)
GPIO26继电器 IN1第 1 路(灯)
GPIO27继电器 IN2第 2 路(风扇)
GPIO14继电器 IN3第 3 路(插座)
GPIO12继电器 IN4第 4 路(备用)
GPIO4DHT11 数据脚 DATA单总线读取温湿度
GPIO34光敏模块 AOADC 读取光照(0~4095)
GPIO21OLED SDAI2C 数据线
GPIO22OLED SCLI2C 时钟线
5V继电器 VCC模块供电
GND所有器件地线必须共地

关键提醒:语音模块与 ESP32 通信要共地;继电器 VCC 接 5V,控制电器时注意安全(火线走 COM/NO)。SU-03T 默认 3.3V 电平,接 ESP32 的 3.3V。

八、核心器件原理简述

1、离线语音识别模块(SU-03T)

  • 本地语音识别芯片,不需联网,把语音词条提前「训练/配置」进模块,识别到就通过串口输出一帧指令;

  • 用厂商配套工具(如「智能公元」在线配置)添加词条(如「开灯」),生成固件烧录进模块,无需写复杂算法;

  • 识别结果以串口数据帧输出(典型帧如 FD 01 00 01 00 FF),ESP32 接收并解析帧里的词条序号即可;

  • 优点:完全离线、响应快、词条可自定义,是毕设里最省心又能突出交互的语音方案。

2、继电器(Relay)

  • 用一个小电流控制线圈吸合/释放触点,从而通断大电流的电器;

  • 常见低电平触发模块(IN 接地吸合),板上带指示灯;

  • 三根关键接线:COM(公共)、NO(常开)、NC(常闭),电器火线接 COM、另一端接 NO,吸合时通电;

  • 程序 digitalWrite 高/低电平即可开关。

3、DHT11 温湿度 / 光敏电阻

  • DHT11:单总线数字传感器,一根线读取 40bit 数据(含校验),无需 ADC;上电需稳定,两次读取间隔 ≥1 秒,读取失败返回 NaN 需判空;

  • 光敏电阻模块:光照越强阻值越小,经模块输出模拟电压,ADC 读数越小说明越亮;用于「光暗自动开灯」联动,阈值需实测标定。

九、语音词条配置与串口协议

1、用智能公元工具配置词条(离线方案)

  1. 打开 智能公元(SU-03T 官方配置平台,免费注册);

  2. 新建项目,选「离线方案」+ 语音识别,添加词条:

    • 唤醒词:小智小智

    • 指令词:开灯、关灯、开风扇、关风扇、打开插座、关闭插座

  3. 每个指令词对应一个「命令词编号」(如 01、02、03…),生成固件并烧录到 SU-03T;

  4. 模块识别到词条后,通过串口输出数据帧(如 FD 01 00 01 00 FF),倒数第 4 字节即词条序号,代码据此区分指令。

2、串口帧格式(以 SU-03T 为例)

帧内容含义
FD帧头
01帧长(可变)
00版本
01命令词编号(本帧为「开灯」)
00数据
FF帧尾

代码里只需校验帧头 FD、帧尾 FF,取出命令词编号,映射到对应继电器动作即可。

十、开发环境搭建

  1. 安装 Arduino IDE(建议 2.x);

  2. 添加 ESP32 板卡:文件 → 首选项 → 附加开发板管理器网址填入 https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 再在「工具 → 开发板 → 开发板管理器」搜索 esp32 安装;

  3. 安装库(工具 → 管理库):DHT sensor library、Adafruit SSD1306、Adafruit GFX;

  4. 选择开发板 ESP32 Dev Module,烧录失败时按住板载 BOOT 键重试。

十一、软件设计(.h / .c 多文件工程)

代码按功能拆分:头文件(.h)只放宏定义、结构体、函数声明,源文件(.c)放具体实现,职责清晰、符合正式工程规范。

1、工程文件结构

esp32_voice_home/
├── config.h      // 全局配置:引脚、继电器、阈值、词条映射(按需修改)
├── voice.h       // 语音识别模块声明
├── voice.c       // 串口接收 + 词条解析实现
├── relay.h       // 继电器模块声明
├── relay.c       // 多路继电器控制实现
├── sensor.h      // 传感器模块声明
├── sensor.c      // DHT11 温湿度 + 光敏采集实现
├── display.h     // OLED 显示模块声明
├── display.c     // OLED 显示实现
└── main.c        // 主程序:setup() / loop()

2、config.h —— 全局配置

#ifndef CONFIG_H
#define CONFIG_H
​
/* 继电器数量与控制引脚(低电平触发) */
#define RELAY_NUM      4
const int relayPin[RELAY_NUM] = {26, 27, 14, 12};
​
/* 环境传感器引脚 */
#define PIN_DHT        4
#define PIN_LIGHT      34        /* 光敏 ADC */
​
/* OLED (I2C) */
#define PIN_OLED_SDA   21
#define PIN_OLED_SCL   22
​
/* 语音模块串口 */
#define VOICE_UART     2         /* 使用 UART2: RX2=16, TX2=17 */
​
/* 本地联动阈值(建议实测标定) */
#define TEMP_AUTO_FAN  32.0f     /* 温度高于此值自动开风扇 */
#define LIGHT_AUTO_ON  2000      /* 光照 ADC 高于此值(暗)自动开灯 */
​
/* 词条编号 → 动作映射(与智能公元配置一致) */
#define CMD_LAMP_ON    1         /* 开灯 */
#define CMD_LAMP_OFF   2         /* 关灯 */
#define CMD_FAN_ON     3         /* 开风扇 */
#define CMD_FAN_OFF    4         /* 关风扇 */
#define CMD_SOCKET_ON  5         /* 打开插座 */
#define CMD_SOCKET_OFF 6         /* 关闭插座 */
​
#endif

3、voice.h / voice.c —— 语音识别模块

voice.h(声明):

#ifndef VOICE_H
#define VOICE_H
#include <stdbool.h>
​
void voice_init(void);       /* 初始化语音串口 */
int  voice_get_cmd(void);    /* 返回收到的词条编号,无指令返回 -1 */
#endif

voice.c(实现):

#include "voice.h"
#include "config.h"
#include <HardwareSerial.h>
​
static HardwareSerial voiceSer(2);  /* UART2 */
​
void voice_init(void) {
    voiceSer.begin(9600, SERIAL_8N1, 16, 17);  /* RX=16, TX=17, 波特率9600 */
}
​
/* 解析 SU-03T 数据帧,取出命令词编号 */
static int parseFrame(byte* buf, int len) {
    if (len < 6) return -1;                 /* 帧至少 6 字节 */
    if (buf[0] != 0xFD) return -1;          /* 校验帧头 */
    if (buf[len - 1] != 0xFF) return -1;    /* 校验帧尾 */
    return buf[3];                          /* 命令词编号 */
}
​
int voice_get_cmd(void) {
    static byte frame[16];
    static int  idx = 0;
​
    while (voiceSer.available()) {
        byte b = voiceSer.read();
        frame[idx++] = b;
​
        if (b == 0xFF) {                    /* 收到帧尾,解析一帧 */
            int cmd = parseFrame(frame, idx);
            idx = 0;
            if (cmd > 0) return cmd;        /* 返回词条编号 */
        }
        if (idx >= (int)sizeof(frame)) idx = 0;  /* 防溢出 */
    }
    return -1;
}

4、relay.h / relay.c —— 继电器控制模块

relay.h(声明):

#ifndef RELAY_H
#define RELAY_H
#include <stdbool.h>
​
void relay_init(void);            /* 初始化所有继电器为关 */
void relay_on(int ch);            /* 打开第 ch 路 */
void relay_off(int ch);           /* 关闭第 ch 路 */
void relay_toggle(int ch);        /* 翻转第 ch 路 */
bool relay_get_state(int ch);     /* 读取第 ch 路状态 */
#endif

relay.c(实现):

#include "relay.h"
#include "config.h"
​
static bool state[RELAY_NUM];
​
void relay_init(void) {
    for (int i = 0; i < RELAY_NUM; i++) {
        pinMode(relayPin[i], OUTPUT);
        relay_off(i);              /* 上电默认全关,更安全 */
    }
}
​
void relay_on(int ch) {
    if (ch < 0 || ch >= RELAY_NUM) return;
    digitalWrite(relayPin[ch], LOW);  /* 低电平触发 */
    state[ch] = true;
}
​
void relay_off(int ch) {
    if (ch < 0 || ch >= RELAY_NUM) return;
    digitalWrite(relayPin[ch], HIGH);
    state[ch] = false;
}
​
void relay_toggle(int ch) {
    if (state[ch]) relay_off(ch);
    else           relay_on(ch);
}
​
bool relay_get_state(int ch) {
    if (ch < 0 || ch >= RELAY_NUM) return false;
    return state[ch];
}

5、sensor.h / sensor.c —— 环境传感器模块

sensor.h(声明):

#ifndef SENSOR_H
#define SENSOR_H
#include <stdbool.h>
​
typedef struct {
    float temp;   /* 温度 ℃ */
    float humi;   /* 湿度 % */
    int   light;  /* 光照 ADC */
    bool  valid;  /* 数据是否有效 */
} env_data_t;
​
void sensor_init(void);        /* 初始化传感器 */
env_data_t sensor_read(void);  /* 读取一次环境数据 */
#endif

sensor.c(实现):

#include "sensor.h"
#include "config.h"
#include <DHT.h>

static DHT dht(PIN_DHT, DHT11);

void sensor_init(void) {
    dht.begin();
}

env_data_t sensor_read(void) {
    env_data_t d;
    d.temp  = dht.readTemperature();
    d.humi  = dht.readHumidity();
    d.light = analogRead(PIN_LIGHT);
    d.valid = !isnan(d.temp) && !isnan(d.humi);
    return d;
}

6、display.h / display.c —— OLED 显示模块

display.h(声明):

#ifndef DISPLAY_H
#define DISPLAY_H
#include "sensor.h"

void display_init(void);                     /* 初始化 OLED */
void display_show(const env_data_t *d, const bool *relay); /* 刷新显示 */
#endif

display.c(实现):

#include "display.h"
#include "config.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

static Adafruit_SSD1306 oled(128, 64, &Wire, -1);

void display_init(void) {
    Wire.begin(PIN_OLED_SDA, PIN_OLED_SCL);
    oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    oled.clearDisplay();
    oled.setTextSize(1);
    oled.setTextColor(SSD1306_WHITE);
}

void display_show(const env_data_t *d, const bool *relay) {
    oled.clearDisplay();
    oled.setCursor(0, 0);
    oled.println("== Voice Home ==");
    oled.print("Temp:"); oled.print(d->temp); oled.println("C");
    oled.print("Humi:"); oled.print(d->humi); oled.println("%");
    oled.print("Lamp:"); oled.println(relay[0] ? "ON " : "OFF");
    oled.print("Fan :"); oled.println(relay[1] ? "ON " : "OFF");
    oled.print("Sock:"); oled.println(relay[2] ? "ON " : "OFF");
    oled.display();
}

7、main.c —— 主程序

#include "config.h"
#include "voice.h"
#include "relay.h"
#include "sensor.h"
#include "display.h"

/* 把词条编号翻译成继电器动作 */
static void execVoiceCmd(int cmd) {
    switch (cmd) {
        case CMD_LAMP_ON:    relay_on(0);          break;
        case CMD_LAMP_OFF:   relay_off(0);         break;
        case CMD_FAN_ON:     relay_on(1);          break;
        case CMD_FAN_OFF:    relay_off(1);         break;
        case CMD_SOCKET_ON:  relay_on(2);          break;
        case CMD_SOCKET_OFF: relay_off(2);         break;
        default: break;
    }
}

/* 环境本地联动:温度高开风扇、光暗开灯(带状态变化防抖) */
static void envLinkage(const env_data_t *d) {
    static bool fanAuto = false, lampAuto = false;

    bool needFan  = (d->temp > TEMP_AUTO_FAN);
    bool needLamp = (d->light > LIGHT_AUTO_ON);

    if (needFan  != fanAuto) { fanAuto  = needFan;  needFan  ? relay_on(1)  : relay_off(1); }
    if (needLamp != lampAuto){ lampAuto = needLamp; needLamp ? relay_on(0)  : relay_off(0); }
}

void setup() {
    relay_init();        /* 初始化继电器 */
    sensor_init();       /* 初始化传感器 */
    display_init();      /* 初始化 OLED */
    voice_init();        /* 初始化语音串口 */
}

void loop() {
    /* ① 处理语音指令 */
    int cmd = voice_get_cmd();
    if (cmd > 0) execVoiceCmd(cmd);

    /* ② 读取环境并本地联动 */
    env_data_t d = sensor_read();
    if (d.valid) envLinkage(&d);

    /* ③ 刷新显示 */
    bool relayState[RELAY_NUM];
    for (int i = 0; i < RELAY_NUM; i++) relayState[i] = relay_get_state(i);
    display_show(&d, relayState);

    delay(500);
}

以上为核心模块代码。需要时可继续扩展:新增 ir.c 红外遥控、ble.c 蓝牙本地控制、把联动做成可配置规则等,主程序只调用接口,逻辑一目了然。

十二、代码要点讲解

  • .h/.c 分离:.h 只放宏、结构体、函数声明供 #include,.c 放具体实现隐藏细节,模块独立、便于扩展,是论文「模块化设计」的要点;

  • config.h 集中配置:引脚、继电器、阈值、词条编号都收在一个文件,改参数不用翻代码;

  • voice.c 串口帧解析:用 0xFD/0xFF 校验帧头帧尾,取 buf[3] 命令词编号,稳定且不误判;词条编号与智能公元配置一一对应;

  • execVoiceCmd() 命令分发:把词条编号翻译成继电器动作,语音模块换词条只需改映射,主逻辑不动;

  • envLinkage() 本地联动:温度 > 阈值自动开风扇、光照变暗自动开灯;用 static 标志只在状态翻转时动作,避免每循环反复触发,也避免和语音控制冲突;

  • 上电默认全关:relay_init 把所有继电器置关,安全;

  • isnan() 判空:DHT11 偶发读取失败返回非数值,必须判空,否则联动误判;

  • 完全不依赖 WiFi:本设计无需连网,语音识别与联动全本地完成,体现「离线可用」的核心卖点。

十三、功能测试与验收

功能实现方式测试方法
语音开灯说「开灯」→ voice_get_cmd 返回 1 → relay_on(0)喊「开灯」,观察灯亮、OLED 显示 Lamp:ON
语音关风扇说「关风扇」→ 返回 4 → relay_off(1)喊「关风扇」,观察风扇停
语音开插座说「打开插座」→ 返回 5 → relay_on(2)喊「打开插座」,插座负载通电
温度联动d.temp > TEMP_AUTO_FAN → 自动开风扇用手捂热 DHT11,温度升高风扇自动启动
光照联动d.light > LIGHT_AUTO_ON → 自动开灯遮住光敏模块,光线变暗灯自动亮
离线可用全程不连 WiFi拔掉 WiFi/断网,语音控制与环境联动仍正常

分步验收清单:

  1. 上电 OLED 显示温度、湿度、设备状态 → 显示层 OK;

  2. 说「小智小智」唤醒,喊「开灯」,灯亮 → 语音识别 + 指令下行 OK;

  3. 喊「关灯」,灯灭 → 反向控制 OK;

  4. 捂热 DHT11,温度超阈值风扇自动转 → 温度联动 OK;

  5. 遮光敏,灯自动亮 → 光照联动 OK;

  6. 拔网测试,功能不变 → 离线可用 OK。

十四、能给你什么启发?

1. 选题优势:交互方式新颖(语音)、完全离线不依赖云端、系统稳定,答辩展示直观,且不像纯远程控制类那样「千篇一律」,差异化明显,论文素材充足。

2. 想冲更高分数,随便往这几个方向扩:

  • 加红外遥控:用语音 + 红外控制空调、电视等带遥控的家电;

  • 加蓝牙/局域网双模式:离线语音 + 手机局域网控制并存,覆盖更多入口;

  • 联动规则可配置:把「温度多高开风扇、光照多暗开灯」做成可配置规则表,突出智能化;

  • 加更多传感器:人体红外实现「人来灯亮、人走灯灭」;

  • 多房间组网:多个语音控制盒分布家中,形成全屋语音智能家居。

十五、开题报告 & 答辩要点

1、开题报告可直接改用的表述

1. 选题依据(背景):随着智能家居的发展,用户对控制方式的便捷性、自然性要求越来越高。传统手机 APP 控制依赖网络、操作步骤多,对老人小孩不友好;云端方案在断网时无法使用。语音是人类最自然的交互方式,离线语音识别可在本地完成指令识别,无需依赖外部网络,能够提升智能家居控制的便捷性与稳定性,具有重要的实用价值。

2. 研究意义:本课题将离线语音识别技术与家居设备控制结合,一方面实现「动口不动手」的自然交互,提升智能家居的易用性与无网可用性;另一方面完整覆盖语音识别、串口通信、多路控制、传感器联动等物联网关键技术,对巩固专业知识、锻炼软硬件综合开发能力有重要意义。

3. 系统功能概述:系统基于 ESP32 主控,通过离线语音识别模块(SU-03T)识别语音指令,经串口将指令帧发送给主控解析,驱动多路继电器控制灯具、风扇、插座等电器;同时采集温湿度与光照数据,实现温度过高自动开风扇、光照变暗自动开灯等本地联动,全程无需联网。

4. 创新点(按实际情况选取):

  • 采用离线语音识别,不依赖云端与网络,系统稳定性强;

  • 采用 .h/.c 模块化软件架构,代码结构清晰、易于扩展;

  • 实现「语音控制 + 环境联动」本地闭环,交互自然、智能化程度高。

5. 技术难点:

  • 离线语音模块的词条配置与串口指令帧解析;

  • 多路继电器独立控制与语音指令的可靠映射;

  • 环境联动逻辑的状态管理与防抖处理。

2、答辩常见问题

可能被问回答要点
为什么选离线语音识别?不依赖网络、响应快、稳定,交互自然,老人小孩都会用,突出差异化
语音识别怎么实现的?SU-03T 离线芯片,提前用智能公元配置词条烧录,识别到后串口输出指令帧
指令帧怎么解析?校验帧头 FD、帧尾 FF,取命令词编号字节,映射到对应继电器动作
本地联动怎么实现?读 DHT11/光敏 → 温度高自动开风扇、光暗自动开灯,带状态翻转防抖
断网能用吗?能,语音识别、控制、联动全部本地完成,不依赖 WiFi 与云平台
系统有哪些改进空间?加红外控空调、蓝牙双模式、联动规则可配置、多房间组网等

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/x1649545783/article/details/169833756

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--