分为以下部分:
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 接地
1 2 3 4 5 6 7 8 9
| 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,返回版本等信息
如下:

至此,可以验证连接成功。
1 2 3 4 5 6 7 8
| 一些其他常用的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)相连,反之亦如此
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #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
1 2 3 4 5 6 7 8 9 10 11
| 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测试服务是否正常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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()
|
1 2 3 4 5 6 7 8 9 10 11
| 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。
最终实现效果及代码:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
| #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); 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; mqttMessage[4] = 77; mqttMessage[5] = 81; mqttMessage[6] = 84; mqttMessage[7] = 84; mqttMessage[8] = 4; mqttMessage[9] = 130; mqttMessage[10] = 0; mqttMessage[11] = 60; mqttMessage[12] = (0xff00 & clientIdLen)>>8; 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; mqttMessage[baseIndex++] = 0xff & UserNameLen; for(u8 i = 0; i < UserNameLen ; i++){ mqttMessage[baseIndex + i] = *((u8*)"hausa" + i); }
baseIndex = 14 + clientIdLen + UserNameLen; mqttMessage[baseIndex++] = (0xff00 & UserNameLen)>>8; mqttMessage[baseIndex++] = 0xff & UserNameLen; 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。再然后怎么不做一套智能家居?:-P
:-)