Arduino教程传送门🧭🏔🌋🛤🏞🏜
- 1. 简介
- 2. 实验准备
- 2.1 硬件
- 2.2 软件
- 3. 实验步骤
- 3.1 TCP点灯实验
- 3.2 MQTT发送温湿度
- 3.3 OTA指令升级
- 4. 总结
1. 简介关于巴法云
专注于开源,智造,创新,分享。关注硬件与创新,突破技术极限,面向未来,我们是认真的。
崇尚开源,发掘未知。 ————巴法科技
ESP8266-NodeMCU的环境配置已经在一篇文章有所交代,接下让我们开启巴法云的物联网开发吧!😀😀😀
2. 实验准备设计目标
- 实现esp8266自动配网;
- 实现ESP8266通过TCP协议连接巴法云的TCP创客云,串口发送指令控制LED的亮灭;
- 实现ESP8266通过MQTT协议连接巴法云的MQTT设备云;串口发送指令控制LED的亮灭,还实现DHT11温湿度数据的获取,并将数据上发巴法云平台,在线显示数据;
- 实现巴法云平台对ESP8266的OTA指令升级,基于前面两个实验。
本次需要做三个实验,分别是TCP点灯实验,MQTT发送温湿度和OTA指令升级,准备工作包括硬件💡💡💡和软件💻💻💻两部分。
2.1 硬件你要实现巴法云的三个实验,你需要准备以下材料✨✨✨
- ESP8266-NodeMCU单片机(外加安卓数据线);
- DHT11温湿度传感器;
- 三根母母杜邦线;
硬件连接:ESP8266-NodeMCU硬件连接非常简单,只需将DHT11数据线接入D6引脚就好,这套连线三个实验都通用,具体接线如下🎀🎀🎀
ESP8266-NodeMCU -----> USB
VCC -----> 3.3V
GND -----> GND
out -----> D2
2.2 软件
- Arduino IED 1.8.5以上(越高越好);
- 浏览器登录巴法云平台。
首先搭建巴法云平台,创建的产品相关主题,检测相关数据流,上传固件和发送指令,以便后期程序端口接入开发。👩👩👩
3.1 TCP点灯实验- 登录巴法云物联网平台,选择控制台,点击TCP创客云,然后新建light002主题,那么巴法云TCP就配置好了🎈
- 程序设计,程序有四部分bemfa02、TCP 、motion和update,其中:🎈🎈
文件名 | 功能 |
---|---|
bemfa02 | 程序初始化调用和主程序调用; |
TCP | 发送数据到TCP服务器,初始化wifi连接,初始化和服务器建立连接; |
motion | 检查数据,发送心跳,检查WiFi; |
update | 固件升级函数。 |
bemfa02.ino
/*
* 智能语言控制控制,支持天猫、小爱、小度、google Assistent同时控制
* Time:20211127
* Author: 2345VOR
* 项目实例:发送on、off的指令开关灯
* 参考文献:https://bbs.bemfa.com/84/last
*/
#include
#include
#define server_ip "bemfa.com" //巴法云服务器地址默认即可
#define server_port "8344" //服务器端口,tcp创客云端口8344
//********************需要修改的部分*******************//
#define wifi_name "J09 502" //WIFI名称,区分大小写,不要写错
#define wifi_password "qwertyuiop111" //WIFI密码
String UID = "e8882ae28d5bde39766c330ea913fd46"; //用户私钥,可在控制台获取,修改为自己的UID
String TOPIC = "light002"; //主题名字,可在控制台新建
const int LED_Pin = D4; //单片机LED引脚值,D2是NodeMcu引脚命名方式,其他esp8266型号将D2改为自己的引脚
String upUrl = "http://bin.bemfa.com/b/3BcZTg4ODJhZTI4ZDViZGUzOTc2NmMzMzBlYTkxM2ZkNDY=light002.bin";//固件链接,在巴法云控制台复制、粘贴到这里即可
//**************************************************//
//最大字节数
#define MAX_PACKETSIZE 512
//设置心跳值30s
#define KEEPALIVEATIME 30*1000
//tcp客户端相关初始化,默认即可
WiFiClient TCPclient;
String TcpClient_Buff = "";//初始化字符串,用于接收服务器发来的数据
unsigned int TcpClient_BuffIndex = 0;
unsigned long TcpClient_preTick = 0;
unsigned long preHeartTick = 0;//心跳
unsigned long preTCPStartTick = 0;//连接
bool preTCPConnected = false;
//相关函数初始化
//连接WIFI
void doWiFiTick();
void startSTA();
//TCP初始化连接
void doTCPClientTick();
void startTCPClient();
void sendtoTCPServer(String p);
//led控制函数,具体函数内容见下方
#define turnOnLed() digitalWrite(LED_Pin,LOW);
#define turnOffLed() digitalWrite(LED_Pin,HIGH);
// 初始化,相当于main 函数
void setup() {
Serial.begin(115200);
pinMode(LED_Pin,OUTPUT);
digitalWrite(LED_Pin,HIGH);
Serial.println("Beginning...");
}
//循环
void loop() {
doWiFiTick();
doTCPClientTick();
}
TCP.ino
/*
*发送数据到TCP服务器
*/
void sendtoTCPServer(String p){
if (!TCPclient.connected())
{
Serial.println("Client is not readly");
return;
}
TCPclient.print(p);
}
/*
*初始化wifi连接
*/
void startSTA(){
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(wifi_name, wifi_password);
}
/*
*初始化和服务器建立连接 : color:#9A9A9A;
*/
void startTCPClient(){
if(TCPclient.connect(server_ip, atoi(server_port))){
Serial.print("\nConnected to server:");
Serial.printf("%s:%d\r\n",server_ip,atoi(server_port));
String tcpTemp=""; //初始化字符串
tcpTemp = "cmd=1&uid="+UID+"&topic="+TOPIC+"\r\n"; //构建订阅指令
sendtoTCPServer(tcpTemp); //发送订阅指令
tcpTemp="";//清空
/*
//如果需要订阅多个主题,可再次发送订阅指令
tcpTemp = "cmd=1&uid="+UID+"&topic="+主题2+"\r\n"; //构建订阅指令
sendtoTCPServer(tcpTemp); //发送订阅指令
tcpTemp="";//清空
*/
preTCPConnected = true;
preHeartTick = millis();
TCPclient.setNoDelay(true);
}
else{
Serial.print("Failed connected to server:");
Serial.println(server_ip);
TCPclient.stop();
preTCPConnected = false;
}
preTCPStartTick = millis();
}
motion.ino
/*
*检查数据,发送心跳
*/
void doTCPClientTick(){
//检查是否断开,断开后重连
if(WiFi.status() != WL_CONNECTED) return;
if (!TCPclient.connected()) {//断开重连
if(preTCPConnected == true){
preTCPConnected = false;
preTCPStartTick = millis();
Serial.println();
Serial.println("TCP Client disconnected.");
TCPclient.stop();
}
else if(millis() - preTCPStartTick > 1*1000)//重新连接
startTCPClient();
}
else
{
if (TCPclient.available()) {//收数据
char c =TCPclient.read();
TcpClient_Buff +=c;
TcpClient_BuffIndex++;
TcpClient_preTick = millis();
if(TcpClient_BuffIndex>=MAX_PACKETSIZE - 1){
TcpClient_BuffIndex = MAX_PACKETSIZE-2;
TcpClient_preTick = TcpClient_preTick - 200;
}
preHeartTick = millis();
}
if(millis() - preHeartTick >= KEEPALIVEATIME){//保持心跳
preHeartTick = millis();
Serial.println("--Keep alive:");
sendtoTCPServer("ping\r\n"); //发送心跳,指令需\r\n结尾,详见接入文档介绍
}
}
if((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick>=200))
{
TCPclient.flush();
Serial.print("Rev string: ");
TcpClient_Buff.trim(); //去掉首位空格
Serial.println(TcpClient_Buff); //打印接收到的消息
String getTopic = "";
String getMsg = "";
if(TcpClient_Buff.length() > 15){//注意TcpClient_Buff只是个字符串,在上面开头做了初始化 String TcpClient_Buff = "";
//此时会收到推送的指令,指令大概为 cmd=2&uid=xxx&topic=light002&msg=off
int topicIndex = TcpClient_Buff.indexOf("&topic=")+7; //c语言字符串查找,查找&topic=位置,并移动7位,不懂的可百度c语言字符串查找
int msgIndex = TcpClient_Buff.indexOf("&msg=");//c语言字符串查找,查找&msg=位置
getTopic = TcpClient_Buff.substring(topicIndex,msgIndex);//c语言字符串截取,截取到topic,不懂的可百度c语言字符串截取
getMsg = TcpClient_Buff.substring(msgIndex+5);//c语言字符串截取,截取到消息
Serial.print("topic:------");
Serial.println(getTopic); //打印截取到的主题值
Serial.print("msg:--------");
Serial.println(getMsg); //打印截取到的消息值
}
if(getMsg == "on"){ //如果收到指令on==打开灯
turnOnLed();
}else if(getMsg == "off"){ //如果收到指令off==关闭灯
turnOffLed();
}else if(getMsg == "update"){ //如果收到指令update
updateBin();//执行升级函数
}
TcpClient_Buff="";
TcpClient_BuffIndex = 0;
}
}
/**************************************************************************
WIFI
***************************************************************************/
/*
WiFiTick
检查是否需要初始化WiFi
检查WiFi是否连接上,若连接成功启动TCP Client
控制指示灯
*/
void doWiFiTick(){
static bool startSTAFlag = false;
static bool taskStarted = false;
static uint32_t lastWiFiCheckTick = 0;
if (!startSTAFlag) {
startSTAFlag = true;
startSTA();
}
//未连接1s重连
if ( WiFi.status() != WL_CONNECTED ) {
if (millis() - lastWiFiCheckTick > 1000) {
lastWiFiCheckTick = millis();
}
}
//连接成功建立
else {
if (taskStarted == false) {
taskStarted = true;
Serial.print("\r\nGet IP Address: ");
Serial.println(WiFi.localIP());
startTCPClient();
}
}
}
update.ino
/**
* 固件升级函数
* 在需要升级的地方,加上这个函数即可,例如setup中加的updateBin();
* 原理:通过http请求获取远程固件,实现升级
*/
void updateBin(){
Serial.println("start update");
WiFiClient UpdateClient;
t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateClient, upUrl);
switch(ret) {
case HTTP_UPDATE_FAILED: //当升级失败
Serial.println("[update] Update failed.");
break;
case HTTP_UPDATE_NO_UPDATES: //当无升级
Serial.println("[update] Update no Update.");
break;
case HTTP_UPDATE_OK: //当升级成功
Serial.println("[update] Update ok.");
break;
}
}
-
修改bemfa02主程序对应wifi和巴法云参数,upUrl参数可以暂时不修改,实验三再修改🎈🎈🎈
-
编译程序,然后上传esp8266,观察esp8266和巴法云TCP控制台🎈🎈🎈🎈
-
实验效果:在订阅的“light002”主题下,发送on或者off,可见esp8266板载灯分别会亮灭。🎈🎈🎈🎈🎈
-
登录巴法云物联网平台,选择控制台,点击MQTT设备云,然后新建led002控制端和temp004状态端主题,那么巴法云MQTT设备云就配置好了🎈
-
程序设计,程序有四部分dht11_led_OTA1.0、OTA(update)PubSubClient.cpp和PubSubClient.h,其中:🎈🎈
文件名 | 功能 |
---|---|
dht11_led_OTA1.0 | 程序初始化调用和主程序调用,自动连接目标wifi,重新连接,led002的回调函数处理; |
OTA(update) | 固件升级函数。 |
dht11_led_OTA1.0.ino
/*
Time:20211127
Author: 2345VOR
项目示例:通过MQTT协议发送on或off控制开关,温湿度上传巴法云
参考文献:https://www.cnblogs.com/bemfa/p/14590133.html
*/
#include //默认,加载WIFI头文件
#include "PubSubClient.h"//默认,加载MQTT库文件
#include //自动升级库 https://bbs.bemfa.com/84
#include //dht11库文件
String upUrl = "http://bin.bemfa.com/b/1BcZTg4ODJhZTI4ZDViZGUzOTc2NmMzMzBlYTkxM2ZkNDY=led002.bin";
const char* ssid = "J09 502"; //修改,修改为你的路由的WIFI名字
const char* password = "qwertyuiop111"; //修改为你的WIFI密码
const char* mqtt_server = "bemfa.com"; //默认,MQTT服务器地址
const int mqtt_server_port = 9501; //默认,MQTT服务器端口
#define ID_MQTT "e8882ae28d5bde39766c330ea913fd46" //mqtt客户端ID,修改为你的开发者密钥
const char* topic = "led002"; //Led主题名字,可在巴法云控制台自行创建,名称随意
const char * dhttopic = "temp004"; //温湿度主题名字,可在巴法云mqtt控制台创建
int pinDHT11 = D2; //dht11传感器引脚输入
int B_led = D4; //控制的led引脚
long timeval = 3 * 1000; //上传的传感器时间间隔,默认3秒
#define ledstatus !digitalRead(B_led);//led状态默认0
long lastMsg = 0;//时间戳
SimpleDHT11 dht11(pinDHT11);//dht11初始化
WiFiClient espClient;
PubSubClient client(espClient);//mqtt初始化
//灯光函数及引脚定义
#define turnOnLed() digitalWrite(B_led, LOW);
#define turnOffLed() digitalWrite(B_led, HIGH);
//自动连接目标wifi
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
//重新连接
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(ID_MQTT)) {//连接mqtt
Serial.println("connected");
client.subscribe(topic);//修改,修改为你的主题
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
pinMode(B_led, OUTPUT);
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, mqtt_server_port);
client.setCallback(callback);
digitalWrite(B_led, HIGH);
}
void loop() {
if (!client.connected()) {//判断mqtt是否连接
reconnect();
}
client.loop();//mqtt客户端
long now = millis();//获取当前时间戳
if (now - lastMsg > timeval) {//如果达到3s,进行数据上传
lastMsg = now;
// read without samples.
byte temperature = 0;
byte humidity = 0;
int err = SimpleDHTErrSuccess;
if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
Serial.print("Read DHT11 failed, err="); Serial.println(err); delay(1000);
return;
}
String msg = "#" + (String)temperature + "#" + (String)humidity + "#" + ledstatus; //数据封装#温度#湿度#开关状态#
client.publish(dhttopic, msg.c_str());//数据上传
}
}
//topic = "led002"的回调函数处理
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
String Mqtt_Buff = "";
for (int i = 0; i < length; i++) {
Mqtt_Buff += (char)payload[i];
}
Serial.print(Mqtt_Buff);
Serial.println();
// Switch on the LED if an 1 was received as first character
if (Mqtt_Buff == "on") {//如果接收字符on,亮灯
turnOnLed();//开灯函数
} else if (Mqtt_Buff == "off") {//如果接收字符off,亮灯
turnOffLed();//关灯函数
}else if (Mqtt_Buff == "update") {//如果接收字符off,亮灯
client.disconnect(); //关闭mqtt
delay(100);
updateBin(); //开始升级
}
Mqtt_Buff = "";
}
OTA(update).ino
/**
* 固件升级函数
* 在需要升级的地方,加上这个函数即可,例如setup中加的updateBin();
* 原理:通过http请求获取远程固件,实现升级
*/
void updateBin(){
Serial.println("start update");
WiFiClient UpdateClient;
t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateClient, upUrl);
switch(ret) {
case HTTP_UPDATE_FAILED: //当升级失败
Serial.println("[update] Update failed.");
break;
case HTTP_UPDATE_NO_UPDATES: //当无升级
Serial.println("[update] Update no Update.");
break;
case HTTP_UPDATE_OK: //当升级成功
Serial.println("[update] Update ok.");
break;
}
}
PubSubClient.cpp
PubSubClient.h
(略)
-
修改dht11_led_OTA1.0主程序对应wifi和巴法云参数,upUrl参数可以暂时不修改,实验三再修改🎈🎈🎈
-
编译程序,然后上传esp8266,观察esp8266和巴法云MQTT控制台🎈🎈🎈🎈
-
实验效果:在订阅的“led002”主题下,发送on或者off,可见esp8266板载灯分别会亮灭;然后点击temp004主题的更多设置,。🎈🎈🎈🎈🎈
实验效果如GIF😅😅😅
- OTA升级控制图
将刚刚两组实验联系起来,实现远程升级固件,通俗讲就是当你配置好实验一,在lighr002输入update指令就可以远程升级到实验二,反而言之也可以。🤩🤩🤩
- 关于上文实验一中的upUrl填写,先生成要升级(实验二)的bin文件,导入到TCP创客云的light002的OTA固件;关于上文实验二中的upUrl填写,先生成要升级(实验一)的bin文件,导入到MQTT设备云的led002的OTA固件,把生成的固件地址复制到对应的实验一的upUrl位置(地址不会变,固件会自动迭代更新)
OTA配置好后,重新下载实验一的代码,然后再TCP创客云的light002主题测试on、off和update指令,输入update就会自动升级到实验二代码,可以到MQTT设备云的led002主题下,测试on、off和update指令,这就是实验一和实验二的梦幻 *** 作!😁😀😂实验一效果如下:
- 期待大家可以消化代码并且半天实现OTA升级**本文是一个难度中等的物联网项目,实现E实现esp8266自动配网;TCP协议连接巴法云的TCP创客云,串口发送指令控制LED的亮灭;实现ESP8266通过MQTT协议连接巴法云的MQTT设备云;串口发送指令控制LED的亮灭,还实现DHT11温湿度数据的获取,并将数据上发巴法云平台,在线显示数据;实现巴法云平台对ESP8266的OTA指令升级,基于前面两个实验** 😁😁😁
- 在以后的博文中我们将学会用ESP8266做常用的物联网开发,从而实现对外部世界进行感知,充分认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。
- 参考链接:
第一个链接十分有用,主要参考代码,期待大家都可以实现!🎉🎉🎉 - esp8266 OTA远程无线升级
- (开源)微信小程序+mqtt+esp8266,温湿度实时显示
- 利用天猫精灵控制ESP8266(NodeMCU开发板)arduino ide开发
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)