ARDUINO UNO --> 8266(使用软串口连接)
数字端口8(RX) --> TX
数字端口9(TX) --> RX
3V3 --> VCC
GND --> GND
GND --> CHPD
想让ARDUINO UNO使用MQTT连接到ONENET,最简单的办法是直接使用ARDUINO IDE或者MICROPYTHON烧录8266,然后ARDUINO UNO通过软串口监听8266的通信。
那么今天来说8266透传的方式,主要还是把具体的逻辑说一下,以便更好地理解MQTT协议的优势。
后面代码的逻辑如下:
1、先用数组形式定义MQTT的协议内容,这个主要是为了方便后面用十六进制方式向ONENET服务器发送数据
2、ARDUINO通过软串口打开8266的透传模式
3、发送MQTT协议
#include
SoftwareSerial mySerial(8, 9); // RX, TX
void (* resetFunc) () = 0;
int v_w_test=0;
int v_w_cnt=0;
int v_w_test_result=0;
int v_w_transfer=0;
int v_w_transfer_result=0;
int v_s_c=0;
int i=0;
int j=0;
int k=0;
unsigned char uart_Receive_Buff [ 80 ]; //定义缓冲buff
unsigned int uart_Receive_Index = 0; //收到的字节实际长度
char Serial_val; // 储存接受数据
unsigned char Serial_val1; // 储存接受数据
String Serial_str="" ; //设置一个空的字符串,用于打印串口输出结果
unsigned char data[42] = {0x10, //上线报头
0x28, //后面的字符数以十六进制表示
0x00,0x04,0x4D,0x51,0x54,0x54, //固定的发送MQTT字符
0x04,0xC2, //固定
0x00,0x78, //上线时间120秒,后面通过心跳来保持这个链接
0x00,0x09,//设备ID长度
0x35,0x36,0x33,0x33,0x32,0x38,0x30,0x37,0x**, //设备ID
0x00,0x06, //产品ID长度
0x32,0x37,0x38,0x36,0x30,0x**, //产品ID
0x00,0x09, //鉴权长度
0x6D,0x71,0x74,0x74,0x62,0x31,0x30,0x32,0x** //鉴权ID
}; //模块上线
unsigned char data_1[2] = {0xC0,0x00 }; //心跳,发送内容是固定的
unsigned char data_2[18] = {0x82,0x10, //订阅报头与后面字符长度
0x00,0x0A, //订阅标题
0x00,0x0B, //订阅长度
0x6D,0x6D,0x6E,0x6E,0x5F,0x74,0x6F,0x70,0x69,0x63,0x31,//订阅内容mmnn_topic1
0x00 //订阅等级
};
void setup()
{ Serial.begin(9600); //串口速率同步
mySerial.begin(9600); //串口速率同比
mySerial.print("+++"); //8266退出串口模式 主要供初始化使用
while ( v_s_c != 5 )
{ delay(1000); Serial.print("*"); v_s_c++;} //等待5秒8266启动时间
v_w_test_result=wifi_test(); //连接状态检测
if(v_w_test_result==5)
{ v_w_transfer_result=wifi_transfer() ;} //启动传输
if(v_w_transfer_result==5)
{Serial.println("INITIALIZATION COMPLETED;"); Serial.println("WIFI TRANSFER OPEN");}
if(v_w_test_result!=5 || v_w_transfer_result!=5) {Serial.println("Resetting Arduino Programmatically"); resetFunc();}
Serial.println("!!!");
}
void loop()
{
if (j<1)
{
for (int i = 0; i < 42; i++)
{
mySerial.write(data[i]);
}
for (int i = 0; i < 18; i++)
{
mySerial.write(data_2[i]);
}
j=1;
}
uart_Receive_Index=0;
while (mySerial.available()>0) //判断软串口是否有待读取数据(字符)
{
Serial_val1 = mySerial.read(); //读取软串口数据(字符)到val变量
uart_Receive_Buff [ uart_Receive_Index ] = Serial_val1; //要判断是否完成传输需要使用字符串,因此将字符连接成字符串
uart_Receive_Index++;
}
for (int i=0; i<20; i++) {Serial.print(uart_Receive_Buff[i],HEX);}
Serial.println();
for (int i=0; i <5; i++ ) { delay(1000); Serial.print("*");} //等待5秒8266启动时间
for (int i=0; i <20; i++ ) {uart_Receive_Buff[i]=0x00;}
if(k == 60) { for (int m = 0; m < 2; m++) { mySerial.write(data_1[m]); } k=0; }
delay(1000);
k++;
}
int wifi_test() //判断WIFI连接状态
{ v_w_test=1; //启动时要搭配5秒延迟使用
while (v_w_test !=5 )
{
switch (v_w_test)
{
case 1: if(1==1)
{ Serial_str=""; mySerial.println("AT+CWJAP?"); v_w_test=2; } break;
case 2: if( Serial_str.indexOf("No AP\r\n\r\nOK")>0)
{ Serial_str=""; mySerial.println("AT+CWJAP=\"whowho\",\"***\""); v_w_test=3; }
if( Serial_str.indexOf("+CWJAP:")>0)
{ v_w_test=3; } break;
case 3: if( Serial_str.indexOf("OK")>0)
{ Serial_str=""; v_w_test=4; } break;
case 4: delay(3000) ;v_w_test=5; break;
default : break;
}
while (mySerial.available()>0) //判断软串口是否有待读取数据(字符)
{
Serial_val = mySerial.read(); //读取软串口数据(字符)到val变量
Serial_str += Serial_val; //要判断是否完成传输需要使用字符串,因此将字符连接成字符串
Serial.print(Serial_val); //依次打印val每个字符
}
if ( Serial_str.indexOf("FAIL")>0 || Serial_str.indexOf("busy")>0 )
{delay(1000) ; if (v_w_test!=9) {Serial_str=""; mySerial.println("AT+RST"); v_w_test=9;} }
if ( v_w_test==9 )
{delay(1000) ; v_w_cnt++; if (Serial_str.indexOf("OK")>0) {Serial_str=""; v_w_test=1; v_w_cnt=0; } }
if ( v_w_test==9 && v_w_cnt>=30)
{ if (1==1) {Serial_str=""; v_w_test=8; v_w_cnt=0; } }
if (millis()>60000) {Serial.println("Resetting Arduino Programmatically"); resetFunc();}
}
Serial_str="";
return v_w_test;
}
int wifi_transfer() //开启透传函数
{ v_w_transfer=1;
while (v_w_transfer !=5 )
{
switch (v_w_transfer)
{
case 1: if(1==1)
{ Serial_str=""; mySerial.println("AT+CIPSTART=\"TCP\",\"183.230.40.39\",6002"); v_w_transfer=2; } break;
case 2: if( Serial_str.indexOf("OK")>0 || Serial_str.indexOf("ALREADY CONNECTED")>0 )
{ Serial_str=""; mySerial.println("AT+CIPMODE=1"); v_w_transfer=3; } break;
case 3: if( Serial_str.indexOf("OK")>0)
{ Serial_str=""; mySerial.println("AT+CIPSEND"); v_w_transfer=4; } break;
case 4: delay(3000); v_w_transfer=5; break;
default : break;
}
while (mySerial.available()>0) //判断软串口是否有待读取数据(字符)
{
Serial_val = mySerial.read(); //读取软串口数据(字符)到val变量
Serial_str += Serial_val; //要判断是否完成传输需要使用字符串,因此将字符连接成字符串
Serial.print(Serial_val); //依次打印val每个字符
}
if (millis()>120000) {Serial.println("Resetting Arduino Programmatically"); resetFunc();}
}
Serial_str="";
return v_w_transfer;
}