2019年3月13日水曜日

ArduinoでBME280とBH1750を使う

BME280

BME280温度、湿度、気圧が測れるセンサーです。Aliexpressにて2.23ドルで買いました。
Amazonでも日本発送のPrime対象商品が売っているので、Aliに抵抗があったり直ぐに欲しい場合はAmazonでもいいかもしれません。
似たような名前ですが、BMP280には湿度センサーが付属していないので注意してください。値段がぜんぜん違うので調べててわかるとは思いますが。BMPの方だと0.75ドルくらいです。


このモジュールボードには3.3V版5V版が存在し、今回は5V版を購入しました。 センサー自体は3.3V駆動なので、5V版にはレギュレータが乗っています。I2Cバスにもレベルコンバータがちゃんと乗っていました。
ところが訳あって購入後にボードを3.3Vで動かす必要が出たので、5V版が3.3Vで動くか心配でしたが、結局の所全然問題ありませんでした。何故か私が買ったところでは3.3Vも5Vも値段が同じなので、迷うなら5V版を買っておいてもいいかもしれません。
なお5V版は両面実装で、センサー以外は全て裏面に乗ってます。

BH1750

BH1750照度(ルクス)が測れるセンサーです。同じくAliexpressにて0.83ドルで買いました。
こちらもAmazonでPrime対象商品が売っています


このモジュールボードは3.3V~5V対応と謳っています。センサーは5Vに耐えられないので、3.3Vのレギュレータが乗っていましたが、問題はI2Cバスです。
そこにレベルコンバータはなく3.3Vラインにプルアップされているだけでした。マイコン側で内部プルアップを用いず、他にI2Cデバイスをぶら下げないならコレでも問題ありませんが、他のデバイスで5Vラインにプルアップされていると、I2Cラインが3.3Vよりも上がってしまい、最悪、BH1750を破損してしまう可能性があります。5V駆動のプルアップ抵抗には注意が必要です。
ということで、無用なトラブルを避けるためにも、複数のI2Cデバイスをぶら下げるときは全て3.3V駆動にするのが安全でしょう。 私はBME280と共存させる予定なので、BME280も3.3V駆動してもらうことにしました。

ArudinoでBME280

ちゃんと先人の手によるライブラリがあります。感謝。

https://github.com/finitespace/BME280
 
Arduino Library List にて検索して出てくるものと同じです。

ライブラリの導入法を軽く書いておくと、Githubの「Clone or download」から「Download ZIP」して、解凍して、ArduinoIDEがインストールされてる階層にある「libraries」フォルダに、「~~master」フォルダごとすべてコピーすれば完了です。中にexampleフォルダがあろうと問題ありません。

ArduinoUnoのピンアサインは、
A4ピンがI2CのSDA
A5ピンがI2CのSCL
となっています。
また、前述の理由から、今回は5Vボードですが3.3V駆動します。ということでUnoの3.3V出力をセンサーボードに供給します。


動作チェック用のサンプルスケッチです。提供されているexampleとほぼ同じです。
// @Uno
// A4 = SDA
// A5 = SCL
// 3.3V = VIN

#include <BME280I2C.h>
#include <Wire.h>

BME280I2C::Settings settings(
  // Temp
  BME280::OSR_X1,
  // Hum
  BME280::OSR_X1,
  // Pres
  BME280::OSR_X1,
  BME280::Mode_Forced,
  BME280::StandbyTime_1000ms,
  BME280::Filter_Off,
  BME280::SpiEnable_False,
  BME280I2C::I2CAddr_0x76
);

BME280I2C bme280(settings);

void setup() {
  Serial.begin(115200);
  
  while(!Serial) {} // Wait

  Wire.begin();

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

float temp, hum, pres;
  
void loop() {
  bme280.read(pres, temp, hum, BME280::TempUnit_Celsius, BME280::PresUnit_hPa);
  
  Serial.print("Temperature: ");
  Serial.print(temp);
  Serial.print("℃");
  Serial.print("  Humidity: ");
  Serial.print(hum);
  Serial.print("%");
  Serial.print("  Pressure: ");
  Serial.print(pres);
  Serial.println("hPa");
  
  delay(1000);
}
書き込み終わったら、IDEのツール→シリアルモニタで確認してみましょう。


いい感じですね。値も結構安定していて優秀です。現実との誤差に関しては比較できませんが。
試しに1m先から息を吹きかけてみましたが、湿度が顕著に上昇し、数秒で元に戻りました。結構鋭敏です。

ArudinoでBH1750

こちらもちゃんと先人の手によるライブラリがあります。感謝。

https://github.com/claws/BH1750

なお、これは、Arduino Library List にて検索して出てくるライブラリと異なります。こちらのライブラリは、私の確認した時点では、ACKのチェックを行っておらず、BH1750の計測時間レジスタの書き込みに対応していなかったので、使用しませんでした。

ライブラリ導入法はBME280と同じ。

再度書きますが、ArduinoUnoのピンアサインは、
A4ピンがI2CのSDA
A5ピンがI2CのSCL
です。
前述の理由から、3.3V駆動とします。
また、ボードにはADDRピンがありますが、これをLowにするかHighにするかでI2Cアドレスを変えられるようです。マイコンのIOピンに接続すれば、送りたいアドレスだけLなりHにすることで、実質的に何台だろうとBH1750を接続できるということですね。便利です。
ちなみにボードのADDRピンは1kΩでプルダウンされていたので、何も接続しなければLowになるようです。ライブラリも、デフォルト設定では、このLowのときのアドレスを勝手に使ってくれるようです。


動作チェック用のサンプルスケッチです。提供されているexampleとほぼ同じです。
// @Uno
// A4 = SDA
// A5 = SCL
// 3.3V = VIN

#include <BH1750.h>
#include <Wire.h>

BH1750 bh1750;

void setup() {
  Serial.begin(115200);
  
  while(!Serial) {} // Wait

  Wire.begin();

  bh1750.begin(BH1750::ONE_TIME_HIGH_RES_MODE);
}
  
void loop() {
  float lux = bh1750.readLightLevel(true);
  Serial.print("Luminosity: ");
  if(lux < 0){
    Serial.println("Error");
  }
  else{
    Serial.print(lux);
    Serial.println("lx");
  }
  
  delay(1000);
}
書き込み終わったら、IDEのツール→シリアルモニタで確認してみましょう。


いい感じですね。
こちらも、値が結構安定していて優秀です。誤差は知りえません。
受光部を一切遮らずに、1m程度離れた場所で人間が動くだけでも数lx変動するようです。人間が反射・遮断する光の量が変化するためだと思われますが、この敏感さには驚きました。

ArduinoでBME280とBH1750を同時に動かす

さて本命です。といってもI2Cなので並列するだけです。
個々で動いたのだから、まぁ普通に動きます。


サンプルスケッチです。合わせただけ。
// @Uno
// A4 = SDA
// A5 = SCL
// 3.3V = VIN

#include <BME280I2C.h>
#include <BH1750.h>
#include <Wire.h>

BME280I2C::Settings settings(
  // Temp
  BME280::OSR_X1,
  // Hum
  BME280::OSR_X1,
  // Pres
  BME280::OSR_X1,
  BME280::Mode_Forced,
  BME280::StandbyTime_1000ms,
  BME280::Filter_Off,
  BME280::SpiEnable_False,
  BME280I2C::I2CAddr_0x76 // I2C address. I2C specific.
);

BME280I2C bme280(settings);

BH1750 bh1750;

void setup() {
  Serial.begin(115200);
  
  while(!Serial) {} // Wait

  Wire.begin();

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

  bh1750.begin(BH1750::ONE_TIME_HIGH_RES_MODE);
}

float temp, hum, pres;
  
void loop() {
  bme280.read(pres, temp, hum, BME280::TempUnit_Celsius, BME280::PresUnit_hPa);
  
  Serial.print("Temperature: ");
  Serial.print(temp);
  Serial.print("℃");
  Serial.print("  Humidity: ");
  Serial.print(hum);
  Serial.print("%");
  Serial.print("  Pressure: ");
  Serial.print(pres);
  Serial.print("hPa");

  float lux = bh1750.readLightLevel(true);
  Serial.print("  Luminosity: ");
  if(lux < 0){
    Serial.println("Error");
  }
  else{
    Serial.print(lux);
    Serial.println("lx");
  }
  
  delay(1000);
}
結果がこちら。


完璧です。

0 件のコメント:

コメントを投稿