IoT Core で Raspberry Pi 3 と I2C 接続したセンサーデータを読んでみた。
とりあえず I2C してみたかったのだけれど、I2Cというより、接続したセンサーの仕様と、UWPアプリ向けのGUIに手間取ってしまった。
C# のコードを書くだけで I2C できるのはなかなか良い。
ハードウェア
使ったセンサーモジュールはこれ。 BME280 というICが載っているようだ。
秋月なら同じICでより安い。
ただし、SWITCH SCIENCE版では別のピンにしてあるVcoreとVioがVDDに一本化されている。
※1: BME280のVDDとVDDIOは、基板上で接続されています。
欲張り根性で高機能なセンサーモジュールを買ってしまったら、 設定やら段取りやらが色々あって大変だった。
とりあえず試したい場合は、ただ読めばいいセンサーにした方が良いと思う。
反省である。
センサー設定
BME280 は色々な設定で動作させることができる。
接続するための設定はICのピンへのHI/LOWで行い、 それ以外の設定はICが持っているレジスタに値を書き込むことで行う。
接続設定
今回は I2C したいので、I2C するための設定をする。
CSB を HI にを繋ぐと I2C、 LOW にすると SPI になる。 なので、HIにする。
I2C の場合 SDO の HI/LOW で2つのI2Cアドレスを切り替えることができる。 今回は他に何もバスにつながないので、どちらでもいい。 なんとなくLOWに落とした。
動作設定
色々できて、面倒くさい&よく分からなかったので、 SWITCH SIENCEで公開されているサンプルスケッチを丸パクリした。
GitHubにもコードが提示されている。
BME280/BME280_I2C.ino at master · SWITCHSCIENCE/BME280 · GitHub
1秒に1回更新されれば十分。
IoT Core で I2C
基本的にはその辺に転がっているサンプルコードをパクればいい。
都合よく日本Microsoftの太田さんの記事がクリティカルヒットしていた。 パクれば動く。
多分、大体こんな感じ。
- I2cDevice.GetDeviceSelector にバス名を食わせる。
- Raspberry Pi なら
"I2C1"
- Raspberry Pi なら
- DeviceInformation.FindAllAsync でつながっているバスを探す。
- I2cConnectionSettings に I2Cアドレスを食わせる。
- それらの設定を元に I2cDevice.FromIdAsync で I2cDevice を取得する。
- 取得した I2cDevice オブジェクトを通じて、I2Cバス上の機器と通信する。
ドライバ? 移植の罠
BME280 は高機能だった。
動作設定や、取得したデータの整形など、かなりのコードをサンプルコードとデータシートから移植する羽目になった。
一応コードはGitHubに上げてあるけれど、使い物にならんと思う。 その内リファクタリングしたい。
PropertyChanged の罠
IoT Core では PropertyChanged は UIスレッドから呼ばないと死ぬ。
GUIにプロパティ値の変化を通知する仕組みを GISTS for MVVM UWP with CRUD over a Data Service (Published) · GitHub からパクっていたのだけれど、Timerのイベントからプロパティを変更したら死んでしまった。
UIスレッドで実行してやれば生き残った。
protected async void RaisePropertyChanged(string property) { if (PropertyChanged != null) { // XXX UIスレッドで通知しないと死ぬので、、、 await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.TryRunAsync(CoreDispatcherPriority.Normal, () => { PropertyChanged(this, new PropertyChangedEventArgs(property)); } ); } }
とりあえず読めた
疲れた。 が、これでなんとなく IoT Core で I2C 出来そうな気分になった。