« 前ページへ - 次ページへ »
前回ではWindows IoT Coreが用意してくれているSPIをやりとりするAPIを使ったプログラミングを紹介しました。電子パーツのお店で売っているLCDはI2CやSPI規格に則ったものが2,3千円くらいで売られています(表示できる内容や規模にもよります)が、ワゴンに無造作に入れられたような数百円で買える激安LCDは独自のシリアル通信を使っていたりします。今回はそういった信号のための学習として、GPIOだけによるSPI通信を試してみました。

配線図は前回とほとんど同じですが、Raspberry Pi側のピンをすべてSPIに対応していない箇所に移しています。データは書き込みのみで、読み取りは行わないので、この線は省略しています。


まずはどのようにしてSPI通信が行われているかを知る必要があります。MCP23S08のデータシートやウィキペディア英語版によると、CS信号を流していない間に、総ビット分のオン・オフをSCKで持続的におこない、SCKがオン(またはオフ)になるタイミングでSI(SO)に信号があるかないかで、シリアルデータが決定されるようです。

ここでWindows特有の問題が発生します。Windows IoT CoreはUniversal Windows Appベースのため、待機状態にするには精度の低い「await Task.Delay()」しかプログラム命令がない上に、Arduinoでのdelay、Linuxでのusleepのようにミリ秒未満を指定することができません(追記:先日発売されたトランジスタ技術2016年11月号の記事によると、Raspberry Pi自体がマイクロ秒のカウントに対応していないようです)。

こちらのブログによると、マイクロ秒単位での待機には、精度の高いStopwatchクラスのカウンターが一定数に達するまで無限ループでぶん回すという力技しか今のところ方法は無いようです。

以上の点を踏まえたプログラムコードがこちらです。つないだ各種ピンをGPIOとして宣言したうえで、信号を送るときはCSピンをオフにし、入力ピンのスイッチを切り替え、パルス信号を送信する手順を行っています。

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Devices.Gpio;

namespace SpiGpio
{
    public sealed class StartupTask : IBackgroundTask
    {
        private BackgroundTaskDeferral deferral;

        private const int GPIO_CS_PIN = 2;  // External chip select input 
        private const int GPIO_SI_PIN = 3;  // Serial data input
        private const int GPIO_CSK_PIN = 4; // Serial clock input
        private const int GPIO_SO_PIN = 17; // Serial data output
        private GpioPin cskpin, sipin, sopin, cspin;

        //Refer from : http://uepon.hatenadiary.com/entry/2016/08/19/234838
        private Stopwatch sw = new Stopwatch();
        private const long WAIT_SEC = 10;
        private void msDelay(long microSeconds)
        {
            long ticks = microSeconds * Stopwatch.Frequency / 1000000L;
            sw.Restart();
            while (sw.ElapsedTicks < ticks) ;
        }

        private GpioPin OpenPin(int pinno, bool input, bool high = false)
        {
            var pin = GpioController.GetDefault().OpenPin(pinno);
            if (input == false) {
                pin.SetDriveMode(GpioPinDriveMode.Output);
                pin.Write((high == true) ? GpioPinValue.High : GpioPinValue.Low);
            } else {
                pin.SetDriveMode(GpioPinDriveMode.Input);
            }
            return pin;
        }

        private void SendByte(byte bits)
        {
            for (int i = 0; i < 8; i++) {
                var pv = (((bits >> (7 - i)) & 0x1) != 0) ? GpioPinValue.High : GpioPinValue.Low;
                sipin.Write(pv);
                msDelay(WAIT_SEC / 2);
                cskpin.Write(GpioPinValue.High);
                msDelay(WAIT_SEC);
                cskpin.Write(GpioPinValue.Low);
                msDelay(WAIT_SEC / 2);
            }
        }

        private void SendCommand(params byte[] bytes)
        {
            cspin.Write(GpioPinValue.Low);
            msDelay(WAIT_SEC);

            foreach(byte b in bytes) {
                SendByte(b);
            }

            msDelay(WAIT_SEC);
            cspin.Write(GpioPinValue.High);
        }

        private async void Start()
        {
            cskpin = OpenPin(GPIO_CSK_PIN, false);
            sipin = OpenPin(GPIO_SI_PIN, false);
            sopin = OpenPin(GPIO_SO_PIN, true);
            cspin = OpenPin(GPIO_CS_PIN, false, true);

            SendCommand(0x40, 0x00, 0x00);

            Random r = new Random();
            while (true) {
                byte bits = 0x0;
                for(int i = 0; i < 4; i++) {
                    if (r.Next(0, 2) == 1) bits |= (byte)(1 << i);
                }
                SendCommand(0x40, 0x09, bits);

                await Task.Delay(500);
            }
        }

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            deferral = taskInstance.GetDeferral();

            Start();
        }
    }
}

このプログラムで実行される内容は前回のLチカと全く同じなので、実行例は写真を掲載するだけにとどめておきます。

, | 2016年10月7日
前回はI2C方式のIOエキスパンダーのWindows IoT Coreプログラミングを紹介しましたが、今回はSPI方式のIOエキスパンダー(MCP23S08)の使用例を紹介したいと思います。

ブレッドボードによる配線図と、写真によるイメージはこちらの通りです。Raspberry PiのSPI0ピンから出力される信号によって、上半分の右8ピンで入出力を拡張することができます。

 

続いてプログラミング。Windows IoT CoreにはSPI通信のためのAPIも用意されているので、これを使ってみます。このICではGPIO出力は3バイト単位で信号を送信することで操作が行えます。はじめの1バイトは操作コード(書き込みモードなら0x40、読み込みモードなら0x41。いずれもハードウェア操作の信号はなし)、次のバイトはレジスタアドレス(GPIOなら0x09)、最後のバイトはオン・オフのビット配列となります。今回は単純なGPIO操作なので、はじめに「0x40, 0x00, 0x00」の信号を送信することで、すべてのピンを出力モードとして初期化しています。

以上を踏まえたソースコードがこちらになります。今回も同様にバックグラウンドで動作し、4つのLEDがランダムで点灯します。
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Devices.Enumeration;
using Windows.Devices.Spi;

namespace SpiApiTest
{
    public sealed class StartupTask : IBackgroundTask
    {
        private BackgroundTaskDeferral deferral;

        private SpiDevice SPIAccel;

        private byte[] sendbytes = new byte[] { 0x40, 0x09, 0x00 };
        private void SendGpio(byte bits)
        {
            sendbytes[2] = bits;
            SPIAccel.Write(sendbytes);
        }

        private void SendCommand(params byte[] args)
        {
            SPIAccel.Write(args);
        }

        private async void Start()
        {
            try {
                var settings = new SpiConnectionSettings(0);
                settings.ClockFrequency = 5000000;
                settings.Mode = SpiMode.Mode0;

                string aqs = SpiDevice.GetDeviceSelector("SPI0");
                var dis = await DeviceInformation.FindAllAsync(aqs);
                SPIAccel = await SpiDevice.FromIdAsync(dis[0].Id, settings);
                if (SPIAccel == null) {
                    Debug.WriteLine(string.Format(
                        "SPI Controller {0} is currently in use by " +
                        "another application. Please ensure that no other applications are using SPI.",
                        dis[0].Id));
                    return;
                }

                SendCommand(0x40, 0x00, 0x00);

                Random r = new Random();
                while (true) {
                    byte bits = 0x0;
                    for (int i = 0; i < 4; i++) {
                        if (r.Next(0, 2) == 1) bits |= (byte)(1 << i);
                    }
                    SendGpio(bits);

                    await Task.Delay(500);
                }
            } catch (Exception ex) {
                Debug.WriteLine("SPI Initialization failed. Exception: " + ex.Message);
            }
        }

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            deferral = taskInstance.GetDeferral();

            Start();
        }
    }
}
, | 2016年10月6日
Raspberry PiやArduinoでLEDドットマトリクスなどを使うと、あっという間にGPIOピンを使い尽くしてしまい、複数の機器をどうすれば同時に動作させられるのかと思うのが電子工作の初心者あるある。今回はRaspberry Pi 2とWindows 10 IoT CoreによるGPIOを増やす方法を紹介します。

用意するのはIOエクステンダーとよばれる200円ほどのIC。これとWindowsのAPIによってプログラミングすることで、4ピン(うち2ピンは電源とGND)だけでより多くのGPIOを用意することができます。エクステンダーは通信方法で大きく分けるとSPIとI2Cがありますが、今回はI2Cを採用している「MCP23017」を使いました。

このチップでは切りかけのある左側上下の16ピンでデータの入出力ができます。上側(GPA)と下側(GPB)ではプログラミングの方法が若干異なってくるので、それを交えた解説をしていきます。

まずは配線図。


写真だとこのような感じになります。

続いてプログラミング。Hackster.ioにあった投稿をベースにしていますが、手を加えているので、独自にカスタマイズした点だけを簡単に記述します。
  1. GPBへの出力を有効にするにはあらかじめ[0x01, 0x00]の2バイトを書き込みます。
  2. GPBバスの番号は0x13です。
  3. GPAとGPBのポート番号は上下で逆(GPAは左から7~0、GPBは左から0~7)になっているので、誤って同じ値を両方に適用しないようにしましょう。

以上を踏まえたソースコードがこちらになります。バックグラウンドで動作し、4つのLEDがランダムで点灯します。
using System;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Devices.Enumeration;
using Windows.Devices.I2c;

namespace I2CApiTest
{
    public sealed class StartupTask : IBackgroundTask
    {
        private BackgroundTaskDeferral deferral;

        private const byte PORT_EXPANDER_I2C_ADDRESS = 0x20;

        private const byte IODIR_A_REGISTER = 0x00;
        private const byte MCP23017_BUS_A = 0x12;

        private const byte IODIR_B_REGISTER = 0x01;
        private const byte MCP23017_BUS_B = 0x13;

        private I2cDevice mcp23017;

        private async void Start()
        {
            var settings = new I2cConnectionSettings(PORT_EXPANDER_I2C_ADDRESS);
            var ds = I2cDevice.GetDeviceSelector("I2C1");
            var dis = await DeviceInformation.FindAllAsync(ds);
            mcp23017 = await I2cDevice.FromIdAsync(dis[0].Id, settings);

            try {
                mcp23017.Write(new byte[] { IODIR_A_REGISTER, 0x00 });
                mcp23017.Write(new byte[] { IODIR_B_REGISTER, 0x00 });

                var r = new Random();
                var wbuf = new byte[2];
                var m = new int[2,2]{{7, 6}, {0, 1}};

                while (true) {
                    for (int i = 0; i < 2; i++) {
                        wbuf[0] = (i == 0) ? MCP23017_BUS_A : MCP23017_BUS_B;
                        wbuf[1] = 0x0;
                        for (int j = 0; j < 2; j++) {
                            if(r.Next(0, 2) == 1) wbuf[1] |= (byte)(1 << m[i,j]);
                        }
                        mcp23017.Write(wbuf);
                    }

                    await Task.Delay(500);
                }
            } catch (Exception e) {
                System.Diagnostics.Debug.WriteLine("Exception: " + e.Message);
            }
        }

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            deferral = taskInstance.GetDeferral();
            Start();
        }
    }
}
, | 2016年10月5日



2016年10月2日
マウスカーソルのすぐそばでIMEが有効になっているかの状態を一目で確認できるユーティリティ「IMEステータス」のVer 2.12の正式版を公開しました。正式版ではWindows 10 Anniversary Updateに対応したのに加え、タスクバーでのアイコンの表示色やクリックメニューなどの、インターフェイスの修正が加えられています。

また、これまでベクターで公開していたバージョンは広告が表示されていましたが、Ver 2.12では試験的に広告を撤去する代わりに機能を制限する無料版という手法を取り入れています。ただし、アプリの反響次第で今後広告が復活する可能性もございますのでご了承ください。

 | 2016年9月30日
Raspberry Pi 2とWindows 10 IoT coreによる電子工作に挑戦しようとしているのですが、なかなか思うように行きません。まずひっかかったのは何もアプリを導入していないにもかかわらず、本体が再起動を繰り返すトラブル。調べてみたところ、主な原因としてSDカードとの相性に問題(200円で買ったワゴンのSDカードを使っていた)があるとのことでした。有志によって作成された互換性一覧によると、サンディスクやサムスンでさえも外れがあるみたいなので、結果、東芝製のカード(EXCERIA M301[輸入品])を買い直すことにしました。

ではここからが本題。Windows 10 IoT Coreによる開発は日本語による資料がほとんどないため、まずは基礎固めとして、ホビープログラミング入門という日経ソフトウェアのムックで紹介されていたRaspbian & Pythonによるスイッチプログラムの移植にチャレンジしてみました。

Windows 10 iot coreの導入方法は探せばすぐに見つかるので、ここでは割愛。まずは、スイッチと抵抗をブレッドボード経由で配線します。ブレッドボード中央の青い線の上に1KΩの抵抗がささっている点に気をつけてください。


続いてVisual Studio 2015のセットアップです。標準ではGUIのあるアプリしか作れませんが、こちらのページよりテンプレートを導入することで、GUIのないバックグラウンドアプリを作成できるようになります。インストールが終わると、Visual Studio 2015の新しいプロジェクトに「Background Application(IoT)」が追加されていると思います。


それではプログラムを組んでみましょう。バックグラウンドアプリはRunメソッドから呼び出されます。アプリを半永久的に起動させ続けるには、ここでGetDeferral()を呼び出す必要があります。今回はGPIO4に電気が入って来るかどうかの回路なので、4番ピンを入力モードにしています。あとはタイマーを起動させ、入力値が変更されたらVisual Studioのデバッグ出力に結果を表示させます。

// StartupTask.cs
using System;
using System.Diagnostics;
using Windows.System.Threading;
using Windows.ApplicationModel.Background;
using Windows.Devices.Gpio;

namespace Switch
{
    public sealed class StartupTask : IBackgroundTask
    {
        private BackgroundTaskDeferral deferral;

        private const int GPIO_PIN = 4;
        private GpioPin pin;

        private ThreadPoolTimer timer;
        private GpioPinValue gpv = GpioPinValue.Low;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // これがないとRunメソッドが終わるとアプリが終了してしまう
            // また、deferral.Complete(); で明示的に終了させることができる
            deferral = taskInstance.GetDeferral();

            // 4番ピンの入力を有効にする
            pin = GpioController.GetDefault().OpenPin(GPIO_PIN);
            pin.SetDriveMode(GpioPinDriveMode.Input);
            gpv = pin.Read();

            // 500msごとに判定する
            timer = ThreadPoolTimer.CreatePeriodicTimer(OnTickTimer, TimeSpan.FromMilliseconds(500));
        }

        private void OnTickTimer(ThreadPoolTimer timer)
        {
            var v = pin.Read();
            if (gpv != v) {
                Debug.WriteLine(v.ToString());
                gpv = v;
            }
        }
    }
}


続いてデバッガの設定です。対象のアーキテクチャを「ARM」にし、ターゲットは「リモートコンピューター」に。C#プロジェクトのプロパティの「Debug」に、対象のRaspberry Piが接続されているIPアドレスを入力します。アドレスは「Windows 10 IoT Core Dashboard」の「自分のデバイス」より確認できます。


初回起動時は追加コンポーネントなどの導入のため、やや時間がかかりますが、デバッガが起動すると、ブレッドボードのスイッチを押したり離したりするたびに、「出力」ウィンドウに結果が表示されます。


ちなみに、スイッチを押しているときはGNDピンへと電気が通じてGPIO4ピンには流れないため、GPIO4の結果は「Low」となり、離すとGPIO4に電気が流れるようになるため、結果が「High」となります。
, | 2016年9月21日
Googleが公開しているAndroidのソースコードをベースにIntel系の端末で汎用的な動作を試みるプロジェクト「Android-x86」。Android 6.0の正式版が先日公開され、最新版では特別な手順を踏まずとも、ちょい古タブレットに用いられているBayTrail世代の32bit UEFIシステムにもインストールできるようになりました。とはいうものの、USBにLinuxブートシステムを導入したり、ブートメニューにWindowsが出てこなくなったりと、一般の人がおいそれと導入することはできない難しさがあります。

管理人も試行錯誤した結果、インストール補助ツール「Android-x86 Installer UEFI Version」のソースコードをカスタマイズすることで、Windows 10とAndroid 6.0デュアルブートができるようになりました。音声が出ないなどのハードウェアの問題は残っているものの、4.4をはじめとするこれまでのバージョンはASUS VivoTab Note 8(M80TA)では全く動かなかったので、動作していること自体が感動的ですらありました。


導入するにはAndroid_UEFIInstaller.exeを実行して、Android Imageには「android-x86-6.0-r1.iso」を、Target Driveにはあらかじめ空けておいたハードディスクのパーティションのドライブを指定します。あとは「Install」ボタンを押すと、インストールが開始されます。Androidを起動するには、BIOSから直接Android OSをブートするか、Windowsの「すべての設定→更新とセキュリティ→回復→今すぐ再起動する」を選択し、その後に表示される一覧より「デバイスの使用→Android OS」を選択します。


カスタマイズされたインストーラーはこちらのリンク先にて、修正されたソースコードを同梱した上で公開しております。修正の要望はオリジナルのプロジェクトにリクエスト済みのため、本家が対応するようになったら公開は終了する予定です。

環境によってはVisualC++ 2015ランタイムが必要になることがありますのでご注意ください。また、インストールによって生じたトラブルに関しては一切責任を負いません。サポートもできませんので、Android自体の不具合などはプロジェクトのフォーラムでお問い合わせください。
 | 2016年9月20日
TNKソフトウェアのサーバーは今までロリポップのサービスを使用していたのですが、パスワード記入欄があるとエラー扱いにするなど、年々ブラウザのhttpによる無暗号通信に対する厳しさが増していく中、未だに独自SSLがオプションである上に高額なので、契約が切れたのを機にバリューサーバーに乗り換えました。

最近はドメイン認証という最低限の信頼性を得たいだけであれば、無料で取得できる時代になりました。ここでは、TNKソフトウェアがhttpsドメインになるまでの手順を簡単に紹介したいと思います。

  1. サブドメインを設定する
    SSLはサブドメイン単位で有効になります。例えば、この設定だと、「tnksoft.com」と「www.tnksoft.com」はhttpsですが、「sh.tnksoft.com」はhttp通信になります。

  2. CSRを作成する
    SSLにおける証明書を発行する認証局に提出するCSRはバリューサーバーで作成します。これはバリューサーバーのヘルプページの1~4が詳しいのでそちらをご覧ください。プライベートキーはこのあと使うので覚えておくように。

  3. StartComから受け取れるメールアドレスを作成する
    「Let's Encrypt」は無料で証明書を発行しくれることで有名ですが、3ヶ月ごとでの更新が必要であることや、Linuxの知識も多少いるなど、サーバー構築になれてない人には難易度が高いので、私はStartComのサービスを使うことにしました。このサービスではドメイン認証に決められたアドレスしか使えないため、あらかじめ「postmaster@」「hostmaster@」「webmaster@」のいずれかのメールアドレスを開設し、受け取れる状態にしておきます。

  4. StartSslにアクセスする
    右上の「Sign-up」よりユーザー登録を行ったら、拡張子.p12のログイン証明書が発行されるので、これをダブルクリックしてパソコンに導入します。StartComに次回以降ログインするときは、この証明書の有無でチェックされるのですが、私の環境ではGoogle ChromeよりもMicrosoft Edgeの方がスムーズにログインできました。

  5. ドメインの証明をする
    ログインしたらコントロールパネルより「Validations Wizard」をクリックし、選択肢から一番上にある「Domain Validation」にチェックが入ったままで、「Continue」をクリック。続けてドメイン名(サブドメインは含まず)を入力します。指定したメールアドレスに届いたコードを「Verification code」に入力すれば認証は完了です。
     

  6. 署名の発行を申請する
    「Certificates Wizard」より「Web Server SSL/TLS Certificate」を選び、次のページに進みます。このページでhttpsを有効にしたいサブドメインを一行単位で入力し、CSRの欄にはバリューサーバーで作成した「-----BEGIN CERTIFICATE REQUEST-----」で始まるCSRテキストを入力します。

    リクエストに成功すると、「Issued」として、「Tool Box→Certificate List」より証明書がダウンロードできるようになります。ちなみに、申請は1日に3回までしか発行してくれないので、この点に注意しましょう。

  7. 中間証明書をダウンロードする
    バリューサーバーはApacheで稼働しているので、証明書はApacheServer.zipに含まれているものを利用することになります。ただし、ここに含まれる「1_root_bundle.crt」を使ってしまうと「この署名は安全性が低い」とブラウザで警告が出てしまうので、https://www.startssl.com/root/の「Intermediate CA Certificates」より、より強い暗号を用いた「StartCom Class 1 DV Server CA(pem)」をダウンロードし、代わりに使用します。

  8. 証明書のテキストを記入する
    最後はヘルプページの6~に従い、取得した各種証明書のテキストデータを入力します。「発行された証明書」にはStartSslから入手した「2_***.crt」内のテキストを、「発行された中間証明書」には「sca.server1.crt」内のテキストを入力します。これでインストールが完了すれば、しばらく後に対象のドメインが自動でhttpsになっているはずです。
2016年9月12日
ウェブページのフィルタリングをおこなうブラウザ拡張「マイリーディングモード」を公開しました。「不要なものを後で消す」広告ブロッカーとは違い、「必要なものだけを最初に残す」プログラム手法により、あなたが頻繁に訪れるサイトにおいて、本当に読みたい情報だけを、スタイルシートなどのオリジナルページの雰囲気を残したまま、素早く表示させることができるようになります。


現在、Google ChromeとFirefox版はそれぞれのブラウザの拡張機能より直接導入することができます。Microsoft Edge版もございますが、現時点ではマイクロソフトがストアアプリへの登録をまだ受け付けていないため、テスト版という体でソースコードとして拡張機能を提供しています。そのため、Microsoft Edgeでは開発者モードにする手順が必要となりますのでご注意ください。
2016年9月7日
ウィンドウズでのハードディスクの方法は主にFAT32とNTFSがあります。FAT32はUSBメモリーなど、いきなりポートから引っこ抜いてもデータが壊れることはあまりなく、SDカードのフォーマットにもっぱら使われますが、1ファイルの上限が4GB、フォーマットサイズの上限が32GBと高画質の映像を記録するのには不向きです。一方でNTFSはファイルの上限はほぼない(約20エクサバイト)ものの、少し前のMac OSでは読み込みしかできなかったり、急にメディアを切るとデータが破損したりと、あまりリムーバブルメディア向きではありません。

そこでNTFSのようにファイルサイズの制限を拡張子、FAT32のデータ保全性のいいとこ取りをしたのがexFATというわけですが、ハードディスクをリムーバブルメディアとして利用する際には気をつけなければいけない点があります。それは、ウィンドウズで特に意識せずそのままフォーマットすると、アロケーションユニットサイズが256キロバイトになることです。

これはデータの最小確保単位を指し、256KB未満のファイルでも、ディスク内では256KB確保されることになります。つまり、数KBのテキストファイルばかりのデータをこのディスクに保存しようとすると、あっというまにディスクの容量の上限に達してしまうのです。以下の例では本来のファイル総サイズの5倍近くの容量を消費しています。


アロケーションユニットサイズを少なくすれば、ディスクのアクセス効率は若干低下しますが、容量の問題は避けられます。しかしながら、Windows 10のフォーマットダイアログでは1TBあるようなメディアでは64KB未満が指定できません(規定は128KB)。もし、アロケーションサイズを少なくしたいのであれば、コマンドラインを使いましょう。
format H: /FS:exFAT /A:4096 /Q

H:はフォーマットするドライブ名、/FSはフォーマット、/Aはアロケーションサイズ(この場合は4096バイト=4KB)、/Qはクイックフォーマットを示します。これにより、細かいファイルをたくさん保存するのに適したハードディスクを作成することができるようになります。

exFATの小技を学んだのであれば、早速大容量の2.5インチHDDをバックアップメディア代わりに買いませんか?
2016年9月6日
« 前ページへ - 次ページへ »