提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、前期准备
- 1.1 硬件配置
- 1.2 软件环境配置
- 二、接线
- 三、核心代码
- 3.1 总代码
- 三、最终效果
- 总结
前言
本系列将以0基础新手视角,完整演示Arduino+ESP8266连接OneNET云平台的全流程,涵盖ESP8266固件烧录、物模型的模型设计、MQTT协议配置及代码实现。建议搭配Arduino IDE 2.0+和Arduino开发板使用。
(二)本文为arduino连接ESP8266(ESP-01S)
前文为,ESP8266模块的测试以及MQTT固件的烧录,不可缺少。
一、前期准备
1.1 硬件配置
需准备Arduino开发板 和 ESP8266
1.2 软件环境配置
安装Arduino IDE 2.0.2
安装 EspSoftwareSerial 库(工具→库管理→搜索EspSoftwareSerial→安装)
二、接线
注:arduino的 5V 给ESP8266的3.3V 供电,不然电压可能不够。
代码中的这句话是指 arduino的软串口,RX为9,TX为10;此时我们用ESP8266的TX接9,RX接10
SoftwareSerial espSerial(9, 10); // RX=9, TX=10 注意前面的是指arduino的TRX,连线时候ESP8266的TX应接9,RX接10
arduino uno | ESP8266 |
---|---|
5V | 3.3V 和 EN(即CH_PD) |
10 | RX |
9 | TX |
GND | GND |
再从 引脚5 引出一根导线,连接 小电阻→LED灯→GND
以备之后测试云平台下发
三、核心代码
3.1 总代码
替换
const char* WIFI_SSID = "Xiaomi 15";
const char* WIFI_PWD = "147258369";
// OneNET参数
#define PRODUCT_ID "1SX9Lm39T5"
#define DEVICE_NAME "arduino"
#define TOKEN "version=2018-10-31&res=products%2F1SX
代码:
#include <SoftwareSerial.h>
#include <ArduinoJson.h>// 网络配置
const char* WIFI_SSID = "Xiaomi 15";
const char* WIFI_PWD = "147258369";
const char* MQTT_SERVER = "mqtts.heclouds.com";// OneNET 物联参数
const int MQTT_PORT = 1883;
#define PRODUCT_ID "1SX9Lm39T5"
#define DEVICE_NAME "arduino"
#define TOKEN "version=2018-10-31&res=products%2F1SX9Lm39T5%2Fdevices%2Farduino&et=2059472864&method=md5&sign=F5DI%2FHUhIdIeZx1CUsR%2ByQ%3D%3D"
// 硬件配置
SoftwareSerial espSerial(9, 10); // RX=9, TX=10 注意前面的是指arduino的TRX,连线时候ESP8266的TX应接9,RX接10
#define TLED_PIN 5 // LED控制引脚// 全局变量
const unsigned long readInterval = 3000;// 数据上报周期(ms)
int postMsgId = 0; // 消息序列号
float temp = 20.25; // 温度值
bool TLED_state = true; // LED开关状态//前置函数声明
bool sendATCommand(const char* cmd, const char* ack, unsigned int timeout);void initESP8266();
void initSwitch();
void Post_Sensor();
void Post_Switch();void setup() {Serial.begin(9600); // 调试串口espSerial.begin(9600); // ESP8266通信initESP8266();initSwitch();}
void loop() {handleMQTTMessage();// 定时上传数据static unsigned long lastPost = 0;if (millis() - lastPost >= readInterval) {Post_Switch();// Post_Sensor();lastPost = millis();}
}// AT指令发送函数(带超时检测)
bool sendATCommand(const char* cmd, const char* ack, unsigned int timeout) {espSerial.println(cmd);unsigned long start = millis();String response;while (millis() - start < timeout) {while (espSerial.available()) {char c = espSerial.read();response += c;}if (response.indexOf(ack) != -1) {Serial.print("[SUCCESS] ");Serial.println(cmd);return true;}}Serial.print("[ERROR] ");Serial.print(cmd);Serial.println(" 未收到预期响应");return false;
}void initESP8266(){// 初始化ESP8266sendATCommand("AT", "OK", 2000);
// sendATCommand("AT+RST", "ready", 8000); sendATCommand("AT+CWMODE=1", "OK", 1000);sendATCommand("AT+CWDHCP=1,1", "OK", 1000);// 连接WiFiString cmd = "AT+CWJAP=\"" + String(WIFI_SSID) + "\",\"" + String(WIFI_PWD) + "\"";sendATCommand(cmd.c_str(), "OK", 5000);\// 配置MQTTString mqttCfg = "AT+MQTTUSERCFG=0,1,\"" + String(DEVICE_NAME) + "\",\"" + String(PRODUCT_ID) + "\",\"" + String(TOKEN) + "\",0,0,\"\"";sendATCommand(mqttCfg.c_str(), "OK", 5000);// 连接服务器String connCmd = "AT+MQTTCONN=0,\"" + String(MQTT_SERVER) + "\"," + String(MQTT_PORT) + ",1";sendATCommand(connCmd.c_str(), "OK", 5000);// 添加订阅命令(在MQTT连接成功后)String subscribeCmd = "AT+MQTTSUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME) + "/thing/property/set\",1";sendATCommand(subscribeCmd.c_str(), "OK", 2000);
}void initSwitch(){pinMode(TLED_PIN, OUTPUT);digitalWrite(TLED_PIN, TLED_state);
}void Post_Sensor(){postMsgId++;// 手动拼接字符串,双引号 \",逗号 \,,符合 ESP8266 的 AT 命令转义要求String jsonPayload = "\\\"id\\\":\\\"" + String(postMsgId) + "\\\"\\,"+ "\\\"version\\\":\\\"1.0\\\"\\,"+ "\\\"params\\\":{"+ "\\\"temp\\\":{\\\"value\\\":" + String(temp, 2) + "}\\,"+ "\\\"TLED\\\":{\\\"value\\\":" + (TLED_state ? "true" : "false") + "}"+ "}";jsonPayload = "{" + jsonPayload + "}";// 构造 MQTT 发布命令String pubCmd = "AT+MQTTPUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME)+ "/thing/property/post\",\"" + jsonPayload + "\",0,0";// 发送sendATCommand(pubCmd.c_str(), "OK", 3000);
}void Post_Switch(){postMsgId++;// 手动拼接字符串,双引号 \",逗号 \,,符合 ESP8266 的 AT 命令转义要求String jsonPayload = "\\\"id\\\":\\\"" + String(postMsgId) + "\\\"\\,"+ "\\\"version\\\":\\\"1.0\\\"\\,"+ "\\\"params\\\":{"+ "\\\"temp\\\":{\\\"value\\\":" + String(temp, 2) + "}\\,"+ "\\\"TLED\\\":{\\\"value\\\":" + (TLED_state ? "true" : "false") + "}"+ "}";jsonPayload = "{" + jsonPayload + "}";// 构造 MQTT 发布命令String pubCmd = "AT+MQTTPUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME)+ "/thing/property/post\",\"" + jsonPayload + "\",0,0";// 发送sendATCommand(pubCmd.c_str(), "OK", 3000);}// 接收数据函数 ▼
void handleMQTTMessage() {while (espSerial.available()) {String message = espSerial.readStringUntil('\n');if (message.indexOf("+MQTTSUBRECV:") != -1) { // 检测到新消息Serial.print("收到原始消息:"); Serial.println(message); // 调试输出// 提取JSON部分int jsonStart = message.indexOf('{');String jsonStr = message.substring(jsonStart);JsonDocument doc;DeserializationError error = deserializeJson(doc, jsonStr);if (!error) {if (doc["params"]["TLED"].as<bool>()) {digitalWrite(TLED_PIN, HIGH);TLED_state = true;Serial.println("✅ 已开灯");} else {digitalWrite(TLED_PIN, LOW);TLED_state = false;Serial.println("✅ 已关灯");}// 回复 set 指令int id = doc["id"] | 0; // 取出id进行回复(可选)String replyJson = String("{\\\"id\\\":\\\"") + id + "\\\",\\\"code\\\":200}";String cmd = "AT+MQTTPUB=0,\"$sys/" + String(PRODUCT_ID) + "/" + String(DEVICE_NAME) + "/thing/property/set/reply\",\"" + replyJson + "\",0,0";sendATCommand(cmd.c_str(), "OK", 1000);} else {Serial.println("[ERROR] JSON解析失败");}}}
}
三、最终效果
串口上,会出现几个error,属于正常情况,如响应超时等
后续出现的success,就代表上传成功
若有问题,则重复上篇文章,使用USB转TTL,进行AT指令测试
总结
本文搭建了 基于Arduino的ESP8266连接OneNET云平台(MQTT协议 物模型)。