対象読者
IoTに興味があり、C#と電子工作の基本的な知識がある方を対象とします。C#や電子工作のごく初歩的な説明は割愛していますので、「C#ではじめるラズパイIoTプログラミング」の記事なども併せて参照してください。
はじめに
前回から、Bluetoothを利用して環境データをモニタリングするプログラムを作成しています。前回は、センサーの計測処理とBluetooth Low Energy(以下、BLEと表記)通信の基本となるプログラムを作成しました。
今回は、前回のプログラムを踏まえて、BLEで定期的に測定値を送信するプログラムと、Wi-Fi経由でAmbientに送信するプログラムを解説します。
ESP32のアプリケーション(1)
まずは、センサーで測定した値を、BLE通信でブロードキャストするプログラムを作成します。
ESP32の接続と新規アプリケーションの作成
ESP32と環境センサーBME680との接続は前回同様です。ESP32のGPIO18をセンサーモジュールのSDA、GPIO19をSCLに接続します。
Visual Studioのプロジェクトは、.NET nanoFrameworkのBlankアプリのテンプレートを選びます。今回も、センサーの通信にはI2C、またBME680に対応したクラスを利用します。
またBluetooth通信も利用するので、次のパッケージをNuGetパッケージマネージャなどでインストールしておきます。
- nanoFramework.Hardware.Esp32
- nanoFramework.System.Device.I2c
- nanoFramework.Iot.Device.Bmxx80
- nanoFramework.Device.Bluetooth
今回のアプリでは、各処理を4つのメソッドに分けて作成しました。順に説明していきます。
メソッド | 概要 |
---|---|
InitializeBme680Sensor() | I2CとBME680の初期設定 |
ReadSensorData() | BME680での測定と値を取得するデリゲート |
InitializeAdvertiser() | BLEブロードキャスト(アドバタイズ)の初期設定 |
SendSensorData() | 送信データの更新 |
基本のセンサー制御コード
最初に、I2CとBME680の初期設定である、InitializeBme680Sensor()メソッドです。
// BME680センサーオブジェクト private static Bme680 _bme680; public class Program { // I2CとBME680制御の初期化 private static void InitializeBme680Sensor() { // I2C接続を設定 Configuration.SetPinFunction(18, DeviceFunction.I2C1_DATA); Configuration.SetPinFunction(19, DeviceFunction.I2C1_CLOCK); I2cConnectionSettings i2cSettings = new(1, 0x77); I2cDevice i2cDevice = I2cDevice.Create(i2cSettings); // BME680センサーのインスタンスを作成 _bme680 = new(i2cDevice); _bme680.Reset(); // 5秒ごとにセンサー値を読み取る(1) new Timer(ReadSensorData, null, 0, 5000); } ~中略~ }
前回は無限ループ内でセンサー値を取得しましたが、今回はタイマー(System.Threading.Timerクラス)を用いています(1)。
Timerクラスのコンストラクタでは、センサー値を取得するデリゲートのReadSensorDataを第1引数に指定しています。このデリゲートのパラメータは不要なので、第2引数はnullとします。第3引数は、最初に呼び出されるまでの待機時間で、ここは0とします。最後の引数では、呼び出し間隔の5秒を指定しています。つまり、このタイマーでは、5秒ごとにセンサーの測定値を読み込みます。
タイマーで呼び出されるReadSensorDataデリゲートは、次のようにラムダ式の形で定義しました。
// 測定を実行してデータを送信する static readonly TimerCallback ReadSensorData = state => { // センサーを強制モードに設定して測定を実行(1) _bme680.SetPowerMode(Bme680PowerMode.Forced); // センサーデータの読み取り(2) if (_bme680.TryReadTemperature(out var temp) && _bme680.TryReadPressure(out var pressure) && _bme680.TryReadHumidity(out var humidity) && _bme680.TryReadGasResistance(out var gas)) { // センサーデータを送信する(3) SendSensorData(temp.DegreesCelsius, humidity.Percent, pressure.Hectopascals, gas.Kiloohms); } };
ReadSensorDataでのセンサー値を取得する処理では、前回と異なり、BME680の電源モードを強制モードに設定して測定を実行します。強制モードとは、気温、気圧、湿度、ガス抵抗を順に1回だけ測定するモードです(1)。
(2)のTryRead~メソッドは、正常に測定値を取得できた場合にtrueを返し、outパラメータの引数に測定値が格納されます。すべての測定値が正常に取得できれば、4つの測定値を引数にしてSendSensorDataメソッドを呼び出します(3)。測定値がそろわなければ、その回の測定では送信しません。