MQTT Publish + Node-RED + BMP280

 MQTT Publish + Node-RED + BMP280


這次實作是使用MQTT發送BMP280的數據到樹莓派上的Node-RED儀錶版上
所以會使用類似的程式碼手法來完成項目。

開始之前先備妥樹莓派上所須的軟硬體
  1. 安裝Mosquitto broker(如果沒玩過樹莓派,請連結這裡安裝樹莓派系統和
  2. 何使用SSH和VNC鏡像)
  3. 安裝 Node-RED installed  和 Node-RED Dashboard在樹莓派上。
  4. 備註:安裝Node-RED時若出現錯誤訊息改用下面所附下載  bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
  5. 接下來先測試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 charssid = "---";
const charpassword = "------";
//mqttServer
const charmqttServer = "---.---.---.--";

//設定wifi
void setupWifi(){
  WiFi.begin(ssidpassword);
  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(mqttServer1883);
  
  if (!bmp.begin()) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring or "
                      "try a different address!"));
    while (1delay(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(temp12tempStr);
      dtostrf(pressure12pressStr);
      dtostrf(humi12humiStr);
      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 charssid = "---";
const charpassword = "------";
//mqttServer
const charmqttServer = "---.---.---.---";

//設定wifi
void setupWifi(){
  WiFi.begin(ssidpassword);
  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(mqttServer1883);
  
  if (!bmp.begin()) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring or "
                      "try a different address!"));
    while (1delay(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(temp12tempStr);
dtostrf(pressure12pressStr);
dtostrf(humi12humiStr);


取得溫度/壓力數值後每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(temp12tempStr);
      dtostrf(pressure12pressStr);
      dtostrf(humi12humiStr);
      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);
    }





































留言

這個網誌中的熱門文章