Windows10 IoTでI2CとSPIを使ってみる
Raspberry Pi 2に入れたWindows10 IoTでI2CとSPIを動かしてみました。
秋月電子のHDC1000 温度・湿度センサー(I2C)
秋月電子のMCP3204 12bit 4ch ADC(SPI)
------------------------------------------------------------------
using Windows.Devices.Enumeration;
using Windows.Devices.I2c;
private const byte HDC1000_TEMPERATURE_POINTER = 0x00;
private const byte HDC1000_HUMIDITY_POINTER = 0x01;
private const byte HDC1000_CONFIGURATION_POINTER = 0x02;
private const byte HDC1000_SERIAL_ID1_POINTER = 0xfb;
private const byte HDC1000_SERIAL_ID2_POINTER = 0xfc;
private const byte HDC1000_SERIAL_ID3_POINTER = 0xfd;
private const byte HDC1000_MANUFACTURER_ID_POINTER = 0xfe;
private const byte HDC1000_CONFIGURE_MSB = 0x10; /* Get both temperature and humidity */
private const byte HDC1000_CONFIGURE_LSB = 0x00; /* 14 bit resolution */
private I2cDevice I2CTemp;
private async void InitI2CTemp()
{
/* Initialize the I2C bus */
try
{
var settings = new I2cConnectionSettings(TEMP_I2C_ADDR);
settings.BusSpeed = I2cBusSpeed.FastMode;
settings.SharingMode = I2cSharingMode.Shared;
string aqs = I2cDevice.GetDeviceSelector(I2C_CONTROLLER_NAME); /* Find the selector string for the I2C bus controller */
var dis = await DeviceInformation.FindAllAsync(aqs); /* Find the I2C bus controller device with our selector string */
I2CTemp = await I2cDevice.FromIdAsync(dis[0].Id, settings); /* Create an I2cDevice with our selected bus controller and I2C settings */
}
/* If initialization fails, display the exception and stop running */
catch (Exception e)
{
return;
}
// Initialize HDC1000
try
{
byte[] init_cmd = new byte[3];
init_cmd[0] = HDC1000_CONFIGURATION_POINTER;
init_cmd[1] = HDC1000_CONFIGURE_MSB;
init_cmd[2] = HDC1000_CONFIGURE_LSB;
} catch(Exception e)
{
return;
}
private void ReadI2CTemp()
{
byte[] ReadBuf = new byte[4]; /* We read 2 bytes sequentially */
ushort tmp;
int nTemp = 0;
double dTemperature = 0.0;
double dHumidity = 0.0;
// Start convert data.
try
{
byte[] GetCmd = new Byte[1];
GetCmd[0] = HDC1000_TEMPERATURE_POINTER;
I2CTemp.Write(GetCmd );
}
catch (Exception e)
{
return;
}
// ほんとはGPIOでRDYピンの状態を見てあげるのがよい。
try
{
I2CTemp.Read(ReadBuf);
Task.Delay(100);
int tdata = ReadBuf[0] << 8;
tdata |= ReadBuf[1];
int hdata = ReadBuf[2] << 8;
hdata |= ReadBuf[3];
dTemperature = tdata / 65536.0 * 165.0 - 40.0;
dHumidity = hdata / 65536.0 * 100.0;
----------------------------------------
以上のコードでI2Cの初期化、HDC1000の初期化、データ取得が行えます。
続いてSPIでのMCP3204のデータ取得のコードです。
----------------------------------------
/*RaspBerry Pi2 Parameters*/
private const string SPI_CONTROLLER_NAME = "SPI0"; /* For Raspberry Pi 2, use SPI0 */
private const Int32 SPI_CHIP_SELECT_LINE = 0; /* Line 0 maps to physical pin number 24 on the Rpi2 */
byte[] readBuffer = new byte[3]; /*this is defined to hold the output data*/
byte[] writeBuffer = new byte[3] { 0x06, 0x00, 0x00 };//00000110 00; /* It is SPI port serial input pin, and is used to load channel configuration data into the device*/
private async void InitSPI()
{
try
{
var settings = new SpiConnectionSettings(SPI_CHIP_SELECT_LINE);
settings.ClockFrequency = 500000;// 10000000;
settings.Mode = SpiMode.Mode0; //Mode3;
string spiAqs = SpiDevice.GetDeviceSelector(SPI_CONTROLLER_NAME);
var deviceInfo = await DeviceInformation.FindAllAsync(spiAqs);
SpiAdc = 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);
}
SpiAdc.TransferFullDuplex(writeBuffer, readBuffer);
----------------------------------------
以上のコードでデータの取得ができます。I2Cに関してはごく一般的なAPIが用意されており、ほとんど迷いなく動かせると思います。
SPIのほうは少し面倒で、デバイスとの通信方式によってやり方が変わってきます。
MCP3204の場合、以下のように全二重通信で行う必要があるようです。
そのため、単純なRead/Writeではなく、TransferFullDuplexを用いて通信をしています。
以上のコードでI2Cデバイス、SPIデバイスが動かせるようになりました。
それぞれのAPIの仕様や設定項目などはMicrosftのページにある最新のドキュメントを参照してください。
これをベースにオリジナルの気象データ測定用のセンサー基板を作ってみたいと思います。