小智AI(ESP32-S3)添加IOT功能、导入外部库 + HomeAssistant + MQTT + ESP8266 = 物联网(基于vscode上的ESP-IDF)_小智ai iot
首先感谢所有帮助过我的佬们!
声明:本人是零基础小白(大四了,为了做毕设才开始学的,之前只学了两个月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
| ^~~~~~~~~~~~~~
解决办法:如果这个缺失的文件,你可以在你电脑上找到,那说明只是路径设置不对,要么改include_path的路径,要么看看你哪份代码里面标了缺失这个文件,看看这个代码里,不缺失的文件在哪个位置,然后把找到的文件复制一份到这个不缺失的文件的文件夹,然后重启电脑,重新打开vscode。但如果是要导入外部库,目前我只能用改include_Path这个办法。
遇到报错4:未找到Arduino库
fatal error: Arduino.h: No such file or directory
10 | #include
| ^~~~~~~~~~~
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
| ^~~~~~~~~~~
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 #include #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(\"state\", \"开关状态\", kValueTypeString)}), [this](const ParameterList& params) { send_mqtt_command(LED_CMD_TOPIC, params[\"state\"].string().c_str()); } ); methods_.AddMethod(\"ControlFan\", \"控制风扇开关\", ParameterList(std::vector{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(\"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 iotDECLARE_THING(ESPController);
注意事项:
一:UART端口别重复
iot文件夹里的用过的UART端口就不要再用了,不然会冲突。
#define UART_PORT UART_NUM_1 // 更换为其他可用UART端口
二:删掉注册WIFI的相关代码
当你实现了ESP32控制ESP8266时,你肯定已经在你代码里注册了WIFI,这里不需要,因为小智AI有自己的STA代码(意思就是,小智AI有“让你给他配置WIFI”这个功能),所以不要注册WIFI的相关代码了。只需要配置好MQTT地址、主题等就行。
三:注意小智AI发送的命令,是大写还是小写
后续想到什么我再补充吧,祝大家更上一层楼,祝中国AI事业更上一层楼。