分为以下部分:
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/