「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
Windows 10 IoT Coreの評価を実施中。
以下のコマンドで切り替え可能。
setbootoption.exe headless shutdown /r /t 0
setbootoption.exe head shutdown /r /t 0
Raspberry Pi 3 MODEL B
micro USB(Androidと同じ)
スイッチとして機能する機器(開発用PCとRaspberry Pi 3を接続する)
ipconfig /all netsh interface ip show config netsh interface ip set address "Ethernet" static [IPアドレス] [サブネットマスク] [デフォゲ]
netsh interface ip set address "Ethernet" static 192.168.1.2 255.255.255.0 192.168.1.1
net user Administrator [パスワード]
setcomputername [新しいマシン名]
Windows 10 IoT Core側の設定に合わせて、
IPアドレス、サブネットマスクなどを変更する。
netsh interface ip set address "Ethernet" static 192.168.1.1 255.255.255.0
Windows 10 IoT Coreとモバイルホットスポット(Wi-Fi)でインターネット接続を共有する。
この設定を行えば、開発用PCと、Windows 10 IoT Coreが、
192.168.137.0/24のサブネットで接続できるようになり、インターネット接続も共有可能になる。
ただし、Windows 10 IoT Core Dashboardから操作するために、有線LAN接続は引き続き必要になる。
Windows 10がインストールされた開発用PCを準備する。
Windows 10 用のWindows SDKをダウンロードしてインストールする。
iotstartup list
iotstartup add headed 完全パッケージ名の先頭部分
iotstartup add headed IoTCoreDefaultApp
[ターゲットバージョン]と[最小バージョン]を選択する。
<Capabilities>
<!-- アプリケーションがカスタムデバイスにアクセスできるようにする -->
<iot:Capability Name="lowLevelDevices" />
<!-- LightningインターフェースのデバイスGUID ID -->
<DeviceCapability Name="109b86ad-f53d-4b76-aa5f-821e2ddf2141"/>
</Capabilities>xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10" IgnorableNamespaces="uap mp iot">
Option 2: Referencing the library
Apple PiのLEDのGPIO numberについては、下記を参照のこと。
LEDの制御(青色LED1=GPIO 5、白色LED2=GPIO 6)
using System.Threading.Tasks;
using Windows.Devices;
using Windows.Devices.Gpio;
using Microsoft.IoT.Lightning.Providers;
namespace App1
{
/// <summary>
/// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
/// </summary>
public sealed partial class MainPage : Page
{
/// <summary>
/// GpioPin #5は青色
/// GpioPin #6は白色
/// </summary>
private readonly int LED_PIN = 6;
/// <summary>GpioPin</summary>
private GpioPin _gpioPin;
/// <summary>Lチカを実装する。</summary>
public MainPage()
{
this.InitializeComponent();
// LightningProviderが利用可能かどうかチェックする。
if (LightningProvider.IsLightningEnabled)
{
// LowLevelDevicesAggregateProviderを取得
LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
}
// GpioControllerを取得
GpioController gpioCtrl = GpioController.GetDefault();
if (gpioCtrl == null)
{
return;
}
// GpioControllerでGpioを取得
this._gpioPin = gpioCtrl.OpenPin(LED_PIN);
// GpioPinでGpioPinをコントロール。
this._gpioPin.SetDriveMode(GpioPinDriveMode.Output);
this._gpioPin.Write(GpioPinValue.High);
this.loop();
}
/// <summary>
/// UIをハングさせないよう、asyncなloop内でawaitを使用する。
/// System.Threading.Threadが無いので、こうなる。
/// </summary>
private async void loop()
{
while (true)
{
// GpioPinでGpioPinをコントロール。
await Task.Delay(1000);
this._gpioPin.Write(GpioPinValue.Low);
await Task.Delay(1000);
this._gpioPin.Write(GpioPinValue.High);
}
}
}
}
using System.Text;
using System.Threading.Tasks;
using Windows.Devices;
using Windows.Devices.I2c;
using Microsoft.IoT.Lightning.Providers;
// 空白ページの項目テンプレートについては、https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x411 を参照してください
namespace App1
{
/// <summary>
/// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
/// </summary>
public sealed partial class MainPage : Page
{
/// <summary>
/// Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
/// (ラズパイ3の GPIO端子の I2C機能を有効にして各種センサーを繋げる方法まとめ)
/// http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_gpio_enable_i2c/
/// </summary>
private readonly byte _Lcd_Addr = 0x3e;
/// <summary>I2cDevice</summary>
private I2cDevice _Lcd;
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
/// <summary>Loaded</summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
await this.InitLcd();
await this.DisplayLcd();
}
/// <summary>
/// LCDを初期化する。
/// 電子工作 - .NET 開発基盤部会 Wiki > 周辺機器 > LCD(液晶ディスプレイ)> I2C LCD AQM0802
/// https://dotnetdevelopmentinfrastructure.osscons.jp/index.php?%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C#b226d3e8
/// </summary>
private async Task InitLcd()
{
// LightningProviderが利用可能かどうかチェックする。
if (LightningProvider.IsLightningEnabled)
{
// LowLevelDevicesAggregateProviderを取得
LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
}
// I2cControllerを取得
I2cController i2cCtrl = await I2cController.GetDefaultAsync();
if (i2cCtrl == null)
{
return;
}
// I2cControllerでLCDを取得。
this._Lcd = i2cCtrl.GetDevice(new I2cConnectionSettings(this._Lcd_Addr));
// 初期化
await WriteLcdCmd(0x38, 1); // 行数の設定
await WriteLcdCmd(0x39, 1); // 拡張コマンドの設定開始
await WriteLcdCmd(0x14, 1); // 内部OSC周波設定
await WriteLcdCmd(0x70, 1); // コントラスト設定
await WriteLcdCmd(0x56, 1); // パワー/アイコン コントラスト設定
await WriteLcdCmd(0x6c, 250); // Follower設定
await WriteLcdCmd(0x38, 1); // 拡張コマンドの設定終了
await WriteLcdCmd(0x0c, 1); // ディスプレイ オン
await WriteLcdCmd(0x01, 2); // ディスプレイ クリア
}
/// <summary>LCDに表示する</summary>
/// <returns>Task</returns>
private async Task DisplayLcd()
{
await WriteLcdCmd(0x01, 2); // ディスプレイ クリア
// 一行目を指定して
await WriteLcdCmd(0x80, 1); // Set DDRAM Address
await WriteLcdDisplay("RzPi3"); // Write data to RAM
// 二行目を指定して
await WriteLcdCmd(0xc0, 2); // Set DDRAM Address
await WriteLcdDisplay("ApplePi"); // Write data to RAM
}
/// <summary>LCDにコマンドを送る</summary>
/// <param name="cmd">byte</param>
/// <param name="waitTime_msec">int</param>
/// <returns>Task</returns>
private async Task WriteLcdCmd(byte cmd, int waitTime_msec)
{
// I2cDeviceでLCDをコントロール。
// 10 bit 書くので2 byte で先頭は空なので 0.
this._Lcd.Write(new byte[] { 0, cmd });
await Task.Delay(waitTime_msec);
}
/// <summary>LCDに表示する</summary>
/// <param name="msg">string</param>
/// <returns>Task</returns>
private async Task WriteLcdDisplay(string msg)
{
byte[] bytesMSG = Encoding.ASCII.GetBytes(msg);
// I2cDeviceでLCDをコントロール。
foreach (byte b in bytesMSG)
{
// 10 bit 書くので2 byte で先頭は・・・
this._Lcd.Write(new byte[] { 0x40, b }); // 先頭0x40は?
}
await Task.Delay(1);
}
}
}
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="tbkTMP" Text="tbkTMP" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="400" Margin="200, 140, 0, 0" TextWrapping="Wrap" FontSize="36" />
<TextBlock x:Name="tbkHUM" Text="tbkHUM" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="400" Margin="200, 210, 0, 0" TextWrapping="Wrap" FontSize="36" />
<TextBlock x:Name="tbkPRE" Text="tbkPRE" HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="400" Margin="200, 280, 0, 0" TextWrapping="Wrap" FontSize="36" />
</Grid>
</Page>
のコードを一部、修正して動かした。
using System.Threading;
using System.Diagnostics;
// 空白ページの項目テンプレートについては、https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x411 を参照してください
namespace App1
{
/// <summary>
/// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
/// </summary>
public sealed partial class MainPage : Page
{
/// <summary>ライブラリ</summary>
private BME280 bme280;
/// <summary>タイマー</summary>
private Timer periodicTimer;
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
/// <summary>Loaded</summary>
/// <param name="sender">object</param>
/// <param name="e">RoutedEventArgs</param>
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
this.bme280 = new BME280();
this.initBme280();
}
/// <summary>初期化</summary>
private async void initBme280()
{
await this.bme280.Initialize();
this.periodicTimer = new Timer(this.TimerCallback, null, 0, 1000);
}
/// <summary>TimerCallback</summary>
/// <param name="state">object</param>
private void TimerCallback(object state)
{
// ココの処理はBackground Threadで動作する。
var temp = bme280.ReadTemperature();
var press = bme280.ReadPreasure() / 100;
var humidity = bme280.ReadHumidity();
var alt = bme280.ReadAltitude(1013); // 1013hPa = pressure at 0m
Debug.WriteLine(
"Temp:{0:F2}℃ Humidity:{1:F2}% Press:{2:F2}hPa Alt:{3:F0}m",
temp, humidity, press, alt);
// 主スレッドで処理する(以下はUWPでのControl.Invokeの書き方らしい)
var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.tbkTMP.Text = temp.ToString("F2") + "℃";
this.tbkHUM.Text = humidity.ToString("F2") + "%";
this.tbkPRE.Text = press.ToString("F2") + "hPa";
});
}
}
}
using System;
using System.Threading.Tasks;
using System.Diagnostics;
using Windows.Devices;
using Windows.Devices.I2c;
using Microsoft.IoT.Lightning.Providers;
namespace App1
{
/// <summary>BME280キャリブレーション用</summary>
public class BME280_CalibrationData
{
// BME280 Registers
/// <summary></summary>
public ushort dig_T1 { get; set; }
/// <summary></summary>
public short dig_T2 { get; set; }
/// <summary></summary>
public short dig_T3 { get; set; }
/// <summary></summary>
public ushort dig_P1 { get; set; }
/// <summary></summary>
public short dig_P2 { get; set; }
/// <summary></summary>
public short dig_P3 { get; set; }
/// <summary></summary>
public short dig_P4 { get; set; }
/// <summary></summary>
public short dig_P5 { get; set; }
/// <summary></summary>
public short dig_P6 { get; set; }
/// <summary></summary>
public short dig_P7 { get; set; }
/// <summary></summary>
public short dig_P8 { get; set; }
/// <summary></summary>
public short dig_P9 { get; set; }
/// <summary></summary>
public byte dig_H1 { get; set; }
/// <summary></summary>
public short dig_H2 { get; set; }
/// <summary></summary>
public byte dig_H3 { get; set; }
/// <summary></summary>
public short dig_H4 { get; set; }
/// <summary></summary>
public short dig_H5 { get; set; }
/// <summary></summary>
public sbyte dig_H6 { get; set; }
}
/// <summary>BME280 本体</summary>
public class BME280
{
#region 各種列挙型
/// <summary>キャリブレーションデータのレジスタアドレス</summary>
enum eCalibrationDataRegistersAddress : byte
{
BME280_REGISTER_DIG_T1 = 0x88,
BME280_REGISTER_DIG_T2 = 0x8A,
BME280_REGISTER_DIG_T3 = 0x8C,
BME280_REGISTER_DIG_P1 = 0x8E,
BME280_REGISTER_DIG_P2 = 0x90,
BME280_REGISTER_DIG_P3 = 0x92,
BME280_REGISTER_DIG_P4 = 0x94,
BME280_REGISTER_DIG_P5 = 0x96,
BME280_REGISTER_DIG_P6 = 0x98,
BME280_REGISTER_DIG_P7 = 0x9A,
BME280_REGISTER_DIG_P8 = 0x9C,
BME280_REGISTER_DIG_P9 = 0x9E,
BME280_REGISTER_DIG_H1 = 0xA1,
BME280_REGISTER_DIG_H2 = 0xE1,
BME280_REGISTER_DIG_H3 = 0xE3,
BME280_REGISTER_DIG_H4_L = 0xE4,
BME280_REGISTER_DIG_H4_H = 0xE5,
BME280_REGISTER_DIG_H5_L = 0xE5,
BME280_REGISTER_DIG_H5_H = 0xE6,
BME280_REGISTER_DIG_H6 = 0xE7,
};
/// <summary>測定データのレジスタアドレス</summary>
enum eDataRegistersAddress : byte
{
BME280_REGISTER_PRESSUREDATA_MSB = 0xF7,
BME280_REGISTER_PRESSUREDATA_LSB = 0xF8,
BME280_REGISTER_PRESSUREDATA_XLSB = 0xF9, // bits <7:4>
BME280_REGISTER_TEMPDATA_MSB = 0xFA,
BME280_REGISTER_TEMPDATA_LSB = 0xFB,
BME280_REGISTER_TEMPDATA_XLSB = 0xFC, // bits <7:4>
BME280_REGISTER_HUMIDDATA_MSB = 0xFD,
BME280_REGISTER_HUMIDDATA_LSB = 0xFE,
};
/// <summary>コマンド</summary>
enum eCmd : byte
{
BME280_REGISTER_CHIPID = 0xD0,
BME280_REGISTER_SOFTRESET = 0xE0,
BME280_REGISTER_CONTROLHUMID = 0xF2,
BME280_REGISTER_STATUS = 0xF3,
BME280_REGISTER_CONTROL = 0xF4,
BME280_REGISTER_CONFIG = 0xF5,
};
/// <summary>
///
/// Enables 2-wire I2C interface when set to ‘0’
/// </summary>
public enum interface_mode_e : byte
{
i2c = 0,
spi = 1
};
/// <summary>
/// スタンバイ時間のオプション
/// t_sb standby options
/// effectively the gap between automatic measurements when in "normal" mode
/// </summary>
public enum standbySettings_e : byte
{
tsb_0p5ms = 0,
tsb_62p5ms = 1,
tsb_125ms = 2,
tsb_250ms = 3,
tsb_500ms = 4,
tsb_1000ms = 5,
tsb_10ms = 6,
tsb_20ms = 7
};
/// <summary>
/// BME280のモード設定
/// sensor modes,
/// it starts off in sleep mode on power on forced is to take a single measurement now normal takes measurements reqularly automatically
/// </summary>
public enum mode_e : byte
{
smSleep = 0,
smForced = 1,
smNormal = 3
};
/// <summary>
/// IIRフィルタの有効/無効
/// Filter coefficients
/// higher numbers slow down changes, such as slamming doors
/// </summary>
public enum filterCoefficient_e : byte
{
fc_off = 0, // OFF
fc_2 = 1,
fc_4 = 2,
fc_8 = 3,
fc_16 = 4
};
/// <summary>
/// Oversampling options for humidity
/// Oversampling reduces the noise from the sensor
/// </summary>
public enum oversampling_e : byte
{
osSkipped = 0,
os1x = 1,
os2x = 2,
os4x = 3,
os8x = 4,
os16x = 5
};
#endregion
#region メンバ変数
/// <summary>
/// Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
/// (ラズパイ3の GPIO端子の I2C機能を有効にして各種センサーを繋げる方法まとめ)
/// http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_3_gpio_enable_i2c/
/// </summary>
const byte BME280_Address = 0x76;
/// <summary>
/// BME280 device signature
/// </summary>
const byte BME280_Signature = 0x60;
/// <summary>
/// String for the friendly name of the I2C bus
/// </summary>
private const string I2CControllerName = "I2C1";
/// <summary>
/// Create an I2C device
/// </summary>
private I2cDevice bme280 = null;
/// <summary>
/// キャリブレーション
/// Create new calibration data for the sensor
/// </summary>
private BME280_CalibrationData CalibrationData;
/// <summary>インターフェイスモード</summary>
private byte spi3w_en = (byte)interface_mode_e.i2c;
/// <summary>スタンバイ時間のオプション</summary>
private byte t_sb;
/// <summary>BME280のモード設定</summary>
private byte mode;
/// <summary>IIRフィルタの有効/無効(サンプリング回数)</summary>
private byte filter;
/// <summary>温度測定の有効(オーバーサンプリング値)/無効</summary>
private byte osrs_t;
/// <summary>気圧測定の有効(オーバーサンプリング値)/無効</summary>
private byte osrs_p;
/// <summary>湿度測定の有効(オーバーサンプリング値)/無告</summary>
private byte osrs_h;
/// <summary>データ校正用変数</summary>
private Int32 t_fine;
#endregion
/// <summary>Constructor</summary>
/// <param name="t_sb">スタンバイ時間のオプション</param>
/// <param name="mode">BME280のモード設定</param>
/// <param name="filter">IIRフィルタの有効/無効(サンプリング回数)</param>
/// <param name="osrs_t">温度測定の有効(オーバーサンプリング値)/無効</param>
/// <param name="osrs_p">気圧測定の有効(オーバーサンプリング値)/無効</param>
/// <param name="osrs_h">湿度測定の有効(オーバーサンプリング値)/無告</param>
public BME280(standbySettings_e t_sb = standbySettings_e.tsb_0p5ms, // 0.5msec
mode_e mode = mode_e.smNormal, // Normal
filterCoefficient_e filter = filterCoefficient_e.fc_16, // サンプリング回数 * 16
oversampling_e osrs_t = oversampling_e.os2x, // オーバーサンプリング * 2
oversampling_e osrs_p = oversampling_e.os16x, // オーバーサンプリング * 16
oversampling_e osrs_h = oversampling_e.os1x) // オーバーサンプリング * 1
{
this.t_sb = (byte)t_sb;
this.mode = (byte)mode;
this.filter = (byte)filter;
this.osrs_t = (byte)osrs_t;
this.osrs_p = (byte)osrs_p;
this.osrs_h = (byte)osrs_h;
}
#region 初期化
/// <summary>
/// Method to initialize the BME280 sensor
/// </summary>
/// <returns></returns>
public async Task Initialize()
{
Debug.WriteLine("BME280::Initialize");
try
{
////Instantiate the I2CConnectionSettings using the device address of the BME280
//I2cConnectionSettings settings = new I2cConnectionSettings(BME280_Address);
////Set the I2C bus speed of connection to fast mode
//settings.BusSpeed = I2cBusSpeed.FastMode;
////Use the I2CBus device selector to create an advanced query syntax string
//string aqs = I2cDevice.GetDeviceSelector(I2CControllerName);
////Use the Windows.Devices.Enumeration.DeviceInformation class to create a collection using the advanced query syntax string
//DeviceInformationCollection dis = await DeviceInformation.FindAllAsync(aqs);
////Instantiate the the BME280 I2C device using the device id of the I2CBus and the I2CConnectionSettings
//bme280 = await I2cDevice.FromIdAsync(dis[0].Id, settings);
// LightningProviderが利用可能かどうかチェックする。
if (LightningProvider.IsLightningEnabled)
{
// LowLevelDevicesAggregateProviderを取得
LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
}
// I2cControllerを取得
I2cController i2cCtrl = await I2cController.GetDefaultAsync();
if (i2cCtrl == null)
{
return;
}
// I2cControllerでbme280を取得。
this.bme280 = i2cCtrl.GetDevice(new I2cConnectionSettings(BME280.BME280_Address));
//Check if device was found
if (this.bme280 == null)
{
Debug.WriteLine("Device not found");
}
}
catch (Exception e)
{
Debug.WriteLine("Exception: " + e.Message + "\n" + e.StackTrace);
throw;
}
byte[] readChipID = new byte[] { (byte)eCmd.BME280_REGISTER_CHIPID };
byte[] ReadBuffer = new byte[] { 0xFF };
// Read the device signature
bme280.WriteRead(readChipID, ReadBuffer);
Debug.WriteLine("BME280 Signature: " + ReadBuffer[0].ToString());
// Verify the device signature
if (ReadBuffer[0] != BME280.BME280_Signature)
{
Debug.WriteLine("BME280::Begin Signature Mismatch.");
return;
}
// Read the coefficients table
// キャリブレーション読み取り
this.CalibrationData = this.ReadCoefficeints();
#region レジスタの設定
// Set configuration registers
this.WriteConfigRegister(); // configレジスタ
this.WriteControlMeasurementRegister(); // ctrl_measレジスタ
this.WriteControlRegisterHumidity(); // ctrl_humレジスタ
//Set configuration registers again to ensure configuration of humidity
this.WriteConfigRegister();
this.WriteControlMeasurementRegister();
this.WriteControlRegisterHumidity();
#endregion
//Dummy read temp to setup t_fine
this.ReadTemperature();
}
#region キャリブレーション読み取り
/// <summary>
/// BME280キャリブレーション読み取り
/// Method to read the caliberation data from the registers
/// </summary>
/// <returns></returns>
private BME280_CalibrationData ReadCoefficeints()
{
// 16 bit calibration data is stored as Little Endian, the helper method will do the byte swap.
this.CalibrationData = new BME280_CalibrationData();
// Read temperature calibration data
this.CalibrationData.dig_T1 = this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_T1);
this.CalibrationData.dig_T2 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_T2);
this.CalibrationData.dig_T3 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_T3);
// Read presure calibration data
this.CalibrationData.dig_P1 = this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P1);
this.CalibrationData.dig_P2 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P2);
this.CalibrationData.dig_P3 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P3);
this.CalibrationData.dig_P4 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P4);
this.CalibrationData.dig_P5 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P5);
this.CalibrationData.dig_P6 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P6);
this.CalibrationData.dig_P7 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P7);
this.CalibrationData.dig_P8 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P8);
this.CalibrationData.dig_P9 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_P9);
// Read humidity calibration data
this.CalibrationData.dig_H1 = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H1);
this.CalibrationData.dig_H2 = (short)this.ReadUInt16_LittleEndian((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H2);
this.CalibrationData.dig_H3 = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H3);
short e4 = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H4_L); // Read 0xE4
short e5 = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H4_H); // Read 0xE5
this.CalibrationData.dig_H4 = (short)((e4 << 4) + (e5 & 0x0F));
short e6 = this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H5_H); // Read 0xE6
this.CalibrationData.dig_H5 = (short)((e5 >> 4) + (e6 << 4));
this.CalibrationData.dig_H6 = (sbyte)this.ReadByte((byte)eCalibrationDataRegistersAddress.BME280_REGISTER_DIG_H6);
return CalibrationData;
}
#endregion
#region レジスタの設定
/// <summary>
/// configレジスタの設定
/// ・t_sb : スタンバイ時間
/// ・filter : IIRフィルタの有効/無効
/// ・spi3w_en : 3 wire SPIの有効/無効
/// ----------
/// Method to write the config register (default 16)
/// 000 100 00
/// ↑ ↑ ↑I2C mode
/// ↑ ↑Filter coefficient = 16
/// ↑t_sb = 0.5ms
/// </summary>
private void WriteConfigRegister()
{
byte value = (byte)((this.t_sb << 5) + (this.filter << 2) + this.spi3w_en);
byte[] WriteBuffer = new byte[] { (byte)eCmd.BME280_REGISTER_CONFIG, value };
bme280.Write(WriteBuffer);
return;
}
/// <summary>
/// ctrl_measレジスタの設定
/// ・osrs_t : 温度測定の有効(オーバーサンプリング値)/無効
/// ・osrs_p : 気圧測定の有効(オーバーサンプリング値)/無効
/// ・mode : BME280の測定モード設定
/// ----------
/// Method to write the control measurment register (default 87)
/// 010 101 11
/// ↑ ↑ ↑ mode
/// ↑ ↑ Pressure oversampling
/// ↑ Temperature oversampling
/// </summary>
private void WriteControlMeasurementRegister()
{
byte value = (byte)((this.osrs_t << 5) + (this.osrs_p << 2) + this.mode);
byte[] WriteBuffer = new byte[] { (byte)eCmd.BME280_REGISTER_CONTROL, value };
bme280.Write(WriteBuffer);
return;
}
/// <summary>
/// ctrl_humレジスタの設定
/// ・osrs_h : 湿度測定の有効(オーバーサンプリング値)/無告
/// ----------
/// Method to write the humidity control register (default 01)
/// </summary>
private void WriteControlRegisterHumidity()
{
byte value = this.osrs_h;
byte[] WriteBuffer = new byte[] { (byte)eCmd.BME280_REGISTER_CONTROLHUMID, value };
bme280.Write(WriteBuffer);
return;
}
#endregion
#endregion
#region センサーを読む
/// <summary>気温を読む</summary>
/// <returns>float</returns>
public float ReadTemperature()
{
//Read the MSB, LSB and bits 7:4 (XLSB) of the temperature from the BME280 registers
byte tmsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_TEMPDATA_MSB);
byte tlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_TEMPDATA_LSB);
byte txlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_TEMPDATA_XLSB); // bits 7:4
//Combine the values into a 32-bit integer
int t = (tmsb << 12) + (tlsb << 4) + (txlsb >> 4);
//Convert the raw value to the temperature in degC
double temp = this.BME280_compensate_T_double(t);
//Return the temperature as a float value
return (float)temp;
}
/// <summary>気圧を読む</summary>
/// <returns>float</returns>
public float ReadPreasure()
{
//Read the MSB, LSB and bits 7:4 (XLSB) of the pressure from the BME280 registers
byte pmsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_PRESSUREDATA_MSB);
byte plsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_PRESSUREDATA_LSB);
byte pxlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_PRESSUREDATA_XLSB); // bits 7:4
//Combine the values into a 32-bit integer
int p = (pmsb << 12) + (plsb << 4) + (pxlsb >> 4);
//Convert the raw value to the pressure in Pa
long pres = this.BME280_compensate_P_Int64(p);
//Return the pressure as a float value
return ((float)pres) / 256;
}
/// <summary>湿度を読む</summary>
/// <returns></returns>
public float ReadHumidity()
{
//Read the MSB and LSB of the humidity from the BME280 registers
byte hmsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_HUMIDDATA_MSB);
byte hlsb = this.ReadByte((byte)eDataRegistersAddress.BME280_REGISTER_HUMIDDATA_LSB);
//Combine the values into a 32-bit integer
int h = (hmsb << 8) + hlsb;
//Convert the raw value to the humidity in %
double humidity = this.BME280_compensate_H_double(h);
//Return the humidity as a float value
return (float)humidity;
}
#endregion
#region 表示用文字列の作成
/// <summary>
/// ℃で温度を戻すメソッド
/// 分解能は0.01℃。
/// Method to return the temperature in DegC. Resolution is 0.01 DegC.
/// Output value of “51.23” equals 51.23 DegC.
/// </summary>
/// <param name="adc_T"></param>
/// <returns></returns>
private double BME280_compensate_T_double(int adc_T)
{
double var1, var2, T;
//The temperature is calculated using the compensation formula in the BME280 datasheet
var1 = (adc_T / 16384.0 - CalibrationData.dig_T1 / 1024.0) * CalibrationData.dig_T2;
var2 = ((adc_T / 131072.0 - CalibrationData.dig_T1 / 8192.0) *
(adc_T / 131072.0 - CalibrationData.dig_T1 / 8192.0)) * CalibrationData.dig_T3;
this.t_fine = (int)(var1 + var2);
T = (var1 + var2) / 5120.0;
return T;
}
/// <summary>
/// Q24.8形式(24の整数ビットと8の小数ビット)のPaの圧力を返すメソッド。
/// Method to returns the pressure in Pa, in Q24.8 format (24 integer bits and 8 fractional bits).
/// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
/// </summary>
/// <param name="adc_P">int</param>
/// <returns>long</returns>
private long BME280_compensate_P_Int64(int adc_P)
{
long var1, var2, p;
//The pressure is calculated using the compensation formula in the BME280 datasheet
var1 = (long)this.t_fine - 128000;
var2 = var1 * var1 * CalibrationData.dig_P6;
var2 = var2 + ((var1 * CalibrationData.dig_P5) << 17);
var2 = var2 + ((long)CalibrationData.dig_P4 << 35);
var1 = ((var1 * var1 * CalibrationData.dig_P3) >> 8) + ((var1 * CalibrationData.dig_P2) << 12);
var1 = (((long)1 << 47) + var1) * CalibrationData.dig_P1 >> 33;
if (var1 == 0)
{
Debug.WriteLine("BME280_compensate_P_Int64 Jump out to avoid / 0");
return 0; //Avoid exception caused by division by zero
}
//Perform calibration operations as per datasheet:
p = 1048576 - adc_P;
p = (((p << 31) - var2) * 3125) / var1;
var1 = ((long)CalibrationData.dig_P9 * (p >> 13) * (p >> 13)) >> 25;
var2 = ((long)CalibrationData.dig_P8 * p) >> 19;
p = ((p + var1 + var2) >> 8) + ((long)CalibrationData.dig_P7 << 4);
return p;
}
/// <summary>
/// %rHの湿度をdoubleとして返す。
/// Returns humidity in %rH as as double. Output value of “46.332” represents 46.332 %rH
/// </summary>
/// <param name="adc_H"></param>
/// <returns></returns>
private double BME280_compensate_H_double(int adc_H)
{
double var_H;
var_H = this.t_fine - 76800.0;
var_H = (adc_H - (CalibrationData.dig_H4 * 64.0 + CalibrationData.dig_H5 / 16384.0 * var_H)) *
CalibrationData.dig_H2 / 65536.0 * (1.0 + CalibrationData.dig_H6 / 67108864.0 * var_H *
(1.0 + CalibrationData.dig_H3 / 67108864.0 * var_H));
var_H = var_H * (1.0 - CalibrationData.dig_H1 * var_H / 524288.0);
if (var_H > 100.0)
{
Debug.WriteLine("BME280_compensate_H_double Jump out to 100%");
var_H = 100.0;
}
else if (var_H < 0.0)
{
Debug.WriteLine("BME280_compensate_H_double Jump under 0%");
var_H = 0.0;
}
return var_H;
}
/// <summary>
/// 気圧から高度を計算するメソッド
/// Method to take the sea level pressure in Hectopascals(hPa) as a parameter and calculate the altitude using current pressure.
/// </summary>
/// <param name="seaLevel">float</param>
/// <returns>float</returns>
public float ReadAltitude(float seaLevel)
{
//Read the pressure first
float pressure = this.ReadPreasure();
//Convert the pressure to Hectopascals(hPa)
pressure /= 100;
//Calculate and return the altitude using the international barometric formula
return 44330.0f * (1.0f - (float)Math.Pow((pressure / seaLevel), 0.1903f));
}
#endregion
#region 読み取り
/// <summary>
/// Method to read an 8-bit value from a register
/// </summary>
/// <param name="register">byte</param>
/// <returns>byte</returns>
private byte ReadByte(byte register)
{
byte value = 0;
byte[] writeBuffer = new byte[] { 0x00 };
byte[] readBuffer = new byte[] { 0x00 };
writeBuffer[0] = register;
bme280.WriteRead(writeBuffer, readBuffer);
value = readBuffer[0];
return value;
}
/// <summary>
/// Method to read a 16-bit value from a register and return it in little endian format
/// </summary>
/// <param name="register">byte</param>
/// <returns>ushort</returns>
private ushort ReadUInt16_LittleEndian(byte register)
{
ushort value = 0;
byte[] writeBuffer = new byte[] { 0x00 };
byte[] readBuffer = new byte[] { 0x00, 0x00 };
writeBuffer[0] = register;
bme280.WriteRead(writeBuffer, readBuffer);
int h = readBuffer[1] << 8;
int l = readBuffer[0];
value = (ushort)(h + l);
return value;
}
#endregion
}
}
上記のセンサー情報をCoreTweet?というライブラリを使用してTwitterにTweetする。
CoreTweet?は、Twitter APIのクライアント・ライブラリなので、
非常に多機能っぽいが、ここではTweetするAPIを利用するだけ。
Twitterからエラーが返った場合、以下のエラー一覧が参考になる。
using System.Threading; using System.Diagnostics; using CoreTweet;・・・
/// <summary>ライブラリ</summary>
private BME280 bme280;
/// <summary>SensorのTimer</summary>
private Timer periodicTimer;
/// <summary>TwitterのTimer</summary>
private DispatcherTimer twitterTimer;
/// <summary>TwitterのToken</summary>
private Tokens tokens;
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
/// <summary>Loaded</summary>
/// <param name="sender">object</param>
/// <param name="e">RoutedEventArgs</param>
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
this.bme280 = new BME280();
this.initBme280();
this.initTwitter();
}
/// <summary>Twitterの初期化</summary>
private void initTwitter()
{
// 実際の値を入力する。その際、{}は削除する。
this.tokens = Tokens.Create(
"{API key}"
, "{API secret}"
, "{Access token}"
, "{Access token secret}");
this.twitterTimer = new DispatcherTimer();
this.twitterTimer.Interval = TimeSpan.FromSeconds(10); // Tweet間隔を調整
this.twitterTimer.Tick += this.TimerCallback;
this.twitterTimer.Start();
}
/// <summary>Bme280の初期化</summary>
private async void initBme280()
{
await this.bme280.Initialize();
this.periodicTimer = new Timer(this.TimerCallback, null, 0, 1000);
}
/// <summary>TwitterのTimerCallback</summary>
/// <param name="state">object</param>
private void TimerCallback(object sender, object e)
{
string text =
this.tbkTMP.Text +"\r\n"
+ this.tbkHUM.Text + "\r\n"
+ this.tbkPRE.Text;
Debug.WriteLine("Tweet :" + text);
this.tweet(text);
}
/// <summary>tweetする</summary>
/// <param name="text">tweetのテキスト</param>
private async void tweet(string text)
{
Status _status = await this.tokens.Statuses.UpdateAsync(status => text);
}
/// <summary>Bme280のTimerCallback</summary>
/// <param name="state">object</param>
private void TimerCallback(object state)
・・・https://github.com/ms-iot/samples
Tags: :インフラストラクチャ, :Windows, :IoT