前面几节介绍了Mqtt协议以及用ESP8266模块作为客户端连接Mqtt服务器并实现数据的发布和订阅。这一节我们就正式的开始制作第一个物联网终端,基于Arduino和ESP8266模块。之所以选择了Arduino是因为它的开发比较方便,并且后期直接可以自己用Atmega芯片搭建最小系统来实现终端的产品化。
以下就是基于Arudino和ESP8266的自动数据采集和上传终端,前期为了调试数据的需要,我直接使用了Arduino mega2560,因为它有多个串口可以使用,当然Arduino UNO也完全没问题,但是由于只有一个硬串口,而软串口支持不了115200波特率,所以ESP模块只能接在硬串口上了,这就导致前期用UNO来开发就会很麻烦,每次改程序就要拔掉ESP模块。所以直接用了2560开发就方便多了。
硬件的连接非常的简单,我这里将ESP模块接到了串口1上,所以接线为:
Esp8266 Arduino Mega2560
Vcc ------------- 3V3
CH_PD ------------ 3V3
GND ------------- GND
URXD ------------- TXD1
UTXD ------------- RXD1
我上传的数据为模拟口A0采集到的模拟电压值,你可以接一个Lm35温度传感器上去,不过我这里仅仅为了测试Mqtt数据传输,就不接了,所以每次测量出来的数据都是随机的。
下面主要就是程序了,思路也很简单,就是完全模拟上一节时手动输入AT指令和Mqtt指令,只不过交由程序来自动实现罢了,好了,直接看程序吧,具体细节我也直接写在程序的注释里了。
String tcplinkstr = "AT+CIPSTART=\"TCP\",\"10.0.0.252\",1883";
String wifiname = "******";
String wifipsd = "******";
String wifilinkstr, tempstr,constr = "";
unsigned char mqttlink[27] = {0x10, 0x19, 0x00, 0x06, 0x4d, 0x51, 0x49, 0x73, 0x64, 0x70, 0x03, 0xc2, 0x01, 0x2c, 0x00, 0x05, 0x4d, 0x61, 0x6b, 0x65, 0x72, 0x00, 0x01, 0x72, 0x00, 0x01, 0x72};
unsigned char mqttpublish[13] = {0x32, 0x0b, 0x00, 0x01, 0x72, 0x00, 0x01, 0x74, 0x3a, 0x2a, 0x2a, 0x2a, 0x2a};
unsigned char mqttheart[2] = {0xc0, 0x00};
unsigned char mqttdata[4];
int mi = 0, sndi = 0, mode = 0, at = 0, espok = 0, temp,rtn;
long timenow, timebefor = 0, tm;
void setup() {
Serial.begin(9600);
Serial1.begin(115200);
wifilinkstr = "AT+CWJAP=\"";
wifilinkstr += wifiname;
wifilinkstr += "\",\"";
wifilinkstr += wifipsd;
wifilinkstr += "\"";
delay(5000);
Serial1.println("AT+CIPSTATUS");
}
void loop() {
if (mode == 0) {
while (Serial1.available())
{
constr += char(Serial1.read());
delay(2);
}
if (constr.length() > 0)
{
tcplink();
}
}
else if (mode == 1) {
while (Serial1.available())
{
mqttdata[mi] = byte(Serial1.read());
mi++;
delay(2);
}
mqttsend();
}
}
void tcplink() {
if (espok == 0)
{
if (constr.indexOf("STATUS:2") || constr.indexOf("STATUS:4"))
{
Serial.println("STATUS:2、4");
delay(500);
at = 4;
espok = 1;
esp8266at(at);
}
else if (constr.indexOf("STATUS:5"))
{
Serial.println("STATUS:5");
delay(500);
at = 1;
espok = 1;
esp8266at(at);
}
else if (constr.indexOf("STATUS:3"))
{
Serial.println("STATUS:3");
delay(500);
at = 7;
espok = 1;
esp8266at(at);
}
}
else
{
if (at < 6 && constr.indexOf("OK"))
{
Serial.println("OK");
delay(500);
at++;
esp8266at(at);
}
else if (at == 6 && constr.indexOf("CONNECT"))
{
Serial.println("CONNECT");
delay(500);
at++;
esp8266at(at);
}
else if (at == 6 && constr.indexOf("CLOSED"))
{
Serial.println("CLOSED");
delay(500);
esp8266at(at);
}
else if (at == 7 && constr.indexOf(">"))
{
Serial.println("TCPlinked!");
delay(1000);
mode = 1;
}
}
constr="";
}
void mqttsend() {
timenow = millis();
tm = timenow - timebefor;
temp = analogRead(A0);
tempstr = String(temp);
int mqtti = tempstr.length();
String mqttch;
for (int j = 0; j < mqtti; j++)
{
mqttch = tempstr.substring(j, j + 1);
mqttpublish[j + 9] = chartobyte(mqttch);
}
for (int j = mqtti; j < 4; j++)
{
mqttpublish[j + 9] = 0x2a;
}
if (sndi == 0)
{
Serial.print("send mqttlink");
Serial1.write(mqttlink, 27);
sndi = 1;
}
if (tm > 10000)
{
Serial1.write(mqttheart, 2);
timebefor = millis();
}
if (mi > 0)
{
mi = 0;
if (mqttdata[0] == 0x20 || mqttdata[0] == 0xd0)
{
Serial1.write(mqttpublish, 13);
}
else if (mqttdata[0] == 0x40)
{
timebefor = millis();
}
}
}
void esp8266at(int eat)
{
switch (eat) {
case 0: {
Serial1.println("AT");
} break;
case 1: {
Serial1.println("AT+CWMODE=1");
} break;
case 2: {
Serial1.println(wifilinkstr);
} break;
case 3: {
Serial1.println("AT");
} break;
case 4: {
Serial1.println("AT+CIPMUX=0");
} break;
case 5: {
Serial1.println("AT+CIPMODE=1");
} break;
case 6: {
Serial1.println(tcplinkstr);
} break;
case 7: {
Serial1.println("AT+CIPSEND");
} break;
}
}
unsigned char chartobyte(String chr) {
if (chr == "#")
return 0x23;
else if (chr == ":")
return 0x3a;
else if (chr == "$")
return 0x24;
else if (chr == "0")
return 0x30;
else if (chr == "1")
return 0x31;
else if (chr == "2")
return 0x32;
else if (chr == "3")
return 0x33;
else if (chr == "4")
return 0x34;
else if (chr == "5")
return 0x35;
else if (chr == "6")
return 0x36;
else if (chr == "7")
return 0x37;
else if (chr == "8")
return 0x38;
else if (chr == "9")
return 0x39;
else if (chr == "@")
return 0x40;
}
将程序写入Arduino,然后打开emqx的websocket页面,连接上后订阅一个主题为“r“的消息,然后将Arduino断电再通电,就可以在页面上观察来自Arduino的消息了,当然你也可以在手机端订阅,同样可以收到消息。
由于没有使用任何的库函数,所以程序看起来有点长,不过各位同学正好可以了解清楚程序运行的全部过程。如果你使用了Arduino UNO模块的话,可以将程序中的Serial1全部改成Serial就可以了,当然还得把原来的Serial全部删除。
好了,这就是Arduino和ESP8266通过Mqtt服务器自动上传数据的终端示例,你可以接入自己的传感器,上传自己的数据。
现在虽然有了上传数据的终端,可是数据并没有保存起来。并且需要开启一台电脑来作为Mqtt服务器,也有点浪费,下一节我会来介绍如何使用一台树莓派来作为Mqtt服务器,再之后我们用Python编写一个小程序来将Arduino上传的数据存储到Mysql数据库里面,这样一个自动采集数据的物联网项目才能算完整!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)