I2Cの温度センサーをWindows 10 IoT Core for Raspberry PI2で使う
今後、https://www.WindowsOnDevices.com から紹介されている、Win10 IoT Core for Raspberry PI2の基本情報は紹介するとして、
https://ms-iot.github.io/content/en-US/win10/samples/I2CAccelerometer.htm
で紹介されているI2Cのセンサー制御サンプルを参考にしながら、I2Cで制御可能な安価な温度センサーTMP102から温度を取得する方法を紹介します。
開発環境やRPI2のROM等の、セットアップ方法は、https://ms-iot.github.io/content/en-US/win10/SetupRPI.htm を参考にしてください。
温度センサー
TMP102 https://www.tij.co.jp/product/jp/tmp102
私が使ったのは、こちら。https://www.sparkfun.com/products/11931 700円ぐらいで購入可能。
これを図の様につないで、
※GNDはRaspberry PI2側の黒いピン(GND)と書かれているピンならどれでもOK)
ADD0はGNDと接続。
Windows 10 Tech PreviewでVisual Studio 2015RCを起動し、新規プロジェクトで、”C#”→”Universal App”→”Blank App”でプロジェクトを作成します。
ソリューションエクスプローラーで、参照を右クリックし、追加で、
Windows Universal の拡張の”Windows IoT Extension SDK”を追加します。
MainPage.xaml.csを開いて、I2C制御のコードを、以下の様に記述します。
public sealed partial class MainPage : Page
{
private const string I2C_CONTROLLER_NAME = "I2C1";
private const byte TMP102_I2C_ADDR = 0x48;
private I2cDevice I2CTMP102;
private const byte I2CTMP102_REG_READ_TEMP = 0x00;
private const byte I2CTMP102_REG_CONFIG = 0x01;
private const byte I2CTMP102_REG_READ_MIN_TEMP = 0x02;
private const byte I2CTMP102_REG_READ_MAX_TEMP = 0x03;
private DispatcherTimer periodicTimer;
private async void InitI2CTemp102()
{
try
{
string
aqs = I2cDevice.GetDeviceSelector(I2C_CONTROLLER_NAME);
var dis = await DeviceInformation.FindAllAsync(aqs);
var settings = new I2cConnectionSettings(TMP102_I2C_ADDR);
settings.BusSpeed = I2cBusSpeed.FastMode;
I2CTMP102 = await I2cDevice.FromIdAsync(dis[0].Id, settings);
if (I2CTMP102 != null)
{
double currentTemp = TakeMeasurementTemperature();
periodicTimer = new DispatcherTimer();
periodicTimer.Interval = TimeSpan.FromMilliseconds(1000);
periodicTimer.Tick += PeriodicTimer_TickMeasureTemperature;
periodicTimer.Start();
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private double TakeMeasurementTemperature()
{
byte[] writeBuf = new byte[] { I2CTMP102_REG_READ_TEMP };
byte[] readBuf = new byte[2];
I2CTMP102.WriteRead(writeBuf, readBuf);
int valh = ((int)readBuf[0]) << 4;
int vall = ((int)readBuf[1] >> 4);
int val = valh + vall;
double unit = 0.0625;
if ((val & 0x800) != 0)
{
val = 0x1000 - val;
unit *= -1;
}
double reading = val * unit;
return reading;
}
private void PeriodicTimer_TickMeasureTemperature(object sender, object e)
{
var currentTemp = TakeMeasurementTemperature();
}
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
InitI2CTemp102();
}
}
TMP102_I2C_ADDRは、ADD0とGNDをつないでいるので”0x48”です。温度は、0x00のレジスターをwriteBufで指定して読み込むと、12Bitで温度がreadBufに格納されて帰ってきます。1バイト目に12ビットの上位8ビット、2バイト目の上位4ビットに、12ビットの下位4ビットが格納されています。単位が、0.0625℃なので、その値をかければ温度が算出できます。12ビットの最上位が1の場合は、補数表示された負の値です。
センサーの詳細は、https://focus.tij.co.jp/jp/lit/ds/symlink/tmp102.pdf から公開されています。上のコードとこのデータシートを見比べると、他のI2Cセンサーを使う場合の一助になると思います。