MQTT-Publish-Node-RED-BMP280
參考文獻-https://randomnerdtutorials.com/esp32-mqtt-publish-subscribe-arduino-ide/
這次實作是使用MQTT發送BMP280的數據到樹莓派上的Node-RED儀錶版上
我是參考這篇文章-https://randomnerdtutorials.com/esp32-mqtt-publish-subscribe-arduino-ide/
所以會使用類似的程式碼手法來完成項目。
開始之前先備妥樹莓派上所須的軟硬體
- 安裝Mosquitto broker(如果沒玩過樹莓派,請連結這裡安裝樹莓派系統和如
- 何使用SSH和VNC鏡像)
- 安裝 Node-RED installed 和 Node-RED Dashboard在樹莓派上。
- _備註:安裝Node-RED時若出現錯誤訊息改用下面所附下載 _****bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
- 接下來先測試BMP280是否可正常測溫度和壓力-請參考之前的紀錄(點我傳送)。
先來看一下整個發送原理比較容易理解自己要學的重點在哪裡
此次實驗我只寫從ESP32發送數據到樹莓派的Mosquitto代理接收/發送
然後通過MQTT通信協議去控制ESP32發送數據到Node-RED,其實我覺
得和ThingSpeak很類似,只是使用Node-RED更能客製化。
看一下這張圖
知道原理後就是開始進入寫程式的主軸
首先要有網路可以連到數莓派和ESP32,然後判斷是否已經連線
如果連不上就再自動重連,連上後印出IP,連上網路後,就是
要去和樹莓派的Mosquitto Broker連線,一樣就是判斷是否成功
連線做出對應的動作。WiFi和Mosquitto Broker都連線之後,就開
始從ESP32客戶端發送溫度和壓力的數據到Node-RED的介面上。
布署Node-RED
程式碼
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
Adafruit_BMP280 bmp; // I2C
WiFiClient espClient;
PubSubClient client(espClient);
//wifi帳密
const char* ssid = "---";
const char* password = "------";
//mqttServer
const char* mqttServer = "---.---.---.--";
//設定wifi
void setupWifi(){
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED){
delay(50);
Serial.print(".");
}
Serial.println("connected successful");
Serial.println(WiFi.localIP());
}
void reconnect(){
while (! client.connected()){
Serial.print("Attempting MQTT connection...");
if (client.connect("esp32Client")){
Serial.println("connected");
}else {
Serial.print("failed connected is : ");
Serial.println(client.state());
delay(2000);
}
}
}
void setup() {
Serial.begin(115200);
Serial.println(F("BMP280 test"));
setupWifi();
client.setServer(mqttServer, 1883);
if (!bmp.begin()) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring or "
"try a different address!"));
while (1) delay(10);
}
}
void loop() {
if (! client.connected()){
reconnect();
}
client.loop();
long lastTime = 0;
long currentTime = millis();
float temp = 0;
float pressure = 0;
float humi = 0;
if (currentTime - lastTime > 5000){
lastTime = currentTime;
temp = bmp.readTemperature();
humi = 1.8 * temp + 32;
pressure = bmp.readPressure();
char tempStr\[8\] = "";
char pressStr\[24\] = "";
char humiStr\[8\] = "";
dtostrf(temp, 1, 2, tempStr);
dtostrf(pressure, 1, 2, pressStr);
dtostrf(humi, 1, 2, humiStr);
Serial.print("Temp: ");
Serial.println(tempStr);
Serial.print("humi: ");
Serial.println(humiStr);
Serial.print("Pressure: ");
Serial.println(pressStr);
client.publish("esp32/temp", tempStr);
client.publish("esp32/pressure", pressStr);
client.publish("esp32/humi", humiStr);
delay(1000);
}
}
解析
匯入所須的程式庫
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
建立bmp280,wifi客戶端及MQTT客戶端代數
Adafruit_BMP280 bmp; // I2C
WiFiClient espClient;
PubSubClient client(espClient);
MQTTserver的IP即是樹莓派的IP
//wifi帳密
const char* ssid = "---";
const char* password = "------";
//mqttServer
const char* mqttServer = "---.---.---.---";
//設定wifi
void setupWifi(){
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED){
delay(50);
Serial.print(".");
}
Serial.println("connected successful");
Serial.println(WiFi.localIP());
}
連線至MQTT伺服器成功與無法連線的對應動作
void reconnect(){
while (! client.connected()){
Serial.print("Attempting MQTT connection...");
if (client.connect("esp32Client")){
Serial.println("connected");
}else {
Serial.print("failed connected is : ");
Serial.println(client.state());
delay(2000);
}
}
void setup(){}裡面的一些必要初始化
void setup() {
Serial.begin(115200);
Serial.println(F("BMP280 test"));
setupWifi();
client.setServer(mqttServer, 1883);
if (!bmp.begin()) {
Serial.println(F("Could not find a valid BMP280 sensor, check wiring or "
"try a different address!"));
while (1) delay(10);
}
}
void loop(){}裡
無法連線就重複連線
if (! client.connected()){
reconnect();
}
client.loop();
關於數值轉字元的函式
char* dtostrf(double _val,signed char _width, unsigned char prec, char* _s)
引數說明:
_val:要轉換的float或者double值。
_width:轉換後整數部分長度。
_prec:轉換後小數部分長度。
_s:儲存到該char陣列中。
其中這個是轉成對應的字元
char tempStr[8] = "";
char pressStr[24] = "";
char humiStr[8] = "";
dtostrf(temp, 1, 2, tempStr);
dtostrf(pressure, 1, 2, pressStr);
dtostrf(humi, 1, 2, humiStr);
取得溫度/壓力數值後每5秒發送到MQTT的Node-RED
if (currentTime - lastTime > 5000){
lastTime = currentTime;
temp = bmp.readTemperature();
humi = 1.8 * temp + 32;
pressure = bmp.readPressure();
char tempStr[8] = "";
char pressStr[24] = "";
char humiStr[8] = "";
dtostrf(temp, 1, 2, tempStr);
dtostrf(pressure, 1, 2, pressStr);
dtostrf(humi, 1, 2, humiStr);
Serial.print("Temp: ");
Serial.println(tempStr);
Serial.print("humi: ");
Serial.println(humiStr);
Serial.print("Pressure: ");
Serial.println(pressStr);
client.publish("esp32/temp", tempStr);
client.publish("esp32/pressure", pressStr);
client.publish("esp32/humi", humiStr);
delay(1000);
}