高度気象ステーション v2.0:温度・気圧・湿度・高度のリアルタイム監視
リビングスペースで温度、気圧、湿度、高度を正確に測定するコンパクトな気象ステーションを構築します。
ストーリー
Raspberry Pi 2上のWindows 10 IoT Core向けAdafruit Starter Packを使用し、BME280センサー(またはBMP280)をインターフェースして環境データを読み取り、クラウドサービスにパブリッシュする方法をデモンストレートします。
BMP280をお持ちの場合は、Weather Station v1ガイドを参照してください: Weather Station v1
ハードウェア
Raspberry Pi 2をブレッドボードに接続し、以下のFritzing図「回路図」セクションに従ってBME280センサーを配線。
ソフトウェア
スターターコードを GitHub – ms-iot/adafruitsample からダウンロード。センサーとの通信と読み取り値のパブリッシュに必要なコード追加を解説します。
Lesson_203v2\StartSolution\lesson_203v2.sln を開き、 mainpage.xaml.cs を編集。
完全版は Lesson_203v2\FullSolution\lesson_203v2.sln で入手可能。
MainPage.xaml.cs
BME280クラスへの参照を追加:
public sealed partial class MainPage : Page {
// センサークラスの新しいオブジェクトを作成
BME280 BME280;
}
OnNavigatedTo でセンサーを初期化:
// センサークラスの新しいオブジェクトを作成
BME280 = new BME280Sensor();
// センサーを初期化
await BME280.Initialize();
次に、データ収集とログ記録のコードを追加:
- 温度、気圧、湿度、高度の変数を作成、0で初期化
- 海面気圧定数を設定(デフォルト1013.25 hPa)
- 4つの測定値を10回読み取り、デバッグコンソールに出力
// 0で初期化
float temp = 0;
float pressure = 0;
float altitude = 0;
float humidity = 0;
// 海面気圧定数
const float seaLevelPressure = 1022.00f;
// データの10サンプルを読み取り
for (int i = 0; i < 10; i++) {
temp = await BME280.ReadTemperature();
pressure = await BME280.ReadPreasure();
altitude = await BME280.ReadAltitude(seaLevelPressure);
humidity = await BME280.ReadHumidity();
// デバッグコンソールに値を出力
Debug.WriteLine("Temperature: " + temp.ToString() + " deg C");
Debug.WriteLine("Humidity: " + humidity.ToString() + " %");
Debug.WriteLine("Pressure: " + pressure.ToString() + " Pa");
Debug.WriteLine("Altitude: " + altitude.ToString() + " m");
Debug.WriteLine("\n");
}
BME280.cs
BME280.cs を開き、レジスタアドレスenumの後に以下を追加:
// I2Cバスのフレンドリ名文字列
const string I2CControllerName = "I2C1";
// I2Cデバイス作成
private I2cDevice bme280 = null;
// センサー用新しいキャリブレーションデータ作成
BME280_CalibrationData CalibrationData;
// デバイス初期化済みかチェックする変数
bool init = false;
Initialize メソッドを拡張し、I2C接続をセットアップ:
public async Task Initialize() {
Debug.WriteLine("BME280::Initialize");
try {
I2cConnectionSettings settings = new I2cConnectionSettings(BME280_Address);
settings.BusSpeed = I2cBusSpeed.FastMode;
string aqs = I2cDevice.GetDeviceSelector(I2CControllerName);
DeviceInformationCollection dis = await DeviceInformation.FindAllAsync(aqs);
bme280 = await I2cDevice.FromIdAsync(dis[0].Id, settings);
if (bme280 == null) {
Debug.WriteLine("Device not found");
}
} catch (Exception e) {
Debug.WriteLine("Exception: " + e.Message + "\n" + e.StackTrace);
throw;
}
}
Begin ルーチンを追加し、センサー署名を検証してキャリブレーションデータを読み込み:
private async Task Begin() {
Debug.WriteLine("BME280::Begin");
byte[] WriteBuffer = new byte[] { (byte)eRegisters.BMP280_REGISTER_CHIPID };
byte[] ReadBuffer = new byte[] { 0xFF };
bmp280.WriteRead(WriteBuffer, ReadBuffer);
Debug.WriteLine("BME280 Signature: " + ReadBuffer[0].ToString());
if (ReadBuffer[0] != BMP280_Signature) {
Debug.WriteLine("BMP280::Begin Signature Mismatch.");
return;
}
init = true;
CalibrationData = await ReadCoefficeints();
await WriteControlRegister();
await WriteControlRegisterHumidity();
}
制御レジスタヘルパー:
private async Task WriteControlRegisterHumidity() {
byte[] WriteBuffer = new byte[] { (byte)eRegisters.BMP280_REGISTER_CONTROLHUMID, 0x03 };
bmp280.Write(WriteBuffer);
await Task.Delay(1);
}
private async Task WriteControlRegister() {
byte[] WriteBuffer = new byte[] { (byte)eRegisters.BMP280_REGISTER_CONTROL, 0x3F };
bmp280.Write(WriteBuffer);
await Task.Delay(1);
}
レジスタデータ読み取り用ユーティリティ関数:
private UInt16 ReadUInt16_LittleEndian(byte register) {
UInt16 value = 0;
byte[] writeBuffer = new byte[] { 0x00 };
byte[] readBuffer = new byte[] { 0x00, 0x00 };
writeBuffer[0] = register;
bmp280.WriteRead(writeBuffer, readBuffer);
int h = readBuffer[1] << 8;
int l = readBuffer[0];
value = (UInt16)(h + l);
return value;
}
private byte ReadByte(byte register) {
byte value = 0;
byte[] writeBuffer = new byte[] { 0x00 };
byte[] readBuffer = new byte[] { 0x00 };
writeBuffer[0] = register;
bmp280.WriteRead(writeBuffer, readBuffer);
value = readBuffer[0];
return value;
}
キャリブレーションと補正関数はBMP280データシートから直接導出され、すでに提供されています。
ReadTemperature を実装し、センサー温度を摂氏で返却:
public async Task ReadTemperature() {
if (!init) await Begin();
byte tmsb = ReadByte((byte)eRegisters.BMP280_REGISTER_TEMPDATA_MSB);
byte tlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_TEMPDATA_LSB);
byte txlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_TEMPDATA_XLSB);
Int32 t = (tmsb << 12) + (tlsb << 4) + (txlsb >> 4);
double temp = BMP280_compensate_T_double(t);
return (float)temp;
}
ReadPreasure を完成(元のタイポを互換性のため維持):
public async Task ReadPreasure() {
if (!init) await Begin();
if (t_fine == Int32.MinValue) await ReadTemperature();
byte tmsb = ReadByte((byte)eRegisters.BMP280_REGISTER_PRESSUREDATA_MSB);
byte tlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_PRESSUREDATA_LSB);
byte txlsb = ReadByte((byte)eRegisters.BMP280_REGISTER_PRESSUREDATA_XLSB);
Int32 t = (tmsb << 12) + (tlsb << 4) + (txlsb >> 4);
Int64 pres = BMP280_compensate_P_Int64(t);
return ((float)pres) / 256;
}
最後に、ReadAltitude を実装し、気圧公式で高度を計算:
public async Task ReadAltitude(float seaLevel) {
if (!init) await Begin();
float pressure = await ReadPreasure();
pressure /= 100;
return 44330.0f * (1.0f - (float)Math.Pow((pressure / seaLevel), 0.1903f));
}
プロジェクトは今やデプロイ準備完了です!
期待される出力
Temperature: 24.46189 deg C
Humidity: 54.372 %
Pressure: 99738.73 Pa
Altitude: 205.1726 m
ソース: Weather Station V 2.0
製造プロセス
- Raspberry Pi搭載DIYソーラー駆動気象ステーション
- Raspberry Pi 2とADS-WS1で屋外気象観測ステーションを構築
- Raspberry Piで気象観測ステーションを構築し、日次天気データをメール送信
- Raspberry Pi 3とPubNubでリモート気象監視
- 気象観測ステーションをCWOPと統合:実践ガイド
- Weather Monitor:Raspberry Pi自作気象ステーション+Dropboxアップロード
- コンパクト気象ステーション:Arduino Nano & ESP8266 + BMP280 + OLED/Nokia LCD
- 10ドルで作る携帯型Arduino気象観測ステーション – Nano、DHT22、BMP180、LCDで簡単DIY
- eDOT:高精度Arduino時計・気象ステーション(IRリモコン・自動輝度調整内蔵)
- ArduinoとThingSpeakで作るリアルタイム気象モニタリングシステム
- Arduino Nano製ウェザーステーション:気圧・温湿度・UV・時計表示付き