小智AI(ESP32-S3)添加IOT功能、导入外部库 + HomeAssistant + MQTT + ESP8266 = 物联网(基于vscode上的ESP-IDF)

首先感谢所有帮助过我的佬们!

声明:本人是零基础小白(大四了,为了做毕设才开始学的,之前只学了两个月C++,没搞过电控,纯小镇做题家),全是根据网上视频、咨询各种大佬、自己摸索尝试学来的,从3.4开始零基础学,3.31正式完工,通了七八个夜,近20天干到凌晨三四点,终于摸索出了一个结果,本篇以作纪念,激励自己未来更进一步!欢迎大家把自己遇到的问题和解决办法发到评论区,大家一起讨论!

(大部分遇到的代码格式报错,我都是找DeepSeek帮我改,一些由于设置不正确导致的报错,我遇到的都在下面了,如果我有讲不对的地方,也请大家帮我指正在评论区,实在不行的就重新安装ESP-IDF,重新导入小智源码,很多时候即使代码报错也可以烧录的,主要是看烧录过程报的错)


————————————————————————前言————————————————————————
Q:为什么要用ESP32(搭载小智AI)借助HomeAssistant平台,通过MQTT协议,控制另一个ESP8266上的设备?而不直接用蓝牙呢?
A:因为小智AI本身自带强大的对话聊天功能。同时,通过HomeAssistant平台搭建一个ESP32到ESP8266的控制,在局域网下的优势更明显,且可以集成别的有线、无线设备,例如小米智能家居等,一体化控制,且HomeAssistant有自己的APP,可以统一管理控制。即便是距离较远,只要在同一个WIFI下,都可以实现控制。并且不仅是在HomeAssistant平台上,通过修改,小智AI也可以同时控制局域网下的所有家居设备。

————————————————————————正文————————————————————————

一、下载安装、环境搭建、代码烧录流程:

参考资料

【ESP-IDF篇】搭建ESP-IDF软件开发环境,包括手动命令行和VSCode两种方式-CSDN博客

VSCode安装Esp-IDF开发环境(pip version)出错解决办法_如何彻底删除esp-idf-CSDN博客

参考这两个即可

如果你烧录过第一遍后,如果你想改代码再烧录,改完后直接依次点“彻底清理”、“ESP-IDF构建、烧录和监视”,这两个就行。
如果你烧录的过程中报错改掉错误后点击“ESP-IDF构建、烧录和监视”,就可以继续烧录。

二、语音控制点亮LED(小智AI自带的功能)

参考资料:

VScode下玩转ESP32S3并成功编译XIAOZHI-ESP32-MAIN代码_xiaozhi-esp32 编译-CSDN博客

【虾哥小智源码编译演示】 https://www.bilibili.com/video/BV1qqNceNE6d/?share_source=copy_web&vd_source=514c9373e6d25d0b426a7c7343964747

小智接入全屋智能HomeAssistant,家居控制,音乐播放完整演示_哔哩哔哩_bilibili

虾哥AI小智ESP32彩屏款编译及添加IOT教程-东阳马生DoYy-稍后再看-哔哩哔哩视频

[开源/教程]用小智闹钟,教你如何使用AI控制本地功能-东阳马生DoYy-稍后再看-哔哩哔哩视频

总结:主要步骤只有三步
①在小智源码(怎么下载自己百度就行)里面的iot文件夹下,创建一个.cc文件,模仿lamp文件里面的格式写。可以参考上述后两个视频,学习以下lamp.cc文件的结构,然后自己就可以写了。(在此感谢两位佬的帮助
②写完之后去问自己的淘宝店家,自己的板子对应boards文件夹(在源码的main文件夹里)里面的什么型号,然后在对应型号的.h文件夹里面添加一个设备。例如我的是compact_wifi_board(买的是淘宝里面那个叫源地什么的店家的套件,人挺好,回复的也挺快。不是广告,纯觉得他人好,我都买回来快一个月了,问他问题他还会回复)

③在iot文件夹里,找到sample_interface.json,添加对应功能

这样就能给小智AI添加一个功能了。

遇到报错1:

————————————————————————
Adding "set-target"'s dependency "fullclean" to list of commands with default set of options.
Executing action: fullclean
Executing action: set-target
Set Target to: esp32s3, new sdkconfig created. Existing sdkconfig renamed to sdkconfig.old.
Running cmake in directory d:\esp\esp\project\hello_world\build
Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DESP_PLATFORM=1 -DIDF_TARGET=esp32s3 -DCCACHE_ENABLE=1 d:\esp\esp\project\hello_world"...
CMake Error at D:/ESP/ESP_IDE/esp-idf/tools/cmake/targets.cmake:19 (message):
IDF_TARGET in CMake cache does not match IDF_TARGET environment variable.
To change the target, clear the build directory and sdkconfig file, and
build the project again
Call Stack (most recent call first):
D:/ESP/ESP_IDE/esp-idf/tools/cmake/project.cmake:7 (__target_init)
CMakeLists.txt:5 (include)


-- Configuring incomplete, errors occurred!
cmake failed with exit code 1
————————————————————————————

解决办法:乖乖地执行上述两个参考文章的烧录步骤,点开左侧ESPIDF里面,第一步,选择当前项目的工作区的文件夹,选xiaozhi-main那个文件夹即可
还有一种可能,就是你已经是选中这个板子的状态了,直接编译就行,所以不让重复选择

遇到报错2:

esp-idf对头文件报错,无法跳转

解决办法:
有部分头文件不影响编译,把影响编译的用下面的解决办法处理。

ESP32的ESP-IDF在VScode工程下,头文件标红警告、报错、无法跳转_vscode esp32 找不到头文件-CSDN博客z可以把报错的都快速修复在include_path里面,但是要是外部库的话还没找到解决办法。(如何导入外部库可以参考下文的解决办法)

三、控制步进电机三个挡位旋转

电机驱动:UNL2003   电机:28BYJ-48

参考资料:

小智物联网开发:为小智安装“机械臂“(其实就是加个舵机进行语音控制)-CSDN博客

(在此感谢LS佬的帮助!)


遇到报错1:thing type not found

编译提示:thing: thing type not found : motor(这个motor是我自己创的文件)

解决办法:

把powershell右侧的都删了,然后把motor都统一了Motor,重新编译即可

遇到报错2:internal compiler error: Segmentation fault

D:/ESP-IDF/ESP-IDF/v5.3.2/esp-idf/components/esp_lcd/rgb/esp_lcd_panel_rgb.c:800:1: internal compiler error: Segmentation fault
  800 | }
      | ^
libbacktrace could not find executable to open

 *  终端进程“d:\ESP-IDF\ESP-IDF-TOOL\tools\ninja\1.12.1\ninja.exe”已终止,退出代码: 1。 

解决办法:系统内存不足,关掉一些没用的程序,还有,把VScode右侧的进程都终止了,重新编译。也可以再次点“ESP-IDF构建、烧录、监视”,继续编译。

遇到报错3:未找到ESP-IDF自带的库

D:/ESP-IDF/ESP-IDF/v5.3.2/esp-idf/components/esp_lcd/rgb/esp_lcd_panel_rgb.c:47:10: fatal error: lcd_periph.h: No such file or directory
   47 | #include <lcd_periph.h>
      |          ^~~~~~~~~~~~~~

解决办法:如果这个缺失的文件,你可以在你电脑上找到,那说明只是路径设置不对,要么改include_path的路径,要么看看你哪份代码里面标了缺失这个文件,看看这个代码里,不缺失的文件在哪个位置,然后把找到的文件复制一份到这个不缺失的文件的文件夹,然后重启电脑,重新打开vscode。但如果是要导入外部库,目前我只能用改include_Path这个办法。

遇到报错4:未找到Arduino库

fatal error: Arduino.h: No such file or directory
   10 | #include <Arduino.h>
      |          ^~~~~~~~~~~
compilation terminated.
解决办法:这是ESP-IDF自身不带Arduino库的原因,Releases · espressif/arduino-esp32 · GitHub
这个网站里面是不同版本的ESP-IDF(不知道版本的自己看ESP-IDF的安装位置,文件夹的名称就是版本号),下载source.zip然后解压到ESP-IDF的components里面即可


遇到报错5:如何导入外部库


fatal error: WiFi.h: No such file or directory
   10 | #include <PubClient.h>
      |          ^~~~~~~~~~~
compilation terminated.

解决办法:(以下只针对单独的一个功能库,且不需要引用别的类似于Arduino等库的类型,如果要导入类似于WiFi.h这种,有很多依赖库的库,就需要把所有库都导入进来,做法和如下相同)
可以参考这个视频的源码(在视频简介)[开源/教程]用小智闹钟,教你如何使用AI控制本地功能-东阳马生DoYy-稍后再看-哔哩哔哩视频

步骤①:打开小智AI源代码的main文件夹,里面的CMakeLists,有一个添加IOT相关文件。

②在main文件夹里创建一个自己的文件夹,例如PubClient,放入自己要导入的外部库的.cc和.h文件
③模仿IOT函数,创建自己的库的引用,例如:

file(GLOB PubClient_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/PubClient/*.cc)

list(APPEND SOURCES ${PubClient_SOURCES})

list(APPEND INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/PubClient)

遇到报错6:ESP--IDF的SDK配置器(menuconfig)打开报错


-- DEBUG: Use esp-modbus component folder: C:/Users/Administrator/Desktop/xiaozhi-esp32-main/managed_components/espressif__esp-modbus. ---------------------------ERROR-------------------------- ESP Insights Project commit: HEAD-HASH-NOTFOUND -----------------------END OF ERROR----------------------- -- git rev-parse returned 'fatal: not a git repository (or any of the parent directories): .git' ---------------------------ERROR-------------------------- ESP RainMaker Project commit: HEAD-HASH-NOTFOUND -----------------------END OF ERROR----------------------- -- git rev-parse returned 'fatal: not a git repository (or any of the parent directories): .git' ---------------------------ERROR-------------------------- CMake Error at D:/ESP-IDF/ESP-IDF/v5.3.2/esp-idf/components/arduino-esp32-3.1.1/CMakeLists.txt:367 (message): esp32-arduino requires CONFIG_FREERTOS_HZ=1000 (currently 100) -----------------------END OF ERROR----------------------- -- Configuring incomplete, errors occurred! ---------------------------ERROR-------------------------- cmake failed with exit code 1, output of the command is in the C:\Users\Administrator\Desktop\xiaozhi-esp32-main\build\log\idf_py_stderr_output_21924 and C:\Users\Administrator\Desktop\xiaozhi-esp32-main\build\log\idf_py_stdout_output_21924 -----------------------END OF ERROR----------------------- ---------------------------ERROR-------------------------- SDK Configuration editor confserver process exited with code: 2 -----------------------END OF ERROR-----------------------
解决办法:打开左侧sdkconfig文件,找到:

CONFIG_FREERTOS_HZ=100   //原本是100,改成1000

四、小智ESP32S3+MQTT + HomeAssistant + ESP8266


这里介绍的是如何让小智AI连接上HomeAssistant,我之前已经实现了用ESP32-S3通过HomeAssistant上的MQTT(Mosquitto平台),控制、监视ESP8266上的设备(需要代码的话可以私信我,编译平台也是VScode)。我的虚拟机是Window自带的HyperV,Docker之前也用过,但是还是选择了HyperV。


参考资料:


【Homeassistant安装、小白也能上车】 https://www.bilibili.com/video/BV1ixXDYkEpa/?share_source=copy_web&vd_source=514c9373e6d25d0b426a7c7343964747


二、使用windows的hyper-v搭建homeassistant智能家居平台 - 哔哩哔哩

【HACS商店安装以及仪表盘卡片下载和使用【homeassistant教程1】】 https://www.bilibili.com/video/BV1jjAHepENu/?share_source=copy_web&vd_source=514c9373e6d25d0b426a7c7343964747

windows10-EMQX与MQTTX的安装及配置使用教程_emqx windows-CSDN博客

arduino esp32 通过wifi连接mqtt_eps32-CSDN博客(这个主要是参考代码怎么写的)

搭建个人智能家居 3 -第一个设备“点灯”_esphome-CSDN博客(这个主要是参考代码怎么写的)

(还有很多,CSDN、B站、瀚思彼岸等社区,还有问大佬,还有Deepseek帮我调代码等)

思路:仍然像给小智添加一个功能一样,在iot文件夹下添加一个.cc文件,叫做ESPController。

踩坑建议:最好还是使用ESP-IDF自带的WIFI库,即esp_wifi.h,Arduino的WiFi库有很多依赖,很麻烦,所以还是用ESP-IDF的库。

以下是小智iot文件夹里创建的代码

//ESPController文件
#include "iot/thing.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_mqtt.h"
#include "driver/uart.h"
#include <cstring>
#include <vector>

#define TAG "ESPController"

// MQTT 配置
#define MQTT_URI       "mqtt://192.168.229.27:1883"
#define CLIENT_ID      "ESP32-Controller"

// MQTT 主题
#define LED_CMD_TOPIC  "home/livingroom/led/command"
#define FAN_CMD_TOPIC  "home/livingroom/fan/command"
#define FAN_PRESET_TOPIC "home/livingroom/fan/preset_mode"

// UART 配置
#define UART_PORT UART_NUM_1 // 更换为其他可用UART端口
#define BUF_SIZE       (1024)

static esp_mqtt_client_handle_t mqtt_client;

namespace iot {

class ESPController : public Thing {
private:
    static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                  int32_t event_id, void* event_data) {
        if (event_id == WIFI_EVENT_STA_START) {
            esp_wifi_connect();
        } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
            esp_wifi_connect();
        }
    }

    static void ip_event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data) {
        if (event_id == IP_EVENT_STA_GOT_IP) {
            esp_mqtt_client_start(mqtt_client);
        }
    }

    static void mqtt_event_handler(void* handler_args, esp_event_base_t base, 
                                  int32_t event_id, void* event_data) {
        esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)event_data;
        if (event->event_id == MQTT_EVENT_CONNECTED) {
            ESP_LOGI(TAG, "MQTT Connected");
        }
    }

    static void uart_read_task(void* arg) {
        uint8_t data[BUF_SIZE];
        while (1) {
            int len = uart_read_bytes(UART_PORT, data, BUF_SIZE - 1, pdMS_TO_TICKS(100)); // 增加超时时间
            if (len > 0) {
                data[len] = '\0';
                std::string command((char*)data);
                command.erase(command.find_last_not_of("\r\n") + 1);

                if (command.find("打开客厅灯") != std::string::npos) {
                    send_mqtt_command(LED_CMD_TOPIC, "ON");
                } else if (command.find("关闭客厅灯") != std::string::npos) {
                    send_mqtt_command(LED_CMD_TOPIC, "OFF");
                } else if (command.find("打开风扇") != std::string::npos) {
                    send_mqtt_command(FAN_CMD_TOPIC, "ON");
                } else if (command.find("关闭风扇") != std::string::npos) {
                    send_mqtt_command(FAN_CMD_TOPIC, "OFF");
                } else if (command.find("一挡") != std::string::npos) {
                    send_mqtt_command(FAN_PRESET_TOPIC, "Low");
                } else if (command.find("二挡") != std::string::npos) {
                    send_mqtt_command(FAN_PRESET_TOPIC, "Medium");
                } else if (command.find("三挡") != std::string::npos) {
                    send_mqtt_command(FAN_PRESET_TOPIC, "High");
                }
            }else {
                vTaskDelay(pdMS_TO_TICKS(10));}
        }
    }

    static void send_mqtt_command(const char* topic, const char* payload) {
        esp_mqtt_client_publish(mqtt_client, topic, payload, 0, 1, 0);
        ESP_LOGI(TAG, "发送指令: %s -> %s", topic, payload);
    }

    public:
ESPController() : Thing("LivingRoomController", "客厅设备控制器") {
    static bool netif_initialized = false;
    if (!netif_initialized) {
        esp_netif_init();
        esp_event_loop_create_default();
        netif_initialized = true;
    }

        // 初始化 MQTT(正确设置 client_id)
        esp_mqtt_client_config_t mqtt_cfg = {};
        mqtt_cfg.broker.address.uri = MQTT_URI;
        mqtt_cfg.credentials.client_id = CLIENT_ID;  // 嵌套在 credentials 中
        mqtt_client = esp_mqtt_client_init(&mqtt_cfg);

        // 注册 MQTT 事件
        esp_mqtt_client_register_event(mqtt_client, MQTT_EVENT_ANY, mqtt_event_handler, NULL);
        // 直接启动 MQTT 客户端(假设网络已就绪)
         esp_mqtt_client_start(mqtt_client);

        // 初始化 UART
            uart_config_t uart_config = {
            .baud_rate = 115200,
            .data_bits = UART_DATA_8_BITS,
            .parity = UART_PARITY_DISABLE,
            .stop_bits = UART_STOP_BITS_1,
            .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        };
        uart_param_config(UART_PORT, &uart_config);
        uart_driver_install(UART_PORT, BUF_SIZE * 2, 0, 0, NULL, 0);

        // 创建 UART 读取任务
        xTaskCreate(uart_read_task, "uart_task", 4096, NULL, 2, NULL);

        // 注册属性与方法
        properties_.AddBooleanProperty("light_status", "客厅灯状态", [this]() -> bool {
            return false;
        });

        // 使用完全限定的参数类型
        methods_.AddMethod("ControlLight", "控制客厅灯开关",
            ParameterList(std::vector<Parameter>{Parameter("state", "开关状态", kValueTypeString)}),
            [this](const ParameterList& params) {
                send_mqtt_command(LED_CMD_TOPIC, params["state"].string().c_str());
            }
        );

        methods_.AddMethod("ControlFan", "控制风扇开关",
            ParameterList(std::vector<Parameter>{Parameter("state", "开关状态", kValueTypeString)}),
            [this](const ParameterList& params) {
                std::string state = params["state"].string();
                send_mqtt_command(FAN_CMD_TOPIC, state.c_str());
            }
        );

        methods_.AddMethod("SetFanSpeed", "设置风扇档位",
            ParameterList(std::vector<Parameter>{Parameter("speed", "档位(Low/Medium/High)", kValueTypeString)}),
            [this](const ParameterList& params) {
                std::string speed = params["speed"].string();
                send_mqtt_command(FAN_PRESET_TOPIC, speed.c_str());
            }
        );
    }
};

} // namespace iot

DECLARE_THING(ESPController);
注意事项:

一:UART端口别重复


iot文件夹里的用过的UART端口就不要再用了,不然会冲突。

#define UART_PORT UART_NUM_1 // 更换为其他可用UART端口
二:删掉注册WIFI的相关代码

当你实现了ESP32控制ESP8266时,你肯定已经在你代码里注册了WIFI,这里不需要,因为小智AI有自己的STA代码(意思就是,小智AI有“让你给他配置WIFI”这个功能),所以不要注册WIFI的相关代码了。只需要配置好MQTT地址、主题等就行。



三:注意小智AI发送的命令,是大写还是小写

 


后续想到什么我再补充吧,祝大家更上一层楼,祝中国AI事业更上一层楼。



 

### AI与4G技术特性及兼容性分析 AI是一款基于物联网IoT)技术的能语音交互设备,支持多种网络连接方式,其中包括Wi-Fi和4G。以下是关于其4G技术支持的具体特性和兼容性的详细介绍: #### 一、4G技术特性 1. **高速数据传输** 使用4G LTE技术可以实现更高的带宽和更低的延迟,这对于实时语音识别和响应至关重要[^1]。这种高效率的数据交换能力使得AI能够在复杂环境下快速完成指令解析并返回结果。 2. **广覆盖范围** 相较于Wi-Fi仅限于局域网环境下的应用,4G提供了更广泛的地理覆盖区域。这意味着即使在没有Wi-Fi信号的地方,只要存在蜂窝网络服务,AI依然能够保持在线状态并与云端服务器通信。 3. **稳定性增强** 蜂窝移动通信系统的架构设计天然具备一定的抗干扰能力和切换机制,在不同基站之间漫游时不会轻易掉线。这一特点对于户外场景下持续稳定的语音交流尤为重要。 #### 二、兼容性说明 1. **硬件适配** 小AI聊天机器人开源开发板采用了ESP32-S3作为核心处理器,该芯片内置双核CPU以及丰富的外设接口资源,同时还集成了Wi-Fi模块和支持Cellular Modem功能所需的UART串口等组件[^2]。因此它可以通过额外配置相应的SIM卡槽及相关驱动程序来接入4G网络。 2. **软件生态支持** 开发者社区围绕此项目构建了一套完整的固件框架体系结构,允许用户轻松集成第三方库文件或者自定义协议栈以满足特定需求。例如AT命令集可用于管理调制解调器参数设置;MQTT客户端则方便订阅发布消息队列从而简化云平台对接流程。 3. **跨操作系统移植便利度** 鉴于整个解决方案均遵循MIT许可证开放源码原则,任何有兴趣参与改进的人都能下载最新版本代码,并依据个人喜好调整目标平台编译选项进而生成适用于ARM Cortex-M系列MCU或其他相似架构的产品变体实例。 ```python import network def connect_4g(): apn = &#39;your_apn&#39; username = &#39;&#39; password = &#39;&#39; modem = network.Modem() modem.connect(apn, username, password) connect_4g() print("Connected to 4G Network.") ``` 上述脚本展示了如何利用MicroPython API初始化蜂窝数据链路层关联过程的一个简单例子。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值