マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

Windows 10 IoT Coreの評価を実施中。

基本

Headモード、Headlessモード

Headモード

Headlessモード

切替方法

以下のコマンドで切り替え可能。

ドライバの種類

Inboxドライバ

DMAPドライバ

準備

開発用PC

IoT機器

本体

Raspberry Pi 3 MODEL B

電源

micro USB(Androidと同じ)

周辺機器

ストレージ

ネットワーク

スイッチとして機能する機器(開発用PCとRaspberry Pi 3を接続する)

入出力

セットアップ

Windows 10 IoT Coreのインストール

Windows 10 IoT Core Dashboardのダウンロード

microSDにWindows 10 IoT CoreのOSイメージを書き込む。

Raspberry Pi 3へ機器を接続

Windows 10 IoT Coreの初期設定をする。

起動時

その他、適宜

Windows 10 IoT Core Dashboardから接続・操作する。

Device Portal

SMB

PowerShell

開発用PC側のIPアドレスを設定/変更する。

IPアドレス、サブネットマスクなどを変更する。

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接続は引き続き必要になる。

開発環境

開発用PCの準備

Windows 10がインストールされた開発用PCを準備する。

開発環境のセットアップ

Visual Studio 2017をインストールする。

開発者モードを有効にする。

Windows SDKのインストール

Windows 10 用のWindows SDKをダウンロードしてインストールする。

“Hello World”的にサンプルを実行する準備

サンプル・プログラムをGitHubからDownloadZIPする。

HelloWorld?する。

HelloBlinky?する。

サンプル・プログラムをデプロイして起動する。

デプロイ

スタートアップアプリに指定

いろいろな処理を実装する。

空のプロジェクトから実装を始める。

プロジェクトの新規作成

UWP バージョンを選択する

[ターゲットバージョン]と[最小バージョン]を選択する。

Debug実行

Writing apps開発の設定を行う

Lチカを実装する。

デバイス

Apple PiのLEDのGPIO numberについては、下記を参照のこと。

MainPage?.xaml.cs

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);
            }
        }
    }
}

LCDに文字を表示する。

デバイス

MainPage?.xaml.cs

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);
        }
    }
}

センサーからデータを取得する。

デバイス

MainPage?.xaml

<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>

MainPage?.xaml.cs

のコードを一部、修正して動かした。

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";
            });
        }
    }
}

BME280.cs

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
    }
}

結果

SensorData

Twitterにセンサー情報をTweetする。

上記のセンサー情報をCoreTweet?というライブラリを使用してTwitterにTweetする。

CoreTweet?は、Twitter APIのクライアント・ライブラリなので、
非常に多機能っぽいが、ここではTweetするAPIを利用するだけ。

Twitterからエラーが返った場合、以下のエラー一覧が参考になる。

Twitter登録

  1. サインアップして、
  2. サインインする。
  3. Twitterの開発者サイトに移動し、
  4. My Appsのリンクをクリックする。
  5. そして、Create New Appボタンを押下する。
  6. [Create an application]画面で以下のように入力して、
    Twitter1
  7. [Create youre Twitter application]ボタンを押下する。
  8. アプリケーション登録後、登録したアプリケーションの画面に遷移するので、
  9. そこで、[Keys and Access Tokens Permissions]タブを押下する。
  10. 表示される[Consumer Key (API Key)], [Consumer Secret (API Secret)]をメモ。
    Twitter2
  11. 次に、当該画面の下部にある[Create my access token]ボタンを押下、
    [Access Token], [Access Token Secret]を入手してコレをメモする。
    Twitter3
  12. この4つのキー[Consumer Key], [Consumer Secret], [Access Token], [Access Token Secret]を使用してTweetを行う。

MainPage?.xaml.cs

結果

SensorTweet

Wio Nodeを使用する。

Wio NodeのデバイスのデータをRESTで取得する。

Wio NodeのデバイスをRESTで操作する。

監視カメラを実装する。

参考

電子工作

Build Insider

MS

ms-iot/samples: Windows 10 IoT Core Samples

https://github.com/ms-iot/samples

Windows 10 IoTCore ハンズオントレーニング

電子工作(MAKE)


Tags: :インフラストラクチャ, :Windows, :IoT


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS