前回まで/次回以降の取り組みはこちらから。
前回に続いて、気圧センサを接続してみます。
もくじ
Arduinoで気圧を測る
こちらもいろいろありますが、BME280というセンサを使用します。
先述のパーツセットに入っていないので別で用意しました。
私はAmazonで安いの買いましたが、もちろん秋月さんやスイッチサイエンスさんなどで求めてもOKです。
ちなみにこのBME280というセンサ、気圧だけでなく、温度と湿度も測れます。
なのでこのあさがお観察システムを作るならDHT11はなくてもOKです。
大気圧の測定がなくてよければ、前回紹介したKeyStudioのパーツセットの部品だけでできるように、という意味でDHT11を使っています。
Arduinoに接続する
今回用意した基板には動作に必要な外付けパーツがすでに実装されているので、Arduinoにつなぐだけで使用できます。
「Vin」ピンは5Vに、「GND」ピンはGNDに、「SCL」ピンと「SDA」ピンはArduinoに同じ名前のピンがあるのでそれぞれ接続します。
このセンサはI2Cという通信方式でArduinoと通信をして使用します。
I2Cは、2本の通信線にセンサなどをたくさんつないで、それぞれにArduinoから指示を出したり、Arduinoにセンサの読み取り値を送信したりできる方式で、センサなど一つ一つの部品にアドレスを割り振って使用します。
今回使用するセンサモジュールははんだブリッジによってアドレスを切り替えられるようになっていました。
Amazonの販売ページの情報に基づいてはんだブリッジしてあります。
Arduino用ライブラリをインストールする
前回のDHT11に続き、こちらもArduinoで使用するためのライブラリがあり、このライブラリを使うことでI2C通信について気にすることなく使うことができます。
こちらもいろいろなライブラリがありますが、今回は「Adafruit_BME280_Library」を使用します。
前回同様にして、「Adafruit_BME280_Library」をインストールしておきます。
サンプルスケッチを開く
メニューバー[ファイル]→[スケッチ例]→[Adafruit_BME280_Library]からサンプルスケッチ「bne280test.ino」を開いてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | /*************************************************************************** This is a library for the BME280 humidity, temperature & pressure sensor Designed specifically to work with the Adafruit BME280 Breakout ----> http://www.adafruit.com/products/2650 These sensors use I2C or SPI to communicate, 2 or 4 pins are required to interface. The device's I2C address is either 0x76 or 0x77. Adafruit invests time and resources providing this open source code, please support Adafruit andopen-source hardware by purchasing products from Adafruit! Written by Limor Fried & Kevin Townsend for Adafruit Industries. BSD license, all text above must be included in any redistribution See the LICENSE file for details. ***************************************************************************/ #include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h> #define BME_SCK 13 #define BME_MISO 12 #define BME_MOSI 11 #define BME_CS 10 #define SEALEVELPRESSURE_HPA (1013.25) Adafruit_BME280 bme; // I2C //Adafruit_BME280 bme(BME_CS); // hardware SPI //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI unsigned long delayTime; void setup() { Serial.begin(9600); while(!Serial); // time to get serial running Serial.println(F("BME280 test")); unsigned status; // default settings status = bme.begin(); // You can also pass in a Wire library object like &Wire2 // status = bme.begin(0x76, &Wire2) if (!status) { Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!"); Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16); Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n"); Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n"); Serial.print(" ID of 0x60 represents a BME 280.\n"); Serial.print(" ID of 0x61 represents a BME 680.\n"); while (1) delay(10); } Serial.println("-- Default Test --"); delayTime = 1000; Serial.println(); } void loop() { printValues(); delay(delayTime); } void printValues() { Serial.print("Temperature = "); Serial.print(bme.readTemperature()); Serial.println(" *C"); Serial.print("Pressure = "); Serial.print(bme.readPressure() / 100.0F); Serial.println(" hPa"); Serial.print("Approx. Altitude = "); Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); Serial.println(" m"); Serial.print("Humidity = "); Serial.print(bme.readHumidity()); Serial.println(" %"); Serial.println(); } |
サンプルスケッチを変更する
今回も残念ながらこのままでは動きませんでした。
45行目
1 | status = bme.begin(); |
を
1 | status = bme.begin(0x76); |
として、BME280のアドレスを指定してやる必要がありました。
先述の通り、0x76としました。
動かしてみる
ここまででArduinoに書き込んでみます。
(図が前回の使いまわしやんけ…)
書き込んだら、シリアルモニタを起動します
温度湿度と気圧がPCにシリアル通信で返ってきます。
温度・湿度についてはDHT11での測定値とほぼ同じ数値が返ってきました。
気圧ずれてね?
温度湿度は体感とか、他の温度計や湿度計と並べてみたら正しい数値が返ってきているかわかりますが、気圧はなかなか分かりません。
一気に気圧が低下すると体調が悪くなる、という体質の人もいます(というか私もです)がなかなか「うーん…今は…1009hPaくらい」って言える人いませんよね?
少なくとも私には無理です。
そこで、気象庁が公開している観測データと照らし合わせてみました。
(作業したのは5/21なので5/21のデータですあと一応場所は伏せときます)
…
…うん。
ズレてるわ。
- BME280の測定値:約1001hPa
- 気象庁の測定値:約1015hPa
とんでもなくズレております。
が、これ、センサの異常とか不良品とかやっすい大陸製のやつだからとかじゃありません。
海面更生
というのも、実は天気予報などで報じられる「気圧」と実際に気圧計で測定できる「気圧」は異なっているんです。
気圧というものは実際には同じ気圧であっても測定する地点の高度によって値が変わるんです。
この、高度による気圧測定値のずれを補正するために、天気予報や気象庁の観測データでは各地点での気圧を「海抜0m地点での気圧に換算した気圧」を使用しているのです。
なので、単にセンサの出力する気圧値が気象庁の観測データとずれるのは当然です。
(※もしかしたらそのあたりうまく補正してくれるセンサーってのもあるのかもしれませんが…なにせ使うセンサの情報はしっかり確認しましょう)
この、「海抜0m地点での気圧に換算した気圧」に換算する作業を「海面更生」といいます。
wikiに換算式も載ってましたね。
個人的には「海面補正」とか「海面校正」と呼んだ方がしっくりくるんだよなぁ…。
Arduinoのスケッチで換算式を表現すると、
1 | pres_0 = pres/(pow((1-((0.0065*Alt)/(temp+0.0065*Alt+273.15))),5.257)); |
ええいややこしい。
ちなみに、
pres: センサで測定した大気圧[hPa]
pres_0:海面更生した大気圧[hPa]
Alt: 測定地点の高度[m]
temp: 測定地点の温度[℃]
です。
コピペすれば動きますが、一度wikiの数式からスケッチに落とし込むのも自分でやってみてね。
試しに、海面更生を入れて気圧を測定してみると…
(帰ってくるデータの表示の仕方変えちゃってるけど…)
ね。気象庁の観測データと一致しました。これでバリデーションもOKです。
…
ちなみに、気象庁の観測データにはその地点の標高も書かれていますが、当然ながら「気象庁の観測地点」と「自分の観測地点」が必ずしも同じ標高とは限りません。
スマホのGPS機能などで簡単に調べられるので、標高データは正しく与えましょう。
私はずっと気象庁の観測地点の標高で計算していて、なんか気圧ずれるなぁ…常に+4hPaくらい…と思って確認してみたら自分の家と標高が20m以上違っていました。そりゃずれるわな…。
最終仕様を作っていく
今回もサンプルスケッチをもとに最終仕様のスケッチを作っていきます。
前回作成したスケッチに追加して、一つのスケッチにまとめます。
DHT11とBME280は通信方式が違っていますが、問題なく一つのArduinoに同居できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | // あさがおIoT観察日記 Arduino側プログラム // 2020.05.21 V0.0.1 DHT11による温度・湿度取得(DHT11サンプルスケッチより作成) // V0.0.2 BME280気圧取得(BME280サンプルスケッチより作成) #include <Adafruit_Sensor.h> #include <DHT.h> #include <DHT_U.h> #define DHTPIN 2 // Digital pin connected to the DHT sensor #define DHTTYPE DHT11 // DHT 11 DHT_Unified dht(DHTPIN, DHTTYPE); #include <Wire.h> #include <SPI.h> #include <Adafruit_BME280.h> #define SEALEVELPRESSURE_HPA (1013.25) Adafruit_BME280 bme; // I2C uint32_t delayMS; int Alt = 120; void setup() { Serial.begin(9600); dht.begin(); delayMS = 1000; bme.begin(0x76); } void loop() { double temp; double temp_0; double humid; double pres; double pres_0; delay(delayMS); sensors_event_t event; dht.temperature().getEvent(&event); if (!isnan(event.temperature)) { temp = event.temperature; } dht.humidity().getEvent(&event); if (!isnan(event.relative_humidity)) { humid = event.relative_humidity; } pres = bme.readPressure() / 100; pres_0 = pres/(pow((1-((0.0065*Alt)/(bme.readTemperature()+0.0065*Alt+273.15))),5.257)); Serial.println(temp); Serial.println(humid); Serial.println(pres); Serial.println(pres_0); } |
海面補正に必要な地表温度には、前回のDHT11の測定値ではなくBME280で測定した温度を使います。
まず、海面補正前の気圧を「pres」というdouble型の変数に代入します。
その後、気圧を海面補正する計算を行って、結果を「press_0」というdouble型の変数に代入、シリアル通信でPCに送るようにしてみます。
こちらも最終的にはシリアル通信でPCではなくRaspberryPiに送って、IoTサービスにデータをアップロードしていく、という流れになります。
DHT11で測定した温度、気圧、BME280で測定した気圧と海面更生した気圧とを送ってきています。
これも最終的にはながーいケーブルで屋外にまで引き回して使いますが、ひとまずブレッドボード上での動作確認はこれでOK。
気圧測定の遊び方(?)
ちょっと番外編。ArduinoとBME280を使うと気圧を測定することができます。
以前、こんなことをやってみたことがあります。
今年の4/12~4/13の温度・湿度・気圧のデータです。
(先述のような海面更生の計算ミスをしているので、気圧データは気象庁の観測データより高めになってます)
赤線が温度、青線が湿度、緑線が気圧です。
この2日間は強い低気圧が接近し、いわゆる春の嵐で大荒れの天気でした。
気圧データを見てみるとこの4/12の0時~17時にかけて気圧が大きく下がり(1020→1000hPa)、翌4/13の6時~24時にかけて気圧が大きく上がっています(1000→1020hPa)。
どうやら低気圧が最も接近していたのは13日の未明だ、ということが気圧データからわかります。
台風が来たときなんかにこうして気圧を観測していると、普段なかなか見ないような気圧の動きや、台風の最接近を観測できます。
(言うまでもありませんが、安全に十分注意して観測してください。避難勧告・避難指示が出たら従ってください。)
温度・湿度に続いて気圧が測定できるようになりました。
まだまだ続きます。
コメント