ArduinoUNO+ESP8266實現MQTT簡單發佈(不燒錄ESP8266)

分爲以下部分:
1:接線並使用AT指令驗證連接
2:使用軟串口
3:搭建/配置/測試MQTT服務端
4:在Arduino實現MQTT的PUB客戶端
5:總結





接線並使用AT指令驗證連接

需要各種線+10k電阻*1
ESP8266的3V3/VCC 接到 3.3V
ESP8266的EN 串聯一個10k電阻 接到3.3V
ESP8266的RX 接到 Arduino的RX0
ESP8266的TX 接到 Arduino的TX1
ESP8266的GND 接地




//驗證程序
const int tx = 1;
const int rx = 0;
void setup() {
   
    
  pinMode(rx,INPUT_PULLUP);
  pinMode(tx,INPUT_PULLUP);
}
void loop() {
   
    
}

將Serial Monitor調整爲Both NL&CR,115200 baud
輸入AT,ESP8266藍色燈光閃爍,返回OK
輸入AT+GMR,返回版本等信息
如下:
在這裏插入圖片描述
至此,可以驗證連接成功。




一些其他常用的AT命令:
AT+RST 重置wifi模塊
AT+CWLAP 掃AP
AT+CWJAP=”SSID”,”PASSWORD” 連接到AP
AT+CWJAP=””,”” 與所有訪問點斷開連接
AT+CIFSR 顯示獲得的IP和MAC
AT+UART=9600,8,1,0,0 修改波特率等
AT+CWMODE= 設置工作模式,可有Station\AP\Station+AP三種

使用軟串口

修改ESP8266的波特率爲9600
假設將2,3分別作爲RX,TX
則將ESP8266的RX與3(Arduino的TX)相連,反之亦如此
代碼:


#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);
void setup() {
   
     
  Serial.begin(9600);
  mySerial.begin(9600);
  mySerial.println("AT+GMR");
}
void loop() {
   
     
  if(wifiSerial.available()) {
   
     
    Serial.write(wifiSerial.read());
  }
  if(Serial.available()){
   
     
    wifiSerial.write(Serial.read());
  }
}

之後打開Serial Monitor即可看到AT+GMR的執行結果了,也可以使用AT指令查看其他信息。


搭建/配置/測試MQTT服務端

服務器使用Ubuntu+mosquitto

apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
apt-get update
apt-get install mosquitto
cd /etc/mosquitto/conf.d
touch myconfig.conf
vim myconfig.conf
echo allow_anonymous false >> myconfig.conf
echo password_file /etc/mosquitto/pwfile.txt >> myconfig.conf
echo port 1883 >> myconfig.conf
mosquitto_passwd -c /etc/mosquitto/pwfile.txt [username]
service mosquitto start

在雲平臺調整服務器的安全組,放行出入1883端口的數據
使用python測試服務是否正常:

#sub.py
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
    print("Connect result:" + str(rc))
    client.subscribe("test_topic")
def on_message(client, userdata, msg):
    print(msg.topic+":" +str(msg.payload))
client = mqtt.Client("admin_sub")
client.username_pw_set("[username]","[password]")
client.on_connect = on_connect
client.on_message = on_message
print("Connectting…")
client.connect("[IP]", 1883, 60)
client.loop_forever()
#pub.py
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
    print("Connect result:" + str(rc))
def on_message(client, userdata, msg):
    print(msg.topic + " " + str(msg.payload))
client = mqtt.Client("admin_pub")
client.on_connect = on_connect
client.on_message = on_message
client.connect('[IP]', 1883, 60)
client.publish('test_topic', payload='test_pub_content', qos=0)

可以連接/通訊,如圖:
在這裏插入圖片描述


在Arduino實現MQTT的PUB客戶端

網上能找到的資料都需要燒寫ESP8266,因爲怕寫壞自己唯一的板子,所以實現了軟串口+TCP協議的MQTT客戶端,站在別人肩膀上先實現Pub功能。沒有做安全保護0.0。
最終實現效果及代碼:
在這裏插入圖片描述

#include <SoftwareSerial.h>

SoftwareSerial wifiSerial(2, 3);
bool on;

void setup()
{
   
       
  Serial.begin(9600);
  wifiSerial.begin(9600);
  while (!Serial);
  while (!wifiSerial);

  wifiSerial.println("AT+RST");
  on=false;
  while(!on){
   
       
    if(wifiSerial.find("OK")){
   
       
      Serial.println("ESP8266 Resetting");
      on = true;
    }
  }
  on = false;
  delay(5000);  //Give enough time for ESP8266's reset 
  
  connect_wifi();
  delay(1000);
  pub_msg();
}
 
void loop() {
   
       
  if(wifiSerial.available())
    Serial.write(wifiSerial.read());
  if(Serial.available()){
   
       
    wifiSerial.write(Serial.read());
  }
}

void connect_wifi(){
   
       
  wifiSerial.println("AT+RST");
  while(!on){
   
       
    if(wifiSerial.find("ready")){
   
       
      delay(1000);
      on = true;
    }
  }
  clear_serial();
  on=false;
  
  wifiSerial.println("AT+CWMODE=1");
  wifiSerial.println("\"hausahan\",\"[password]\"");
  delay(3000);
  if(wifiSerial.find("OK")){
   
       
      Serial.println("WIFI Connected!");
      delay(1000);
      clear_serial();
      tcp_connect();
  }
}

void tcp_connect(){
   
       
    wifiSerial.println("AT+CIPSTART=\"TCP\",\"114.116.239.164\",1883");
    delay(1000);
    while(!on){
   
       
        on = true;
        if(wifiSerial.find("OK")){
   
       
           Serial.println("TCP Connected!");
        }
    }
    mqtt_connect();
}

void mqtt_connect(){
   
       
   u8 mqttMessage[128]={
   
       0};
   u8 packetLen;
   u8 baseIndex = 0;
   u8 clientIdLen = strlen("arduino_pub");
   u8 UserNameLen = strlen("hausa");
   u8 passwordLen = strlen("[password]");
   packetLen = 16 + clientIdLen + UserNameLen + passwordLen;
   mqttMessage[0] = 16;
   mqttMessage[1] = packetLen - 2;
   mqttMessage[3] = 4;       // Protocol Name Length LSB    
   mqttMessage[4] = 77;      // ASCII Code for M    
   mqttMessage[5] = 81;      // ASCII Code for Q    
   mqttMessage[6] = 84;      // ASCII Code for T    
   mqttMessage[7] = 84;      // ASCII Code for T    
   mqttMessage[8] = 4;       // MQTT Protocol version = 4    
   mqttMessage[9] = 130;     // conn flags 
   mqttMessage[10] = 0;      // Keep-alive Time Length MSB    
   mqttMessage[11] = 60;     // Keep-alive Time Length LSB 
   mqttMessage[12] = (0xff00 & clientIdLen)>>8;// Client ID length MSB
   mqttMessage[13] = 0xff & clientIdLen; 
   for(u8 i = 0; i < clientIdLen; i++){
   
       
        mqttMessage[14 + i] = *((u8*)"arduino_pub" + i);    
   }
   
   baseIndex = 14 + clientIdLen;
   mqttMessage[baseIndex++] = (0xff00 & UserNameLen)>>8; //username length MSB    
   mqttMessage[baseIndex++] = 0xff & UserNameLen;        //username length LSB 
   for(u8 i = 0; i < UserNameLen ; i++){
   
       
      mqttMessage[baseIndex + i] = *((u8*)"hausa" + i);    
   }

   baseIndex = 14 + clientIdLen + UserNameLen;
   mqttMessage[baseIndex++] = (0xff00 & UserNameLen)>>8; //password length MSB    
   mqttMessage[baseIndex++] = 0xff & UserNameLen;        //password length LSB 
   for(u8 i = 0; i < UserNameLen ; i++){
   
       
      mqttMessage[baseIndex + i] = *((u8*)"[password]" + i);    
   }
   
   send_tcp_package(mqttMessage, packetLen);
}

void pub_msg(){
   
       
  u8 mqttMessage[100]={
   
       0};
  u16 i,index=0;  
  u16 topicLen = strlen("test_topic");    
  u16 messageLen = strlen("arduino_say_hi");  

  mqttMessage[index++] = 48;
  mqttMessage[index++] = 2 + topicLen + messageLen;
  mqttMessage[index++] = (0xff00 & topicLen)>>8;
  mqttMessage[index++] = 0xff & topicLen;
  for(i = 0; i < topicLen; i++){
   
       
    mqttMessage[index + i] = *((u8 *)"test_topic" + i);
  }
  index += topicLen;
  for(i = 0; i < messageLen; i++){
   
       
    mqttMessage[index + i] = *((u8*)"arduino_say_hi" + i);
  }

  send_tcp_package(mqttMessage, 4 + topicLen + messageLen);
 
}

void send_tcp_package(u8 *data,u16 len){
   
       
  clear_serial();
  wifiSerial.print("AT+CIPSEND=");
  wifiSerial.println(len);
  delay(500);
  if(wifiSerial.find(">")){
   
       
    for(u16 i=0; i<len; i++)
      wifiSerial.write(data[i]);
    wifiSerial.println();
    delay(500);
  }
}

void clear_serial(){
   
       
  while(wifiSerial.read()>= 0);
  while(Serial.read()>= 0);
}

總結

還是有很多讓人疑惑的問題的,比如:
ESP8266很多指令執行後必須等幾秒才能進行下一步操作。
也有收穫:
每次編程後使用AT+RST進行重置並在燒寫完成後復位Arduino能解決很多奇怪的問題。
更理解通信協議、協議棧、wireshark的使用、、、等知識了
下一步:
考慮多買幾塊8266,學習直接使用8266的方法,因爲看起來好像很方便,並實現一個遠程控制LED的Deeeeeemo。再然後怎麼不做一套智能家居?😛
😃






參考文章
https://blog.csdn.net/Fredric_2014/article/details/89602457
https://blog.csdn.net/anxianfeng55555/article/details/80908795
也歡迎各位來窩的小窩看窩:www.hausahan.cn/iot/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章