「GR-PEACH + NETMFで1行プログラミング」LT資料を公開しました (ルネサスナイト 9、2016年7月23日 (土) 開催)

30日(土) の勉強会資料の公開とは順番が逆になってしまいましたが、7月23日(土) 開催のルネサスナイト 9 に参加して LT登壇しました。

https://docs.com/d/embed/D25193197-9500-6085-1560-001018019056%7eBfe5a7bff-fc39-9c7d-d35f-86e930988702

皆さん、ガチで組込み開発をされている方ばかりで相当場違い、アウェイな感じでしたが、得るものも多く有意義な時間でした。

そういう方たちに向けて、GR-PEACH で動作する .NET Micro Framework の紹介をしました。

GR-PEACH の特徴の一つがマルチプラットフォームなのですが、NETMF on GR-PEACH は肩身が狭く、当日のイベントでも冒頭に「マルチプラットフォームで .NET Micro Framework も動く」という一言だけで片付けられる始末・・・orz
そういう場所で、.NET Micro Framework を認知してもらう程度にはお役に立てたと思っています。
裏にライブラリがあるから、C#だから、Visual Studio があるからという理由があるにしても、ボタンと LED 程度ならば本当に 1行で書けるわけで、これは他のプラットフォームや言語に対するメリットだと思います。(もちろんケースバイケースで向き不向きはあるはずですが)

LT は持ち時間 4分、そのうち 2分はライブコーディング(1行だけですが)の構成で作った資料なので、ツールやライブラリのダウンロードサイトの紹介、1行プログラミングの例を載せただけです。

これで NETMF に興味を持った方は、ぜひこのブログや MS 太田さんのブログハンズオン資料を見て、NETMF を楽しんでほしいと思います。

GR-SAKURAⅡで .NET Micro Framework を動かしてみる

先日、GR-SAKURA II が発売されました。(何故かひっそりと)
前バージョンの GR-SAKURA に対してメモリ容量が倍になっているとのこと。

38320002

ということで、.NET Micro Framework を動かしてみました。
世間ではすっかり Windows 10 IoT 一色な感じですが、

  • NETMF は軽い
  • 起動が速い
  • シャットダウンの面倒がない
  • APIセットが分かりやすい(個人的な好みも若干ありますが・・・)

と、メリットがたくさんあります。
特に今回、久しぶりに SAKURA で NETMF を動かしてみて、アプリ転送からリブート、起動までの時間の速さに驚きました。これならどんどんデバッグできます。
(あとは、GR-PEACHに比べてお手頃な価格もうれしい)

さて、GR-SAKURA II で NETMF を動かすためには、まずはファームの書き込みが必要です。これについてはマイクロソフトの太田さんのブログで詳しく解説されているので、そちらを参照してください。

まだボード上の LED とボタンしか確認できていませんが、Lチカも GrFamily ライブラリも問題なく動作しています。
「PEACH はちょっと高いんだよね」という方も、「ラズパイ以外も触ってみたい」という方も、SAKURA を試してみては。快適なマイコンボード開発、IoT が楽しめますよ。

WP_20160627_22_27_56_Pro

GR ファミリー用ライブラリを Visual Studio 2015 Update 2 対応しました

追記)4月27日に公開した API リファレンスの構成が壊れているという連絡をいただきました。29日未明に修正版をコミットしました。すでにダウンロード済みの方はお手数ですが、再度最新版をダウンロードしてください。
なおバージョン番号は変更していません。

.NET Micro Framework v4.3 QFE2 と Visual Studio 2015 Update 2 との微妙な問題が解決し、GR-Family ライブラリの既存分の動作確認を終え、(超手抜きながら・・・)API リファレンスもなんとか作りました。

ということで、昨年秋に公開して少しずつ手を加え続けている、GR-Family ライブラリを改めて宣伝します。

https://github.com/netmf-lib-grfamily/GrFamilyLibrary

中味は全然すごくなくて、いちいち GPIO 操作する面倒を隠蔽したり I2C の低レベルの操作をラッピングしているだけなんですが、よろしければご活用ください。
GR-PEACH や PinKit をお持ちの方には便利に使えると思います。

 

そろそろ Windows 10 IoT 用のライブラリにも着手しようかな。皆さんにとっては素のままでも十分簡単なのか、ライブラリ化する人が出てこないけど、やっぱりコーディングは少しでもラクできるほうがいいですよね。

「IoT ALGYAN ハンズオンのソースコード解説します」セッション資料を公開しました(Techfair.jp 勉強会 2016年3月19日開催)

2016年3月19日(土) に、Techfair.jp 主催、IoT ALGYAN 協力の勉強会

「IoT ALGYAN ハンズオンのソースコード解説します」

を開催しました。

IoT ALGYAN のハンズオンのソースを起点に、.NET Micro Framework やマイコンボードのプログラミングについて解説するというものです。あわせて Windows 10 IoT ではどう書くのかも紹介しました。

セッション資料は docs.com で公開しています。参加した皆さんは復習のため、参加していない方はマイコンボードプログラミングの参考にお使いください。

マイコンボードプログラミングは決して難しくはないものの、未経験の方にはとっつきにくいかもしれません。
そのハードルを越えるために、資料を活用してください。

参加者は決して多くはなかったものの、今回は内容についての評価が高く、参加者の期待には答えることができたと思います。
今後の勉強会では、ハンズオン資料のクラウド側の部分の解説をしたいと思います。が、単にコード解説ではなくて知見のあるスピーカーを呼んでセッション形式のパートもあるといいかもしれませんね。役に立って楽しいイベントになるように少し企画を検討してみます。

 

PS. 今回残念だったのは、前日・当日のキャンセル、無断欠席が多かったこと。申込者の半数が会場に来てくれませんでした。・・・残念です。参加したくなる仕掛けも考えてみないといけないですね。

「GR Family 用ライブラリの紹介」LT資料を公開しました (IoT 祭 2016 / 2016年3月12日) #algyan

IoT 祭 2016」(IoT ALGYAN 1周年記念イベント、3月12日(土) 開催) で、

GR Family 用ライブラリの紹介

というテーマで LT 登壇しました。
今回から資料は docs.com で公開しています。これまでの資料は引き続き SlideShare で公開しています。

 

以前からブログでお知らせしていた内容ではあるんですが、改めて LT で紹介しました。
「GitHub で公開してます」だけでは面白くないので、ライブラリを作り始めた経緯とか、ライブラリ利用でどんな風に便利になるのかをお伝えしました。
ぜひ活用して IoT を楽しんでください!

幸い、面白かったと言ってくださる方がいらっしゃって、実は内心薄い内容だな~と思っていたのですが、時間をいただいてよかったです。

懇親会で「DLL ってどうやって使うの?」という質問をいただきました。
このあたりは説明なしでいいのかなと思っていたんですが、やはり使い方とかリファレンスはあるほうがよさそうですね。
用意していきますので、少しだけ長い目で見てください。

 

次の週末 19日(土) の勉強会に参加してくだされば、ライブラリの使い方も紹介できます。ぜひ参加を検討してください。
現在、キャンセル待ちが出ている状態ですが、どうも増席されるんじゃないかな~と。(決めるのは私ですが /笑)

NETMF : 複数の I2C モジュールを接続(三軸加速度センサー ADXL345+キャラクターディスプレイ)

I2C の使用例として、これまで二つ紹介しました。

今回は I2C モジュールを二つ接続してみます。

WP_20160118_10_18_49_Pro

I2C のメリットは、複数のモジュールがあっても信号線 2本+電源の接続で済むこと。
I2C の概要は こちら のエントリーを参照していただければ。


I2CDevice の継承クラス / ADXL345 固有のクラス

.NET Micro Framework の I2CDevice クラスを使いやすくする拡張、および ADXL345 (三軸加速度センサー)は、こちらのコード がそのまま使えます。
特に変更する必要はありません。名前空間が気に入らなければ適当に変更してください。


キャラクターディスプレイのクラス

キャラクターディスプレイクラスは こちらのコード が使える・・・のですが、今回は 8×2行の別のモジュール、AQM0802A-RN-GBW を使ってみました。
理由は、実験用シールドに加速度センサーとキャラクターディスプレイの両方を載せるため。

キャラクターディスプレイは多くがHD44780 互換なのですが、AQM0802A は拡張機能セットを使います。
標準的な機能セットと共通の部分が多いのですが、モジュールの初期化コマンドおよびキャラクター出力コマンドが標準とは異なります。

ということで、以下のコードにします。

public class Aqm0802A : I2CDeviceEx
{
    private bool _displayOn = true;         // ディスプレイをオンにするか
    private bool _cursorOn = false;         // カーソルを表示するかどうか
    private bool _blinkOn = false;          // カーソル位置でブリンクするか

    private readonly int _commandWait = 1;  // コマンド実行後のウェイト

    public Aqm0802A(ushort aqm0802A, int defaultClockRateKhz, int timeout) :
        base(aqm0802A, defaultClockRateKhz, timeout)
    {
        Thread.Sleep(1000);

        // AQM0802A は HD44780 の拡張機能セットを使用する
        // 以下は拡張機能セットでの初期化コマンド
        // 標準機能セットを使用するモジュールについては以下を参照
        //   yseosoft.wordpress.com/2015/12/31/i2c_clcd_demo/ の記事
        //   GrFamilyLibrary のソースコード (github.com/netmf-lib-grfamily/GrFamilyLibrary)
        WriteCommand(0x38);         // 標準機能セットを指定
        WriteCommand(0x39);         // 拡張機能セットを指定
        WriteCommand(0x14);         // 内部オシレーター周波数を指定
        WriteCommand(0x70);         // コントラストを指定(下位4ビット)
        WriteCommand(0x56);         // コントラストを指定 (上位4ビット)
        WriteCommand(0x6c);         // フォロワーコントロール
        WriteCommand(0x38);         // 標準機能セットに戻す
        WriteCommand(0x0c);         // 表示オン

        WriteCommand(0x01);         // 表示クリア
        WriteCommand(0x06);         // カーソルと表示のシフト設定
        WriteCommand(0x0c);         // カーソルとブリンクの表示をオフ

        Thread.Sleep(100);
    }

    public void Print(string msg)
    {
        for (var i = 0; i < msg.Length; i++)
        {
            WriteCharactor((byte)msg[i]);
        }
    }

    // 表示クリア
    public void Clear()
    {
        WriteCommand(0x01, 5);      // Clear Displayはウェイトが必要
    }

    // カーソルを初期位置に戻す
    public void Home()
    {
        WriteCommand(0x02, 5);      // Return Homeはウェイトが必要
    }

    public void DisplayOn(bool displayOn)
    {
        ControlDisplay(displayOn, _cursorOn, _blinkOn);
        _displayOn = displayOn;
    }

    // カーソル表示オン・オフを切り替える
    public void CursorOn(bool cursorOn)
    {
        ControlDisplay(_displayOn, cursorOn, _blinkOn);
        _cursorOn = cursorOn;
    }

    // カーソル位置のブリンクのオン・オフを切り替える
    public void BlinkOn(bool blinkOn)
    {
        ControlDisplay(_displayOn, _cursorOn, blinkOn);
        _blinkOn = blinkOn;
    }

    public void SetCursor(int row, int col)
    {
        var addr = (byte)(((byte)row) << 6) + (byte)col;
        WriteCommand((byte)(0x80 | addr));
    }

    private void ControlDisplay(bool displayOn, bool cursorOn, bool blinkOn)
    {
        var cmd = (byte)0x08;
        if (displayOn)
            cmd |= 0x04;
        if (cursorOn)
            cmd |= 0x02;
        if (blinkOn)
            cmd |= 0x01;

        WriteCommand(cmd, _commandWait);
    }

    public void WriteCharactor(byte data)
    {
        // AQM0802A は拡張機能セットを使うので 0x40
        // 標準機能セットの場合は 0x80
        RegWrite((byte)0x40, data);
    }

    public void WriteCommand(byte cmd, int wait = 1)
    {
        var reg = (byte)0x00;
        RegWrite(reg, cmd);
        Thread.Sleep(wait);
    }
}

アプリケーションのコード例

アプリケーションのコード例は以下の通り。

public class Program
{
    private const ushort Adxl345Address = 0x1d;     // ADXL345のアドレス
    private const ushort Aqm0802AAddress = 0x3e;    // AQM0802A-RN-GBWのアドレス
    private const int DefaultClockRateKhz = 100;    // 転送速度 (KHz)
    private const int Timeout = 1000;               // 送受信ごとのタイムアウト

    public static void Main()
    {
        var prog = new Program();
        prog.Run();
    }

    private void Run()
    {
        var accel = new Adxl345(Adxl345Address, DefaultClockRateKhz, Timeout);
        var lcd = new Aqm0802A(Aqm0802AAddress, DefaultClockRateKhz, Timeout);

        while (true)
        {
            Int16 x;
            Int16 y;
            Int16 z;

            accel.Measure();
            accel.GetXYZ(out x, out y, out z);

            lcd.Clear();
            lcd.Print(x.ToString() + "," + y.ToString());
            lcd.SetCursor(1, 0);
            lcd.Print(z.ToString());

            Thread.Sleep(1000);
        }
    }
}

加速度センサーの使い方、キャラクターディスプレイの使い方が分かれば、(当然ですが)特に不思議なところも難しいところもないですね。


結線

結線は以下の通り。

I2C モジュールは信号線をパーティーライン状に接続するだけです。通信時にモジュールのアドレスが含まれているので(.NET Micro Framework では隠蔽されていますが)、どちらに対しても正しくデータを送受信できます。

WP_20160118_10_17_03_Pro2016-01-18 16-06-59

NETMF : I2C 接続のセンサーモジュール活用例(三軸加速度センサー ADXL345 の場合)

I2C の使用例としてキャラクターディスプレイモジュールについてすでに紹介しました。
キャラクターディスプレイは出力モジュールなので、マイコンボードからのコマンドも出力方向のみ(キャラクターディスプレイからデータを読み打差宇ことはない)でした。

今回は双方向のデータ通信について紹介します。センサーデバイスですね。
センサーデータを要求するコマンドをマイコンボードからモジュールに送信し、センサーデータをマイコンボードで受け取るという通信です。
モジュールによって通信に使う領域(レジスター)は異なりますが、送受信ともに既定の領域を使ってデータをやりとりします。


今回使用するモジュール

センサーモジュールの例として、今回は ADXL345 を使用します。3軸の加速度センサーです。
安価で入手しやすいモジュールです。
PinKit のセンサーボードをお持ちの方は以下のコードがそのまま使えます。
GR-PEACH のみで購入して PinKit のセンサーボードを持っていない方は秋月あたりでモジュールを購入できます。

WP_20150313_006WP_20151103_003

※写真では実験用シールドに ADXL345 を載せていますが、もちろん普通のブレッドボードなどを使ってもかまいません。加速度センサーは持ち上げて傾けるのでブレッドボードが分かれているよりマイコンボードと一体化しているほうがやりやすいというだけの理由です。


ADXL345 固有の情報

ADXL345 を使うにあたって必要な(モジュール固有の情報)をまとめておきます。

I2C アドレスは、私が使った上記のモジュールでは 0x1d です。

レジスタ(通信のための領域)のうち、最低限必要なものは以下です。

  • 0x2d・・・電源管理(センサーデータ取得でも使います)
  • 0x31・・・データフォーマット(加速度の測定範囲を設定)
  • 0x32~0x37・・・x, y, x 方向の加速度データ

I2CDevice の継承クラス

.NET Micro Framework の I2CDevice クラスは少しだけ不便なところがあるので、少し拡張してあげます。
これは I2C キャラクターディスプレイの例で紹介したものと同じです。

using Microsoft.SPOT.Hardware;

namespace AccelTest01
{
    public class I2CDeviceEx
    {
        private readonly I2CDevice _i2C;
        private readonly int _timeout;

        private readonly byte[] _adata = new byte[1];   // アドレス指定用のバイトデータ領域
        private readonly byte[] _rdata = new byte[1];   // データ受信用のバイトデータ領域
        private readonly byte[] _wdata = new byte[2];   // データ送信用のバイトデータ領域

        private I2CDevice.I2CTransaction[] _trRegRead;      // データ受信用のトランザクションデータ
        private I2CDevice.I2CTransaction[] _trRegWrite;     // データ送信用のトランザクションデータ

        public I2CDeviceEx(ushort i2CAddress, int clockRateKhz = 100, int timeout = 1000)
        {
            _i2C = new I2CDevice(new I2CDevice.Configuration(i2CAddress, clockRateKhz));
            _timeout = timeout;

        }

        protected byte RegRead(byte reg)
        {
            _adata[0] = reg;
            _trRegRead = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateWriteTransaction(_adata),
                I2CDevice.CreateReadTransaction(_rdata) };
            _i2C.Execute(_trRegRead, _timeout);
            return _rdata[0];
        }

        protected void RegReads(byte reg, ref byte[] data)
        {
            _adata[0] = reg;
            _trRegRead = new I2CDevice.I2CTransaction[] {
                I2CDevice.CreateWriteTransaction(_adata),
                I2CDevice.CreateReadTransaction(data) };
            _i2C.Execute(_trRegRead, _timeout);
        }

        protected void RegWrite(byte reg, byte val)
        {
            _wdata[0] = reg;
            _wdata[1] = val;
            _trRegWrite = new I2CDevice.I2CTransaction[] { I2CDevice.CreateWriteTransaction(_wdata) };
            _i2C.Execute(_trRegWrite, _timeout);
        }

        protected void RegWriteMask(byte reg, byte val, byte mask)
        {
            var tmp = RegRead(reg);
            _wdata[0] = reg;
            _wdata[1] = (byte)(tmp & ~(int)mask | ((int)val & (int)mask));
            _trRegWrite = new I2CDevice.I2CTransaction[] { I2CDevice.CreateWriteTransaction(_wdata) };
            _i2C.Execute(_trRegWrite, _timeout);
        }
    }
}

 


ADXL345 固有のクラス

ADXL345 固有の機能をクラスにまとめるとこうなります。

アプリからは Measure メソッドを呼び出したあとに GetXYZ メソッドを呼び出すと加速度データが得られます。
なお ADXL345 では測定範囲は設定により変更できますが、今回はサンプルということで 4G に固定しています。
このあたりの変更は GrFamilyLibrary のソースコードを参考にしていただければ。

public class Adxl345 : I2CDeviceEx
{
    private const byte PowerCtl = 0x2d;
    private const byte DataFormat = 0x31;
    private const byte DataX0 = 0x32;

    private byte[] _xyz = new byte[6];

    public Adxl345(ushort adxl345Address, int defaultClockRateKhz, int timeout) :
        base(adxl345Address, defaultClockRateKhz, timeout)
    {
        Thread.Sleep(1000);

        SetRange4G();
        ToWakeup();
    }

    public void Measure()
    {
        RegWriteMask(PowerCtl, 0x08, 0x08);
    }

    public void GetXYZ(out Int16 x, out Int16 y, out Int16 z)
    {
        RegReads(DataX0, ref _xyz);
        x = (Int16)(((UInt16)_xyz[1] << 8) + (UInt16)_xyz[0]);
        y = (Int16)(((UInt16)_xyz[3] << 8) + (UInt16)_xyz[2]);
        z = (Int16)(((UInt16)_xyz[5] << 8) + (UInt16)_xyz[4]);
    }

    private void SetRange4G()
    {
        // 4Gまで測定するには第2引数を 0x01
        // 2G・・・0x00, 4G・・・0x01, 8G・・・0x10
        RegWrite(DataFormat, 0x01);     
    }

    private void ToWakeup()
    {
        RegWriteMask(PowerCtl, 0x00, 0x04);     // 通常モードに入る(スリープモードではない)
    }
}

 


アプリケーションのコード例

ADXL345 を使うアプリケーションのコード例は以下の通り。

1秒間隔で加速度データを読み出しています。

.NET っぽくイベントハンドラーを使いたいなどは、(ここでもやはり)GrFamilyLibrary を参照してください。

public class Program
{
    private const ushort Adxl345Address = 0x1d;     // ADXL345のアドレス
    private const int DefaultClockRateKhz = 100;    // 転送速度 (KHz)
    private const int Timeout = 1000;               // 送受信ごとのタイムアウト

    public static void Main()
    {
        var prog = new Program();
        prog.Run();
    }

    private void Run()
    {
        var accel = new Adxl345(Adxl345Address, DefaultClockRateKhz, Timeout);

        while (true)
        {
            Int16 x;
            Int16 y;
            Int16 z;

            accel.Measure();
            accel.GetXYZ(out x, out y, out z);
            Debug.Print("X = " + x + ", Y = " + y + ", Z = " + z);

            Thread.Sleep(1000);
        }
    }
}

 


念のため、結線について

I2C は本当に結線が簡単ですが、念のため紹介しておくと以下のようにします。
※PinKit のセンサーボードをお持ちの方は、もちろん GR-PEACH に載せるだけ。

2016-01-16-18-23-51WP_20151103_004