公式(?)にあるサンプルはちょっとわかりづらかったので簡単な解説的な?ちなみにこちらです。
※というかMCP3002使った時のコード間違ってるんだよねーあとでPRするかな、、、
Raspberry Pi 2にWindows 10 IoT Core(Build10240=Public Release)をのせてるものとします。あとセンサーとしては一般的な3ピンなアナログ温度センサー、A/DコンバーターはMCP3002を使うものとします。
MCP3002のデータシートはこちら
ちなみに回路的にはこちらのBlogの通りです。温度センサーの極性とRaspberry Pi2のGPIOのピン間違わなければまぁ問題ないでしょう。
- Raspberry Piで温度センサー。部屋の気温を取得しよう
- ※記事中のRaspberry Piは2じゃないのでちょっと注意
※回路図のせようと思ったけどhttp://fritzing.org/にサインアップできないので断念。
※あと温度センサーによるのかもしれないけど誤差とかにも注意しましょう(使ったやつは個体によって最大±4℃の精度らしい。。。)。キャリブレーションできるようにアプリ作っておくといいかもですね。
さてWindows 10 IoT Coreで動作するUniversalなアプリを作ってセンサーからデータを読み取ってみましょう。
まずはSPIデバイスの初期化。
private const string SPI_CONTROLLER_NAME = "SPI0"; private const Int32 SPI_CHIP_SELECT_LINE = 0; private SpiDevice SpiDisplay; private async Task InitSPI() { try { var settings = new SpiConnectionSettings(SPI_CHIP_SELECT_LINE); settings.ClockFrequency = 500000; settings.Mode = SpiMode.Mode0; string spiAqs = SpiDevice.GetDeviceSelector(SPI_CONTROLLER_NAME); var deviceInfo = await DeviceInformation.FindAllAsync(spiAqs); SpiDisplay = await SpiDevice.FromIdAsync(deviceInfo[0].Id, settings); } /* If initialization fails, display the exception and stop running */ catch (Exception ex) { throw new Exception("SPI Initialization Failed", ex); } }
SPI0使うように設定してSpiDeviceのインスタンス作ってる感じです。
データ読み取るには以下のようにデバイスのTransferFullDuplex()を呼び出せばいいです。
byte[] readBuffer = new byte[3]; byte[] writeBuffer = new byte[3] { 0x68, 0x00, 0x00 }; //01101000 00; /* It is SPI port serial input pin, and is used to load channel configuration data into the device*/ SpiDisplay.TransferFullDuplex(writeBuffer, readBuffer);
とりあえず後の話はセンサー側とか固有の話なので同じA/Dコンバーターなど使わなければ意味がないかも。
MCP3002の場合は欲しいチャンネルの情報を渡せば10ビットで応答が返る仕様です。WriteBufferに決まった信号をセットします。(1bitは固定で0、2bit目は必ず1(スタートビット)、SGL/DIFFも1、CH0を使うので0、MSBFで受け取るので1、あとは0という感じで0b01101000 = 0x68 であとはゼロ、という感じです。MCP3002は10ビット2chのA/Dコンバーターなんですがスタートビットからの分も含めると1回のやり取りで3バイト分の領域が必要になるのでbyte[3]な感じです。
さてreadBufferには読み取った値が入ってるわけですが必要なデータだけ3バイトの中から抽出します。
private int ConvertToInt(byte[] data) { int result = data[0] & 0x03; result <<= 8; result += data[1]; return result; }
スタートビットから数えると応答の1バイト目の3ビットが有効な値なのでその部分を取得して8ビットシフトして、2バイト目の値をそのまま足します。(なんでというのはデータシートでも見てください)
これでデータがとれました。で、取れた値を温度に変換する必要があります。
使った温度センサーは0℃で500mVの出力電圧で、1℃につき10mV出力電圧が変わる仕様です。なんでざっくり計算するとこんな感じ。
var adc = ConvertToInt(readBuffer); var vol = adc * 3300 / 1024; var t = (vol - 500) / 10.0;
adcの値が得られた値で入力の3.3V(3300mv)を掛けて10ビットの1024で割ると出力電圧がでます。0℃で500mVなので500引いて単位をそろえると摂氏な温度が得られます。
あとは画面に出すなり外部に吐き出すなりお好きなようにどうぞという感じです。
※ブレッドボードで何も考えずつないでやってるあたり、学習コンテンツだなーとは思いますがまぁ面白いからいいです。1万円もかからずにC#(UWP)でアプリが組めてデバイスも触れてという環境はいいんじゃないでしょうか。