Arduino筆記(59):大氣壓強度(高度計)感測模組 GY-BMP280

我有一個G-SHOCK電子錶具有高度計的功能,手錶的高度計功能,應該是偵測大氣壓力,根據氣壓的變化測得高度,可是總覺得誤差很大,有時可能到20-30公尺。本實作用的是 BMP280這個模組,根據規格來看,相對的精確度可達1公尺。

我原本用 Github上的 adafruit/Adafruit_BMP280_Library。執行時,無法偵測到我的BMP280模組,原本也不確定這個模組是否正常可用,試著找到 sSense-BMx280 的函式庫之後,就可以正常測得壓力與溫度。之後有時間再慢慢找看看問題在哪裡?


[BMP280 大氣壓強度(高度計)感測模組 ]

GY-BMP280高精度大氣壓強度感測模組規格如下:
  • 型號:GY-BMP280-3.3
  • 使用芯片:BMP280
  • 供電電源:3v
  • 通信方式:標準IIC/SPI通信協議
  • 氣壓範圍: 300- 1100hPa
  • 採用沉金PCB, 機器焊接工藝保證質量
  • 引腳間距:2.54mm
BMP280氣壓傳感器是專為移動應用。它的小尺寸和低功耗允許用在電池供電的移動電話等設置,GPS模組或手錶。BMP280應用領域如天氣預報、海拔高度測量、室內導航、健身和體育運動等。數字氣壓傳感器BMP280可提供卓越的性能,相對精度為±0 12 hPa(相當於±1米),且包括壓力和溫度測量功能傳感器,功耗僅有2.7μA。

[安裝sSense-BMx280 Library]

sSense-BMx280函式庫提供用於使用BMP280的大氣壓強度讀取的值
• 先到 itbrainpower.net 下載 sSense-BMx280.zip 。
• 將下載的壓縮檔解壓縮,放在 Arduino 主程式下的 libraries目錄內,以我的電腦來說,Arduino安裝在 C:\Program Files (x86)\Arduino,點進目錄有一個 libraries的子目錄,下載後解壓縮的目錄,整個放進  libraries 目錄,重新啟動 Arduino即可。

[材料]

• Arduino Uno x 1
• GY-BMP280 x 1
• 連接線 x 4 條

[接線與電路圖]

Arduino
GY-68 BMP180
3.3V (VCC)
VCC
GND
GND
A4 
SDA
A5 
SCL



[程式]

#include <sSense-BMx280I2C.h>
#include <Wire.h>
#define SERIAL_SPEED  19200

BMx280I2C::Settings settings(
   BME280::OSR_X1,
   BME280::OSR_X1,
   BME280::OSR_X1,
   BME280::Mode_Forced,
   BME280::StandbyTime_1000ms,
   BME280::Filter_Off,
   BME280::SpiEnable_False,
   0x76    // I2C address. I2C specific.
);

BMx280I2C ssenseBMx280(settings);

void setup()
{
  delay(5000);
  DebugPort.begin(SERIAL_SPEED);

  while(!DebugPort) {}        
  DebugPort.println("s-Sense BME/BMP280 I2C sensor.");

  Wire.begin();
  while(!ssenseBMx280.begin())
  {
    DebugPort.println("Could not find BME/BMP280 sensor!");
    delay(1000);
  }
  
  switch(ssenseBMx280.chipModel())
  {
     case BME280::ChipModel_BME280:
       DebugPort.println("Found BME280 sensor! Humidity available.");
       break;
     case BME280::ChipModel_BMP280:
       DebugPort.println("Found BMP280 sensor! No Humidity available.");
       break;
     default:
       DebugPort.println("Found UNKNOWN sensor! Error!");
  }

   // Change some settings before using.
   settings.tempOSR = BME280::OSR_X4;

   ssenseBMx280.setSettings(settings);
}


void loop()
{
   printBMx280Data(&DebugPort);
   delay(500);
}


void printBMx280Data(Stream* client)
{
   float temp(NAN), hum(NAN), pres(NAN);

   BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
   BME280::PresUnit presUnit(BME280::PresUnit_Pa);

   ssenseBMx280.read(pres, temp, hum, tempUnit, presUnit);

   client->print("Temp: ");
   client->print(temp);
   client->print(" "+ String(tempUnit == BME280::TempUnit_Celsius ? 'C' :'F'));
   client->print("\t\tHumidity: ");
   client->print(hum);
   client->print("% RH");
   client->print("\t\tPressure: ");
   client->print(pres);
   client->println(" Pa");

   delay(1000);
}

程式二:可換算氣壓為高度,只是不確定這個高度是否正確?
#include <BMx280_EnvCalc.h>
#include <sSense-BMx280I2C.h>
#include <Wire.h>
#define SERIAL_SPEED 19200

BMx280I2C ssenseBMx280;   // Default : forced mode, standby time = 1000 ms
                          // Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,

void setup()
{
  delay(5000);
  DebugPort.begin(SERIAL_SPEED);

  while(!DebugPort) {} // Wait

  Wire.begin();

  while(!ssenseBMx280.begin())
  {
    DebugPort.println("Could not find BME280 sensor!");
    delay(1000);
  }

  switch(ssenseBMx280.chipModel())
  {
     case BME280::ChipModel_BME280:
       DebugPort.println("Found BME280 sensor! Humidity available.");
       break;
     case BME280::ChipModel_BMP280:
       DebugPort.println("Found BMP280 sensor! No Humidity available.");
       break;
     default:
       DebugPort.println("Found UNKNOWN sensor! Error!");
  }
}

void loop()
{
   printBMx280Data(&DebugPort);
   delay(500);
}


void printBMx280Data( Stream* client )
{
   float temp(NAN), hum(NAN), pres(NAN);

   BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
   BME280::PresUnit presUnit(BME280::PresUnit_Pa);

   ssenseBMx280.read(pres, temp, hum, tempUnit, presUnit);

   client->print("Temp: ");
   client->print(temp);
   client->print(String(tempUnit == BME280::TempUnit_Celsius ? "C" :"F"));
   client->print("\t\tHumidity: ");
   client->print(hum);
   client->print("% RH");
   client->print("\t\tPressure: ");
   client->print(pres);
   client->print(" Pa");

   BMx280_EnvCalc::AltitudeUnit envAltUnit  =  BMx280_EnvCalc::AltitudeUnit_Meters;
   BMx280_EnvCalc::TempUnit     envTempUnit =  BMx280_EnvCalc::TempUnit_Celsius;

   float altitude = BMx280_EnvCalc::Altitude(pres, envAltUnit);
   float dewPoint = BMx280_EnvCalc::DewPoint(temp, hum, envTempUnit);
   float seaLevel = BMx280_EnvCalc::EquivalentSeaLevelPressure(altitude, temp, pres);
   // seaLevel = BMx280_EnvCalc::SealevelAlitude(altitude, temp, pres); // Deprecated. See EquivalentSeaLevelPressure().

   client->print("\r\nAltitude: ");
   client->print(altitude);
   client->print((envAltUnit == BMx280_EnvCalc::AltitudeUnit_Meters ? "m" : "ft"));
   client->print("\tDew point: ");
   client->print(dewPoint);
   client->print(String(envTempUnit == BMx280_EnvCalc::TempUnit_Celsius ? "C" :"F"));
   client->print("\t\tEquivalent Sea Level Pressure: ");
   client->print(seaLevel);
   client->println(" Pa\r\n");

   delay(1000);
}

[實作結果]

程式一執行結果:

程式二執行結果:

[參考資料]

• Hackster.io:Arduino BMP280 Sensor How To

2 留言

  1. 原本的Adafruit_BMP280_Library無法認到模組,應該是原本的範例程式中沒有設定模組的I2C address及chipid。他是空白的,需要使用者自己填上去。

    擷取一段Adafruit_BMP280_Library的範例程式,位置大概在第10行左右,如下
    unsigned status;
    //status = bmp.begin(BMP280_ADDRESS_ALT, BMP280_CHIPID);
    status = bmp.begin();

    其中的status = bmp.begin();
    請改成status = bmp.begin(0x76, 0x60);
    這樣應該就可以使用了。

    回覆刪除
  2. 即便你的氣壓換算高度是正確的(每降低1hpa,高度則上升9公尺),但是即便你在同個地點相同高度,不同時監測得的氣壓值還是不一樣,颱風來的時候最低可能不到970,冬天寒流來的時候可能高達1020,前後誤差400公尺以上,所以必須扣掉當地當時的相對海平面氣壓所得到的高度才是正確的,這就是你的手錶高度誤差的原因。

    回覆刪除

張貼留言

較新的 較舊