11.Arduino基础入门— 8.收集温度信息,通过WIFI连接Mosquito服务器再存储到Mysql中
前言:很多参考来源于 https://blog.csdn.net/qq_28877125/article/details/78785472
这个东西是通过使用arduino UNO R3板子获取温湿度模块DHT11中的温湿度然后通过ESP8266WiFi模块发送到MQTT服务器上面,然后再在网页上面显示出来的。
自己补充画了一个图
涉及到的一些技术:
-
Arduino的基本使用:
arduino软件模拟串口的使用(网上资料很多)
DHT11的温湿度读取(有arduino官方库,网上资料也很多)
-
ESP8266WiFi模块AT指令的使用:
从某宝上面买一块型号为ESP-01的WiFi模块(ESP8266是该类模块的芯片名字),型号有好多种,一开始我也买错了,后面换成ESP-01。
买来的模块里面已经有程序,上电就可以运行的,一般是官方的AT固件
该官方AT固件,是有使用指导书的,可以问店家要,也可以从官网下载,然后就可以知道怎么用了。
arduino模块的串口引脚(我代码里面的串口引脚是软件模拟的)和买来的ESP-01模块的串口引脚相连接(R-T,T-R),然后再在代码里面,使用串口发送例如“AT+RST\r\n”的指令。
-
MQTT服务器的部署使用:
一般是要有自己的MQTT服务器的,如果没有,网上也有公共的MQTT Broker可以暂时用一下,本篇文章用mosquitto作为消息中间件服务器,
-
把订阅的消息插入到数据库中
这里使用的是客户端插件,通过Node把订阅的消息插入到Mysql数据中。
Arduino所需要使用的库(重要):
arduino的MQTT库:PubSubClient by Nick O’Leary.
arduino的封装好AT指令的WiFi操作库:WiFiEsp by bportaluri
Adafruit Unified Sensor by Adafruit
DHT sensor library by Adafruit
第1个是MQQT用的、第2个是在Wifi执行AT指令的库、第4个是温度计的库
一、连上wifi
一个wifi模块,要想连上网络首先得连上WiFi热点,所以使用AT指令来让WiFi模块连接上SSID。如果你的arduino IDE已经安装了以上那些库,那么就可以把下面的代码拷贝再修改一下 ssid 和 password就可以连接WiFi了。
网上有些代码是调用ESP8266WiFi.h库来完成,一开始找了很久后面发现
https://tttapa.github.io/ESP8266/Chap01%20-%20ESP8266.html
ESP8266WiFi.h库适用于ESP8266作为主控芯片的板,不适合UNO R3+ESP8266的模式。
所以后面变成下述的代码
1 #include "DHT.h" 2 #include <WiFiEspClient.h> 3 #include <WiFiEsp.h> 4 #include <WiFiEspUdp.h> 5 #include <PubSubClient.h> 6 #include "SoftwareSerial.h" 7 8 #define WIFI_AP "jzc_28E7" 9 #define WIFI_PASSWORD "Jzckj@2017" 10 11 // DHT 12 //温度指针 7脚 13 //#define DHTPIN 7 14 //#define DHTTYPE DHT11 15 16 char MqttServer[] = "127.0.0.1"; 17 18 // 初始化以太网客户端对象 -- WiFiEspClient.h 19 WiFiEspClient espClient; 20 21 // 初始化DHT11传感器 22 //DHT dht(DHTPIN, DHTTYPE); 23 24 // 初始化MQTT库PubSubClient.h的对象 25 PubSubClient client(espClient); 26 27 SoftwareSerial soft(3, 2); // RX, TX 28 29 int status = WL_IDLE_STATUS; 30 unsigned long lastSend; 31 32 void setup() { 33 Serial.begin(9600); 34 // dht.begin(); 35 36 InitWiFi(); 37 38 39 } 40 41 void loop() { 42 43 44 status = WiFi.status(); 45 if ( status != WL_CONNECTED) { 46 while ( status != WL_CONNECTED) { 47 Serial.print("[loop()]Attempting to connect to WPA SSID: "); 48 Serial.println(WIFI_AP); 49 // 连接WiFi热点 50 status = WiFi.begin(WIFI_AP, WIFI_PASSWORD); 51 delay(500); 52 } 53 Serial.println("[loop()]Connected to AP"); 54 } 55 56 57 } 58 59 void InitWiFi() 60 { 61 // 初始化软串口,软串口连接ESP模块 62 soft.begin(9600); 63 // 初始化ESP模块 64 WiFi.init(&soft); 65 // 检测WiFi模块在不在,宏定义:WL_NO_SHIELD = 255,WL_IDLE_STATUS = 0, 66 if (WiFi.status() == WL_NO_SHIELD) { 67 Serial.println("WiFi shield not present"); 68 while (true); 69 } 70 71 Serial.println("[InitWiFi]Connecting to AP ..."); 72 // 尝试连接WiFi网络 73 while ( status != WL_CONNECTED) { 74 Serial.print("[InitWiFi]Attempting to connect to WPA SSID: "); 75 Serial.println(WIFI_AP); 76 // Connect to WPA/WPA2 network 77 status = WiFi.begin(WIFI_AP, WIFI_PASSWORD); 78 delay(500); 79 } 80 Serial.println("[InitWiFi]Connected to AP"); 81 }
连接成功(以下的信息是打开串口调试助手,arduino会通过串口打印出来的信息,从中我们可以看到已经连接成功!):图是借用的,实际显示的类似。
二、连上温度传感器
一个DHT11模块
1 #include "DHT.h" 2 #include <WiFiEspClient.h> 3 #include <WiFiEsp.h> 4 #include <WiFiEspUdp.h> 5 #include <PubSubClient.h> 6 #include "SoftwareSerial.h" 7 8 // DHT 9 #define DHTPIN 7 //温度指针 7脚 10 #define DHTTYPE DHT11 11 12 #define WIFI_AP "jzc_28E7" //WIFI SSID 13 #define WIFI_PASSWORD "Jzckj@2017" //WIFI 密码 14 char MqttServer[] = "127.0.0.1"; //MQTT服务器 15 16 const int tx = 2; //tx针脚 17 const int rx = 3; //rx针脚 18 SoftwareSerial soft(rx, tx); // RX, TX WIFI信号RX,TX针脚 19 20 const int millisecond = 3000; //重复发送的周期, 默认1000毫秒=1秒 21 22 // 初始化以太网客户端对象 -- WiFiEspClient.h 23 WiFiEspClient espClient; 24 25 // 初始化DHT11传感器 26 DHT dht(DHTPIN, DHTTYPE); 27 28 // 初始化MQTT库PubSubClient.h的对象 29 PubSubClient client(espClient); 30 31 int status = WL_IDLE_STATUS; 32 unsigned long lastSend; 33 34 void setup() { 35 Serial.begin(9600); 36 dht.begin();//DHT开始工作 37 38 InitWiFi(); 39 40 lastSend = 0; 41 42 } 43 44 void loop() { 45 46 status = WiFi.status(); 47 if ( status != WL_CONNECTED) { 48 while ( status != WL_CONNECTED) { 49 Serial.print("[loop()]Attempting to connect to WPA SSID: "); 50 Serial.println(WIFI_AP); 51 // 连接WiFi热点 52 status = WiFi.begin(WIFI_AP, WIFI_PASSWORD); 53 delay(500); 54 } 55 Serial.println("[loop()]Connected to AP"); 56 57 } 58 59 if ( millis() - lastSend > millisecond ) { // 用于定时1秒钟发送一次数据 60 getAndSendTemperatureAndHumidityData(); // 获取温湿度数据 61 lastSend = millis(); 62 } 63 64 65 } 66 67 void InitWiFi() 68 { 69 // 初始化软串口,软串口连接ESP模块 70 soft.begin(9600); 71 // 初始化ESP模块 72 WiFi.init(&soft); 73 // 检测WiFi模块在不在,宏定义:WL_NO_SHIELD = 255,WL_IDLE_STATUS = 0, 74 if (WiFi.status() == WL_NO_SHIELD) { 75 Serial.println("WiFi shield not present"); 76 while (true); 77 } 78 79 Serial.println("[InitWiFi]Connecting to AP ..."); 80 // 尝试连接WiFi网络 81 while ( status != WL_CONNECTED) { 82 Serial.print("[InitWiFi]Attempting to connect to WPA SSID: "); 83 Serial.println(WIFI_AP); 84 // Connect to WPA/WPA2 network 85 status = WiFi.begin(WIFI_AP, WIFI_PASSWORD); 86 delay(500); 87 } 88 Serial.println("[InitWiFi]Connected to AP"); 89 90 } 91 92 //void InitTemp(){ 93 // float h = dht.readHumidity();//读湿度 94 // float t = dht.readTemperature();//读温度,默认为摄氏度 95 // Serial.println((String)t+"C"); 96 // } 97 98 /* 99 * 100 * 读取温湿度数据 101 * 102 */ 103 void getAndSendTemperatureAndHumidityData() 104 { 105 Serial.println("Collecting temperature data."); 106 107 // 大概250ms读取一次 108 float h = dht.readHumidity(); 109 float t = dht.readTemperature(); 110 111 // 查看是否读取温湿度失败的 112 if (isnan(h) || isnan(t)) { 113 Serial.println("Failed to read from DHT sensor!"); 114 return; 115 } 116 117 Serial.print("Humidity: "); 118 Serial.print(h); 119 Serial.print(" %\t"); 120 Serial.print("Temperature: "); 121 Serial.print(t); 122 Serial.print(" *C "); 123 Serial.println(""); 124 125 String temperature = String(t); 126 String humidity = String(h); 127 128 // Just debug messages 129 // Serial.print( "Sending temperature and humidity : [" ); 130 // Serial.print( temperature ); Serial.print( "," ); 131 // Serial.print( humidity ); 132 // Serial.print( "] -> " ); 133 134 135 /* 136 // 构建一个 JSON 格式的payload的字符串 137 String payload = "{"; 138 payload += "\"temperature\":"; payload += temperature; payload += ","; 139 payload += "\"humidity\":"; payload += humidity; 140 payload += "}"; 141 142 // Send payload 143 char attributes[100]; 144 payload.toCharArray( attributes, 100 ); 145 146 // boolean publish(const char* topic, const char* payload); 147 148 client.publish( "v1/devices/me/telemetry", attributes ); 149 Serial.print("[publish]-->>"); 150 Serial.println( attributes ); 151 */ 152 }
三、通过MQTT客户端传送数据
前提是安装好mosquitto服务器,并测试好订阅端和发送端
1 #include "DHT.h" 2 #include <WiFiEspClient.h> 3 #include <WiFiEsp.h> 4 #include <WiFiEspUdp.h> 5 #include <PubSubClient.h> 6 #include "SoftwareSerial.h" 7 8 // DHT 9 #define DHTPIN 7 //温度指针 7脚 10 #define DHTTYPE DHT11 11 12 #define WIFI_AP "jzc_28E7" //WIFI SSID 13 #define WIFI_PASSWORD "Jzckj@2017" //WIFI 密码 14 char MqttServer[] = "192.168.0.141"; //MQTT服务器 注意这里已经连上网络需要找到MQTT的实际IP地址,不能用本机的127.0.0.1地址了。 15 16 const int tx = 2; //tx针脚 17 const int rx = 3; //rx针脚 18 SoftwareSerial soft(rx, tx); // RX, TX WIFI信号RX,TX针脚 19 20 21 const int connect_wifi_delay_millisecond =500; //连接WIFI重试毫秒 22 const int send_temp_millisecond = 3000; //重复发送温度的周期, 默认1000毫秒=1秒 23 const int mqqt_retry_connect_millisecond=5000; //如果连接MQQT服务器不成功,循环直到连接上MQTT服务器 24 25 //串口波特率 26 const int serial_port =9600; 27 28 //设置设备ID 29 const String deviceID = "tempDevice1"; 30 //mqqt服务器端口 31 const int mqqt_server_port = 1883; 32 33 // 初始化以太网客户端对象 -- WiFiEspClient.h 34 WiFiEspClient espClient; 35 36 // 初始化DHT11传感器 37 DHT dht(DHTPIN, DHTTYPE); 38 39 // 初始化MQTT库PubSubClient.h的对象 40 PubSubClient client(espClient); 41 42 int status = WL_IDLE_STATUS; 43 unsigned long lastSend; 44 45 void setup() { 46 Serial.begin(9600); 47 dht.begin();//DHT开始工作 48 49 InitWiFi(); //初始化WIFI 50 client.setServer( MqttServer, mqqt_server_port ); // 连接WiFi之后,连接MQTT服务器 51 lastSend = 0; 52 53 } 54 55 void loop() { 56 57 status = WiFi.status(); 58 if ( status != WL_CONNECTED) { 59 while ( status != WL_CONNECTED) { 60 Serial.print("[loop()]Attempting to connect to WPA SSID: "); 61 Serial.println(WIFI_AP); 62 // 连接WiFi热点 63 status = WiFi.begin(WIFI_AP, WIFI_PASSWORD); 64 delay(connect_wifi_delay_millisecond); 65 } 66 Serial.println("[loop()]Connected to AP"); 67 68 } 69 70 if ( !client.connected() ) { 71 reconnect(); 72 } 73 74 if ( millis() - lastSend > send_temp_millisecond ) { // 用于定时1秒钟发送一次数据 75 getAndSendTemperatureAndHumidityData(); // 获取温湿度数据 76 lastSend = millis(); 77 } 78 79 client.loop(); 80 81 } 82 83 void InitWiFi() 84 { 85 // 初始化软串口,软串口连接ESP模块 86 soft.begin(serial_port); 87 // 初始化ESP模块 88 WiFi.init(&soft); 89 // 检测WiFi模块在不在,宏定义:WL_NO_SHIELD = 255,WL_IDLE_STATUS = 0, 90 if (WiFi.status() == WL_NO_SHIELD) { 91 Serial.println("WiFi shield not present"); 92 while (true); 93 } 94 95 Serial.println("[InitWiFi]Connecting to AP ..."); 96 // 尝试连接WiFi网络 97 while ( status != WL_CONNECTED) { 98 Serial.print("[InitWiFi]Attempting to connect to WPA SSID: "); 99 Serial.println(WIFI_AP); 100 // Connect to WPA/WPA2 network 101 status = WiFi.begin(WIFI_AP, WIFI_PASSWORD); 102 delay(500); 103 } 104 Serial.println("[InitWiFi]Connected to AP"); 105 106 } 107 108 109 /* 110 * 111 * 读取温湿度数据 112 * 113 */ 114 void getAndSendTemperatureAndHumidityData() 115 { 116 Serial.println("Collecting temperature data..."); 117 118 // 大概250ms读取一次 119 float h = dht.readHumidity(); 120 float t = dht.readTemperature(); 121 122 // 查看是否读取温湿度失败的 123 if (isnan(h) || isnan(t)) { 124 Serial.println("Failed to read from DHT sensor!"); 125 return; 126 } 127 128 Serial.print("Humidity: "); 129 Serial.print(h); 130 Serial.print(" %\t"); 131 Serial.print("Temperature: "); 132 Serial.print(t); 133 Serial.print(" *C "); 134 Serial.println(""); 135 136 String temperature = String(t); 137 String humidity = String(h); 138 139 140 // PostData2MQTTServer(temperature,humidity); 141 // Just debug messages 142 Serial.print( "Sending temperature and humidity : [" ); 143 Serial.print( temperature ); Serial.print( "," ); 144 Serial.print( humidity ); 145 Serial.print( "] -> " ); 146 147 148 149 // 构建一个 JSON 格式的payload的字符串 150 String payload = "{"; 151 payload += "\"temperature\":"; payload += temperature; payload += ","; 152 payload += "\"humidity\":"; payload += humidity; 153 payload += "}"; 154 155 // Send payload 156 char attributes[100]; 157 payload.toCharArray( attributes, 100 ); 158 159 // boolean publish(const char* topic, const char* payload); 160 161 //client.publish( "v1/devices/me/telemetry", attributes ); 162 client.publish( "test", attributes ); 163 Serial.print("[publish]-->>"); 164 Serial.println( attributes ); 165 166 } 167 168 // void PostData2MQTTServer(String temp,String hum) 169 //{ 170 // // 构建一个 JSON 格式的payload的字符串 171 // String payload = "{"; 172 // payload += "\"temperature\":"; payload += temp; payload += ","; 173 // payload += "\"humidity\":"; payload += hum; 174 // payload += "}"; 175 // 176 // // Send payload 177 // char attributes[100]; 178 // payload.toCharArray( attributes, 100 ); 179 // 180 // // boolean publish(const char* topic, const char* payload); 181 // 182 // //client.publish( "v1/devices/me/telemetry", attributes ); 183 // client.publish( "test", attributes ); 184 // 185 // Serial.print("[publish]-->>"); 186 // Serial.println( attributes ); 187 // } 188 189 190 /** 191 * 192 * MQTT客户端断线重连函数 193 * 194 */ 195 196 void reconnect() { 197 // 一直循环直到连接上MQTT服务器 198 while (!client.connected()) { 199 Serial.print("[reconnect]Connecting to MQTT Server ..."); 200 // 尝试连接connect是个重载函数 (clientId, username, password) 201 if ( client.connect(deviceID.c_str()) )//client.connect(deviceID, NULL, NULL) ) 202 { 203 Serial.println( "[DONE] MQTT Server is connect Now!Client:"+(String)deviceID.c_str() ); 204 } else { 205 Serial.print( "[FAILED] [ mqtt connect error code = " ); 206 Serial.print( client.state() ); 207 Serial.println( " : retrying in 5 seconds]" );// Wait 5 seconds before retrying 208 delay( mqqt_retry_connect_millisecond ); 209 } 210 } 211 }
传送成功的话会串口工具返回的信息如下
四、运行客户端插件把订阅的数据插入到数据库中
关于如何配置,可以参考10.Arduino基础入门— 7.如何把在Mosquitto服务器上订阅到的消息写入到数据库里面
其中在Node客户端获取到订阅的信息
注意:注意:注意:
ESP8266 ESP-01出厂默认的波特率是115200,需要把波特率改为9600,否则会导致传输数据失败。可以通过安信可的串口调试工具执行命令 AT+UART_DEF=9600,8,1,0,0
修改为9600。