【使用豆包大模型开发ESP32C3的ESPNOW数传电台】
本文介绍如何利用豆包大模型辅助开发ESP32C3的ESPNOW双向通讯系统。ESP32C3芯片结合ESPNOW协议可实现无需WiFi的点对点高速通信,适用于物联网场景。文章详细说明了开发流程:首先注册豆包大模型账号,该AI工具可快速生成代码、解决技术问题;然后配置PlatformIO开发环境,准备ESP32C3开发板等硬件;最后提供核心代码实现,包括项目配置文件和ESPNOW通讯主程序。通过豆包大
使用豆包大模型开发ESP32C3的ESPNOW数传电台
使用豆包大模型开发ESP32C3的ESPNOW双向通讯
前言
随着物联网技术的快速发展,ESP32系列芯片因其强大的性能和丰富的功能,成为了物联网开发的热门选择。而ESPNOW作为ESP32的一种高速无线通信协议,无需WiFi网络即可实现设备间的点对点通讯,非常适合传感器数据传输、智能家居控制等场景。
现在,我们可以利用豆包大模型的强大能力,更高效地开发ESP32C3的ESPNOW双向通讯功能。本文将详细介绍如何结合豆包大模型,快速实现ESP32C3之间的ESPNOW双向通讯系统。
用ESP32C3实现ESPNOW双向通讯,不仅可以传输传感器数据,还可以实现设备间的实时控制!豆包大模型辅助开发,让代码编写更加高效。😘😘😘💕💕💕
首先声明没有恰饭广告,源代码已经匿名处理,制作细节非常完善,方便大家复刻才会提供快捷的相关链接跳转!!!😘😘😘
本文将重点介绍如何通过豆包大模型辅助开发ESP32C3的ESPNOW双向通讯系统。
1. 豆包大模型
请大家点击豆包火山注册地址,不注册是不能完成下面的实验哦:https://t.vncps.com/5LOve
谢谢啦大家的支持💖💖💖
豆包与火山方舟、火山引擎之间的关系主要体现为技术同源、产品定位互补,三者均隶属于字节跳动旗下。具体联系如下:
🛠️ 1. 火山引擎:底层技术基座
定位:字节跳动推出的企业级云服务平台,提供云计算、大数据、AI 中台、容器服务等基础技术能力。
功能:为火山方舟提供算力支持(GPU集群)、模型训练/推理框架、数据存储等基础设施。
关系:是豆包和火山方舟的技术底层支撑。🤖 2. 豆包:AI 产品化终端应用
定位:面向公众的AI对话助手(类似ChatGPT),可提供问答、写作、编程等能力。
技术来源:依赖于火山引擎的算力资源及自研大模型(如Skywork天工、Cloud系列模型)。
产品形态:直接向用户提供服务的C端应用(网页/App),如doubao.com。🔧 3. 火山方舟:AI 模型开发与服务平台
定位:聚焦于企业级AI模型的开发、部署与管理平台(类似百度文心千帆)。
核心功能:
- 模型接入:支持集成第三方大模型(如百川、MiniMax)。
- 工具链:提供模型精调(Fine-tuning)、评测、API部署等工具。
- 场景方案:针对企业需求定制客服、营销等AI解决方案。
与豆包的联系:- 技术同源:共用火山引擎的AI训练框架和推理加速技术。
- 能力互补:企业可通过火山方舟训练模型,再以SDK/API形式接入自身产品(如集成类似豆包的聊天功能)。
- 模型共享:豆包的底层模型可能通过火山方舟向企业客户开放定制。
1.1 豆包大模型在ESP32开发中的应用
豆包大模型可以帮助我们:
- 快速生成代码:根据需求描述自动生成ESP32相关代码
- 解决技术问题:解答开发过程中遇到的技术难题
- 优化代码结构:提供代码优化建议,提高代码质量
- 学习新技术:快速了解ESP32的新功能和使用方法
1.2 订阅火山codeplan
如果大家订阅火山codeplan
就可以畅享Trae中所有模型,写代码神速,可以理解上下文和代码,我是采用vscode安装Trae插件
还可以写博客记录下面是我使用的部分记录,对比千问还是强不少,大大减少markdown语法不识别问题
请大家点击豆包火山注册地址:https://t.vncps.com/5LOve
方舟 Coding Plan 支持 Doubao、GLM、DeepSeek、Kimi 等模型,工具不限,现在订阅折上9折,低至8.9元,订阅越多越划算!立即订阅:https://volcengine.com/L/2p_L1OTLQZw/ 邀请码:TVGNH4JT
访问火山方舟 Coding Plan 新用户特惠活动,按需订阅套餐。套餐介绍参见套餐概览https://www.volcengine.com/docs/82379/1925114?lang=zh。
在开通管理页面https://console.volcengine.com/ark/region:ark+cn-beijing/openManagement?LLM=%7B%7D&advancedActiveKey=subscribe选择或切换目标模型,无需在工具中额外变更模型配置。
2. 环境配置
2.1 开发环境准备
- PlatformIO:下载并安装VSCode + PlatformIO插件;
- ESP32开发板库:在PlatformIO中添加ESP32支持;
- 相关依赖库:根据项目需求添加必要的库文件。
2.2 所需零件
要学习本教程,您需要:
【下单链接】https://s.click.taobao.com/ViA8xfn,一定要安装天线测试
【下单链接】https://s.click.taobao.com/FUJ3xfn,ESP32C3 PRO MINI开发板板载ESP32-C3FH4芯片模块wifi 蓝牙开发板也是可以的,我采用这个小巧模块自带陶瓷天线
- ESP32C3开发板x2:建议使用Seeed XIAO ESP32C3,体积小巧,功能强大;
- WIN10/WIN11电脑:编写代码调试功能
- USB数据线x2:用于烧录代码和串口通信。
2.3 硬件连接
- LED引脚默认在ESP32C3开发板的GPIO8(可在代码中修改);
- USB供电。
3. 核心代码
3.1 项目配置文件
首先,我们需要配置PlatformIO项目文件:
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:seeed_xiao_esp32c3]
platform = espressif32
board = seeed_xiao_esp32c3
framework = arduino
; 串口上传速度(可选)
; upload_speed = 921600
; 监视器波特率
monitor_speed = 115200
lib_deps =
mikalhart/TinyGPSPlus@^1.1.0
plerup/EspSoftwareSerial@^8.2.0
SPIFFS
board_build.partitions = partitions.csv
; 启用 C++17(推荐)
build_flags = -std=gnu++17
upload_resetmethod = ck
3.2 主代码实现
下面是ESP32C3的ESPNOW双向通讯核心代码,由豆包大模型辅助开发:
#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>
#include <esp_wifi.h>
#include <nvs_flash.h>
#include <nvs.h>
#include <string.h>
#define LED_PIN 8
#define NVS_NAMESPACE "espnow"
#define NVS_KEY_PEER_MAC "peer_mac"
static uint8_t selfMac[6];
static uint8_t peerMac[6];
static bool isPaired = false;
static bool isConnected = false;
const unsigned long BLINK_INTERVAL = 500;
const unsigned long HEARTBEAT_INTERVAL = 1000;
const unsigned long CONNECTION_TIMEOUT = 3000;
unsigned long lastBlink = 0;
unsigned long lastSent = 0;
unsigned long lastReceived = 0;
// 模拟温度
float simulateTemperature() {
static float temp = 22.0f;
temp += (random(0, 200) - 100) * 0.01f;
if (temp < 20.0f) temp = 20.0f;
if (temp > 35.0f) temp = 35.0f;
return temp;
}
// 格式化 MAC 地址
String formatMac(const uint8_t* mac) {
char buf[18];
snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}
// ================== NVS ==================
bool savePeerMac(const uint8_t* mac) {
nvs_handle_t handle;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle);
if (err != ESP_OK) return false;
err = nvs_set_blob(handle, NVS_KEY_PEER_MAC, mac, 6);
if (err != ESP_OK) { nvs_close(handle); return false; }
err = nvs_commit(handle);
nvs_close(handle);
return (err == ESP_OK);
}
bool loadPeerMac(uint8_t* outMac) {
nvs_handle_t handle;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle);
if (err != ESP_OK) return false;
size_t size = 6;
err = nvs_get_blob(handle, NVS_KEY_PEER_MAC, outMac, &size);
nvs_close(handle);
return (err == ESP_OK && size == 6);
}
void eraseSavedPeer() {
nvs_handle_t handle;
if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle) == ESP_OK) {
nvs_erase_key(handle, NVS_KEY_PEER_MAC);
nvs_commit(handle);
nvs_close(handle);
}
}
// ========================================
bool parseMacAddress(const String& input, uint8_t* outMac) {
String clean = input;
clean.replace(":", "");
clean.replace("-", "");
clean.replace(" ", "");
if (clean.length() != 12) return false;
for (int i = 0; i < 6; i++) {
String byteStr = clean.substring(i * 2, i * 2 + 2);
outMac[i] = (uint8_t)strtol(byteStr.c_str(), NULL, 16);
}
return true;
}
bool attemptPairWith(const uint8_t* targetMac) {
esp_now_peer_info_t peer;
memset(&peer, 0, sizeof(peer));
memcpy(peer.peer_addr, targetMac, 6);
peer.channel = 0;
peer.encrypt = false;
if (esp_now_add_peer(&peer) != ESP_OK) return false;
const char* testMsg = "CONN";
return (esp_now_send(targetMac, (uint8_t*)testMsg, strlen(testMsg)) == ESP_OK);
}
// 接收回调:带调试打印
void onDataRecv(const uint8_t *mac, const uint8_t *data, int len) {
// 构造接收到的字符串(确保以 \0 结尾)
char buffer[len + 1];
memcpy(buffer, data, len);
buffer[len] = '\0';
String senderMac = formatMac(mac);
Serial.printf("📥 Recv from %s: %s\n", senderMac.c_str(), buffer);
if (isPaired && memcmp(mac, peerMac, 6) == 0) {
lastReceived = millis();
isConnected = true;
}
}
void setup() {
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); // 初始灭灯
Serial.begin(115200);
Serial.println("\nESP32-C3 ESP-NOW Enhanced (with Debug Log)");
Serial.println("Commands: PAIR xx:xx:..., CLEAR, AT+RESTART, HELP, AT+MAC, AT+FRIEND");
randomSeed(analogRead(0));
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
nvs_flash_erase();
nvs_flash_init();
}
WiFi.mode(WIFI_STA);
esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE);
if (esp_now_init() != ESP_OK) {
Serial.println("❌ ESP-NOW init failed!");
return;
}
esp_now_register_recv_cb(onDataRecv);
esp_read_mac(selfMac, ESP_MAC_WIFI_STA);
Serial.printf("\n>>> MY MAC: %s <<<\n\n", formatMac(selfMac).c_str());
if (loadPeerMac(peerMac)) {
Serial.printf("💾 Loaded peer: %s\n", formatMac(peerMac).c_str());
if (attemptPairWith(peerMac)) {
isPaired = true;
isConnected = true;
lastReceived = millis();
Serial.println("✅ Resumed pairing!");
} else {
Serial.println("❌ Resume failed");
eraseSavedPeer();
}
}
}
String serialBuffer = "";
void loop() {
while (Serial.available()) {
char c = Serial.read();
if (c == '\n' || c == '\r') {
serialBuffer.trim();
if (serialBuffer.startsWith("PAIR ") && !isPaired) {
String macStr = serialBuffer.substring(5);
if (parseMacAddress(macStr, peerMac)) {
if (attemptPairWith(peerMac)) {
savePeerMac(peerMac);
isPaired = true;
isConnected = true;
lastReceived = millis();
Serial.println("✅ Paired and saved!");
} else {
Serial.println("❌ Pairing failed");
}
} else {
Serial.println("❌ Invalid MAC");
}
} else if (serialBuffer.equalsIgnoreCase("CLEAR")) {
eraseSavedPeer();
isPaired = false;
isConnected = false;
Serial.println("🧹 Cleared");
} else if (serialBuffer.equalsIgnoreCase("AT+RESTART")) {
ESP.restart();
} else if (serialBuffer.equalsIgnoreCase("HELP")) {
Serial.println("Commands:");
Serial.println(" PAIR xx:xx:xx:xx:xx:xx");
Serial.println(" CLEAR");
Serial.println(" AT+RESTART");
Serial.println(" AT+MAC");
Serial.println(" AT+FRIEND");
} else if (serialBuffer.equalsIgnoreCase("AT+MAC")) {
Serial.println(formatMac(selfMac));
} else if (serialBuffer.equalsIgnoreCase("AT+FRIEND")) {
if (isPaired) {
Serial.println(formatMac(peerMac));
} else {
Serial.println("No paired device");
}
} else if (!serialBuffer.isEmpty()) {
Serial.println("❓ Unknown command. Type HELP.");
}
serialBuffer = "";
} else {
serialBuffer += c;
}
}
unsigned long now = millis();
// 断连检测
if (isPaired && (now - lastReceived > CONNECTION_TIMEOUT)) {
isConnected = false;
}
// LED 控制
if (isConnected) {
if (now - lastBlink >= BLINK_INTERVAL) {
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
lastBlink = now;
}
} else {
digitalWrite(LED_PIN, HIGH); // 熄灭
}
// 每秒发送数据(带调试打印)
if (isPaired && (now - lastSent >= HEARTBEAT_INTERVAL)) {
float temp = simulateTemperature();
String payload = formatMac(selfMac) + "," + String(temp, 1);
esp_now_send(peerMac, (uint8_t*)payload.c_str(), payload.length());
lastSent = now;
// 🔽 调试:打印发送内容
Serial.printf("📤 Sent: %s\n", payload.c_str());
}
delay(10);
}
两块开发都上传同样代码,如果出现上传失败

就按住boot,然后点按reset,松开boot重新烧录即可
烧录成功后按一下reset,选择打开串口助手(插件monitor),回车符LF,发送AT+MAC返回当前地址
记录MAC地址:0C:4E:A0:68:6A:78
3.3 代码解析
-
初始化部分:
- 初始化LED引脚和串口
- 初始化NVS闪存,用于存储配对信息
- 初始化WiFi和ESPNOW
- 注册数据接收回调函数
-
配对功能:
- 通过串口命令"PAIR 0C:4E:A0:68:6A:78"进行设备配对
- 配对成功后将对方MAC地址保存到NVS
- 设备重启后自动加载配对信息
-
数据传输:
- 每秒发送一次模拟温度数据
- 接收对方发送的数据并更新连接状态
- 通过LED闪烁指示连接状态
-
命令系统:
- PAIR:配对新设备
- CLEAR:清除配对信息
- AT+RESTART:重启设备
- HELP:显示帮助信息
- AT+MAC:显示本机MAC地址
- AT+FRIEND:显示配对设备MAC地址
4. 功能测试
4.1 测试步骤
- 烧录代码:将代码烧录到两个ESP32C3开发板
- 查看MAC地址:通过AT+MAC命令查看两个设备的MAC地址
- 配对设备:在一个设备上发送"PAIR xx:xx:xx:xx:xx:xx"命令,其中xx:xx:xx:xx:xx:xx是另一个设备的MAC地址
- 观察连接状态:配对成功后,LED会开始闪烁
- 查看数据传输:在串口监视器中查看数据发送和接收情况

4.2 测试结果
| 测试项 | 预期结果 | 实际结果 |
|---|---|---|
| 设备配对 | 配对成功后显示"✅ Paired and saved!" | ✅ |
| 数据发送 | 每秒发送一次温度数据 | ✅ |
| 数据接收 | 能接收到对方发送的数据 | ✅ |
| 连接状态 | 连接时LED闪烁,断开时LED熄灭 | ✅ |
| 自动重连 | 重启设备后自动加载配对信息 | ✅ |
---- 已发送 utf8 编码消息: "AT+RESTART\n" ----
ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0xd (SPI_FAST_FLASH_BOOT)
Saved PC:0x40381972
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5810,len:0x438
load:0x403cc710,len:0x90c
load:0x403ce710,len:0x2624
entry 0x403cc710
ESP32-C3 ESP-NOW Enhanced (with Debug Log)
Commands: PAIR xx:xx:..., CLEAR, AT+RESTART, HELP, AT+MAC, AT+FRIEND
>>> MY MAC: 1C:DB:D4:CD:CE:C0 <<<
---- 已发送 utf8 编码消息: "HELP\n" ----
Commands:
PAIR xx:xx:xx:xx:xx:xx
CLEAR
AT+RESTART
AT+MAC
AT+FRIEND
---- 已发送 utf8 编码消息: "PAIR 0C:4E:A0:68:6A:78\n" ----
✅ Paired and saved!
📤 Sent: 1C:DB:D4:CD:CE:C0,21.7
📤 Sent: 1C:DB:D4:CD:CE:C0,22.2
📤 Sent: 1C:DB:D4:CD:CE:C0,22.4
📤 Sent: 1C:DB:D4:CD:CE:C0,22.1
📤 Sent: 1C:DB:D4:CD:CE:C0,22.2
正常通讯连接就是两个设备交替闪烁
数传输出效果,正常100m没有问题,打印效果如下
5. 豆包大模型辅助开发技巧
5.1 代码生成
当你需要实现某个功能时,可以向豆包大模型描述你的需求,例如:
请帮我生成ESP32C3的ESPNOW双向通讯代码,包含设备配对、数据发送接收、LED状态指示功能。
豆包会根据你的需求生成完整的代码,并提供详细的注释和说明。
5.2 问题解决
在开发过程中遇到问题时,可以向豆包提问,例如:
ESP32C3的ESPNOW连接不稳定,经常断开连接,如何解决?
豆包会分析可能的原因,并提供解决方案。
5.3 代码优化
当你有了初步的代码后,可以向豆包请求代码优化建议,例如:
请帮我优化以下ESP32C3的ESPNOW代码,提高连接稳定性和数据传输效率。
豆包会分析你的代码,并提供具体的优化建议。
6. 总结
通过本文的介绍,我们学习了如何使用豆包大模型辅助开发ESP32C3的ESPNOW双向通讯系统。主要实现了以下功能:
- 设备配对:通过串口命令实现两个ESP32C3设备的配对
- 数据传输:实现了设备间的双向数据传输
- 状态指示:通过LED闪烁指示设备连接状态
- 自动重连:设备重启后自动加载配对信息,恢复连接
- 调试功能:提供了丰富的调试信息和命令接口
结合豆包大模型的强大能力,我们可以更高效地开发ESP32项目,快速解决遇到的技术问题,提高代码质量和开发效率。
未来,我们可以进一步扩展这个系统,添加更多传感器数据采集、远程控制等功能,实现更复杂的物联网应用场景。
项目源码:GitHub仓库链接
参考资料:
- ESP32官方文档:https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/index.html
- Arduino ESP-NOW库文档:https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/ESPNow
- 豆包大模型:https://www.volcengine.com/product/doubao
希望本文对您的ESP32C3开发有所帮助!如果您有任何问题或建议,欢迎在评论区留言。😘😘😘💕💕💕
更多推荐



所有评论(0)