micro:bitにつないだSPI接続センサをブロックエディタから使う

この記事は micro:bit Advent Calendar 2018 の 10日目の記事です。

まえがき

以前、CQ出版インターフェース誌のオフ会で話した内容から抜粋して紹介します。 いや、かなり情報を補足しているような気も。

micro:bitに次の3種類のセンサをつないで、MakeCodeブロックエディタに 標準で用意されているブロックだけを使って、センサ値を読み取ります。 もちろん専用のブロックが用意されていればその方が便利なのですが、 標準ブロックでも何とかなる(場合もある)ことを示します。

  • アナログ出力温度センサ:LM61
  • SPI接続温度センサ:ADT7310
  • I2C接続温度センサ:ADT7410

f:id:yamamoto-works:20181216031747p:plain


対象

今回は、SPI接続温度センサADT7310を取り上げます。

接続

ここでは、ADT7310の電源とGNDをそれぞれmicro:bitの3V端子、GND端子に接続し、 ADT7310のSCLをP13、SDOをP14、SDIをP15、/CS(CSの上に横棒があるのを表現できないので、ここではこう書きます)をP16端子にそれぞれ接続しています。 P13からP15端子は、micro:bitのSPI機能につながっています。

プログラム

作成したプログラムは次のとおりです。 このプログラムは、初期化部と温度測定部からなります。

初期化部

f:id:yamamoto-works:20181216200112p:plain

温度測定部

f:id:yamamoto-works:20181216200141p:plain

プログラムの解説

初期化部

ここではmicro:bitのSPI機能を使うための設定を行います。 まず、念のためにP16に1を出力してセンサをSPIから切り離します。 次にSPIで使う端子の指定、SPI形式として8ビット、モード3の指定を行い、最後にSPI周波数を指定します。 煩雑になるので、この説明は省略します。

次に、「SPI 書き出す」で255を4回書き出しています。 これにより、32ビット連続1を書いています。 その結果、このセンサにリセットがかかります。 この処理は本来不要なはずなのですが、正常に動作しない 場合があるので追加しました。

その前後でP16端子を0にしたり、1にしたりしていますが、これはセンサをSPIに接続するか切り離すかを指定しています。 P16を0にするとセンサがSPIに接続され、1にすると切り離されます。

一方、このセンサはリセット後のデフォルト状態では13ビットの精度で連続温度測定モードになっています。 そこで、温度測定開始を指示するために、「SPI 書き出す」で 84(データシートには16進数で0x54と書いてある)を指定しています。 詳細はデータシートを参照してください。

なお、SPI通信を行うブロックとして「SPI書き出す」は あるのですが、SPIから読み込むブロックはありません。 これはSPI通信の特性によるものです。

SPI通信では、micro:bitからセンサに値を書くと、 その値がトコロテン式にセンサがもっている値を押し出し、 そのセンサがもっていた値がmicro:bitに送られてきます。 今回もセンサに値84を書くと、センサがもっていた値が 変数tmpに代入されます。その値は、ここでは使っていません。

このように、センサに何か値を書くときはセンサから 値が送られますし、逆にセンサから値を読みたいときも 何か値を書く必要があります。 そういうわけで、「SPI書き出し」ブロックしかないのです。

温度測定部

ここの処理は大きく分けて、センサから値を読みだす部分と、 温度を計算する部分からなります。

センサから値を読み出すのは、先ほどと同じくP16を0にして センサをSPIに接続した後、2回に分けて読み出します。 このセンサでは先に上位8ビット、2回目に下位8ビットが 読みだせます。 先ほど説明したように、温度を読み出すにも「SPI書き出す」 ブロックを使います。 それが終わるとP16を1にして、センサをSPIから切り離しています。

次に読みだした値を連結して16ビットの温度データにします。 ビットごとのシフトやORを行うブロックが見当たらなかったので、 掛け算と足し算で代用しています。

センサが13ビットの精度の場合、その16ビットの値の内訳は、 上位9ビットが温度の整数部、その下の4ビットが小数部、 さらにその下の3ビットはセンサの状態を表すフラグ になっています。

最下位3ビットにあるフラグは、温度を表していません。 そこで温度を計算するために、まずフラグを削除します。 先ほど計算した16ビット値を8(2の3乗)で割って 余りを切り捨てることでフラグを削除できます。 まあ、正直に言うと、ごくわずかな影響しかないので、 ここまでしなくても問題ないはずですが。

なお、余りの切り捨て方に、floorとtruncがあります。 温度がプラスの時は同じ動作ですが、 マイナスになったときの動作が異なります。 ー∞に向かって切り捨てるか(floor)、 0に向かって切り捨てるか(trunc)で、 ここではfloorを使っていますが、 ちょっと自信がありません。

次に、4ビットの小数部分を反映させるために、 フラグを削除した値を16(2の4乗)で割ります。 これにより温度を求めることができます。

動作確認

プログラムを実際に動かして、別に用意した温度計と比較してみると、 だいたい同じような値になり、うまくいっているようです。 ただし、温度がマイナスになる場合をテストしていないので、 その動作は確認できていません。

なお、このセンサは16ビット精度で温度を測定できるので、 もし必要であれば温度測定を開始する前にモード設定を行います。


なんか、ずいぶんくどい記事になってしまいましたが、 もしお役に立てば幸いです。