1.主要思想
? ? ? ? 前期已學習如何用ESP8266連接WIFI,并發送數據到服務器。現在只需要在單片機與nodeMCU之間建立起串口通信,這樣單片機就可以將傳感器測到的數據:光照,溫度,濕度等等傳遞給8266了,然后8266再對數據進行打包,發送到服務器。
? ? ? ? 51單片機和nodeMCU的連線方式如下
????????它們串口的兩根線交叉連接,二者的USB供電端一起接在電腦的USB口上。如果它們不是用的同一套供電系統,就需要注意共地的問題!?
2.代碼設計
51單片機的主體代碼大致如下;
主要就是測量一些數據,然后通過串口發送到nodeMCU
?nodeMCU的代碼如下:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
const char* ssid = "iPhone"; //WIFI名稱 自己補上你的WIFI
const char* password = "12345678"; //WIFI密碼 自己補上你的密碼
const char* mqtt_server = "broker-cn.emqx.io"; //mqtt服務器地址 (IP/域名) 不改
const char *pubTopic="my_pubtopic";
const char *subTopic="my_subtopic";WiFiClient espClient;
PubSubClient client(espClient);char information[80]="";
int value = 0;void setup_wifi() {delay(10);// We start by connecting to a WiFi networkSerial.println();Serial.print("Connecting to ");Serial.println(ssid);WiFi.mode(WIFI_STA);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}randomSeed(micros());Serial.println("");Serial.println("WiFi connected");Serial.println("IP address: ");Serial.println(WiFi.localIP());
}void callback(char* topic, byte* payload, unsigned int length) {String cmd="";for (int i = 0; i < length; i++) {cmd+=(char)payload[i];}const size_t capacity = JSON_OBJECT_SIZE(1) + 10; //計算buffer的大小 ...SIZE(1)表明buffer中只有一個對象DynamicJsonBuffer jsonBuffer(capacity); //創建動態的jsonbufferJsonObject& root = jsonBuffer.parseObject(cmd); //解析Json對象字符串Serial.println("get");if(root.containsKey("led")) //判斷是否包含某個鍵{int led = root["led"]; if(led==1){Serial.println("1");}elseSerial.println("2");}if(root.containsKey("beep")) //判斷是否包含某個鍵{int beep = root["beep"]; if(beep==1){Serial.println("3");}elseSerial.println("4");}
}void reconnect() {// Loop until we're reconnectedwhile (!client.connected()) {Serial.print("Attempting MQTT connection...");// Create a random client IDString clientId = "ESP8266Client-";clientId += String(random(0xffff), HEX);// Attempt to connectif (client.connect(clientId.c_str())) {Serial.println("connected");// Once connected, publish an announcement...client.publish(pubTopic, "hello world");// ... and resubscribeclient.subscribe(subTopic);} else {Serial.print("failed, rc=");Serial.print(client.state());Serial.println(" try again in 5 seconds");// Wait 5 seconds before retryingdelay(5000);}}
}void setup() {Serial.begin(9600);setup_wifi();client.setServer(mqtt_server, 1883);client.setCallback(callback);
}void loop() {if (!client.connected()) {reconnect();}client.loop();value=0;while(!Serial.available()); //等待數據傳送過來,若沒有數據,一直等待,即執行到本行不向下執行while(Serial.available()){ information[value]=(char)Serial.read(); value++; delay(3);}client.publish(pubTopic, information); Serial.print(information);// }
}
3.注意實現
51單片機發送給nodeMCU的數據,全部存在了這個數組里面
所以這個數組要足夠大,至少要大于你發送的內容。不然就會導致nodeMCU出現堆棧溢出的錯誤。(本人在這里卡了好幾個小時)? 希望大家可以避免類似的錯誤
在nodeMCU將數據發送到服務器的同時,可以使用nodeMCU的串口,將數據打印出來,方便調試,看看是否正確的接收到了數據。如下圖所示,這種是正確接收的效果。
如果通信出現錯誤,沒有準確接收,那么它會顯示一群亂碼,根本看不清楚是什么!!!
如果你發現你接收到的數據總是不準確,或者總是有亂碼,可以嘗試調整這個延時時間
4.最終效果?
如上圖所示,服務器已經可以成功接收到單片機發送的數據了!!!
此時,只需要開發一個MQTT協議的手機APP,就可以實現單片機數據在手機上顯示的效果!?