koudenpaのブログ

趣味のブログです。株式会社はてなでWebアプリケーションエンジニアをやっています。職業柄IT関連の記事が多いと思います。

Windows 10 IoT Core で I2C

IoT Core で Raspberry Pi 3 と I2C 接続したセンサーデータを読んでみた。

とりあえず I2C してみたかったのだけれど、I2Cというより、接続したセンサーの仕様と、UWPアプリ向けのGUIに手間取ってしまった。

C# のコードを書くだけで I2C できるのはなかなか良い。

github.com

ハードウェア

使ったセンサーモジュールはこれ。 BME280 というICが載っているようだ。

www.switch-science.com

秋月なら同じICでより安い。

akizukidenshi.com

ただし、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に落とした。

f:id:koudenpa:20160516052401p:plain

動作設定

色々できて、面倒くさい&よく分からなかったので、 SWITCH SIENCEで公開されているサンプルスケッチを丸パクリした。

BME280 – スイッチサイエンス

GitHubにもコードが提示されている。

BME280/BME280_I2C.ino at master · SWITCHSCIENCE/BME280 · GitHub

1秒に1回更新されれば十分。

IoT Core で I2C

基本的にはその辺に転がっているサンプルコードをパクればいい。

都合よく日本Microsoftの太田さんの記事がクリティカルヒットしていた。 パクれば動く。

blogs.msdn.microsoft.com

多分、大体こんな感じ。

  1. I2cDevice.GetDeviceSelector にバス名を食わせる。
    • Raspberry Pi なら "I2C1"
  2. DeviceInformation.FindAllAsync でつながっているバスを探す。
  3. I2cConnectionSettings に I2Cアドレスを食わせる。
  4. それらの設定を元に I2cDevice.FromIdAsyncI2cDevice を取得する。
  5. 取得した 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));
                  }
               );
            }
        }

とりあえず読めた

f:id:koudenpa:20160516045805p:plain

疲れた。 が、これでなんとなく IoT Core で I2C 出来そうな気分になった。