レビューメディア「ジグソー」

Intel Edisonデュアルプロセッサの限界を探る

Edisonは切手サイズの上になんと!ATOM x Quarkのデュアルプロセッサを搭載する極小PCだ。受注生産の放射線センサとSeeedのGroveキットが来る前に、ATOMベンチとQuarkのマイクロセカンドLチカをやってみた。EdisonのATOM Z3400シリーズCPUはコア当たりの性能がCore i7の17分の1、最速Xeonの24分の1。Quarkもおもしろい。

 

さて、EdisonはふつうにLinuxが走り、WiFiとBTがつながり、そのままIoTsすなわちInternet of Thingsの核になる。って言われても電子工作の素人には何のことやら?レビューするにあたってEdisonらしさって何だろうって考えたんだけど、つまるところArduinoに無くてEdisonが持ってるものって・・・?

 

電子工作もプログラミングも素人だけどPCヲタの一人(なにそれ?)としては、やっぱりそこら辺のCortexボードと違うんだから、消費電力ATOMの10分の1、そして”リアルタイムOS”が走るQuarkを使わなきゃEdisonの意味ないでしょ、と言いたい。Arduinoスケッチを使ってというレビューの趣旨からするとなんだけど、まだArduino IDEとかインスコすらしてない時点で言うのもなんだけど、絶対Quarkが面白い。しかも情報がほとんどない!!

 

(追記9/15)OSXでMCU SDKが動かない問題を解決したかも。展開したフォルダのsrcの中にあるmcu_fw.zipをscrの中に展開したらMCU > New MCU Projectを実行できるようになった(Intelに問い合わせ中)。なんとなく原因を彷彿とさせるのが、一旦通ると、展開したmcu_fwフォルダを削除しても大丈夫なこと。MCU pluginのバグだと思う。

 

(追記9/16) OSXで動くようになったら、今度はWindowsでUSB RNDISドライバが動かなくなった。J16でUSBテザリングに必要なドライバで、SSHが通らないからアプリのDownloadが出来ない。あぁ、もう・・・orz。良く分からないが、J16につなぐミニUSBケーブルは品がいいものを使った方が安心かも。

 

(追記9/18)MCU SDKを使ってQuarkのGPIO速度を計測したところ、8.8μ秒、約113 MHzという結果になった(セクション3.6)。すべてのピンについて調査した結果も追記。

 

(追記10/2) ポケットガイガーと、あちゃんでいいのでシリアルLEDの動作確認がとれた。まだまだ続くよ・・・

 

(追記10/13) LEDを制御するための加速度センサの試験に成功。長かった orz

 

(追記10/17) IoT Analyticsクラウド解析のセットアップ、やっと出来たあ

 

 

■ ■ ■ も く じ ■ ■ ■ ■ 

 

A.実践編

 

1.初期設定から最短WiFi・SSH接続まで

2.ATOMベンチマーク

3.Quarkマイコン制御

4.Grove Starter Kit Plus - Intel IoT Editionを使ったスケッチの練習

5.ポケットガイガーを使った放射線測定とクラウド解析

6.ArduinoをつないでシリアルLEDを光らせる

 

B.資料編

 

1.略語・用語の一覧と心の準備

2.Arduino互換性に関する見解

3.Edison開発環境の設定

4.Edisonのハードウェア

5.WindowsのRNDISドライバ障害からの復帰

 

■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 

 

 

 

A.実践編

 

1.初期設定から最短WiFi・SSH接続まで


 

はじめに一言:いろいろなやり方があるけど、基本的にWindowsでやるのが地雷が少ないと思う。また設定ツールを使うんじゃなくて一つづつ確認しながらインストールして行った方が、最終的には安心出来ると思う。IntelのDeveloper Zoneの説明は比較的分かりやすいけど、ハードウェアマニュアルにはArduino互換ボードのピンの配置の説明すら無い。orz   サードパーティーのまとめサイトの方が参考になる。WindowsとOSXで1台のEdisonをいじるのは良くないかも知れない・・・反省(セクションB5)。

初期設定の流れ。上から順番に、ひとつづつ確認しながら(心して望まないと、至る所に地雷が)。J3のシリアルコンソールだけはWindowsのFTDIドライバさえ気をつければトラブルが少ないように思う。ずっとつなぎっぱなしで良い。SSHとWiFiの接続まで安全にたどり着けば、開発環境の設定は楽勝。

 

※最もEdisonらしいとも言えるクラウドツール関連は、タカキさんちばとどさんのレビューを参照

 

1.1 EdisonをArduino拡張基盤に貼り付ける。コツは手前のヒロセソケットの真上とArduino基盤の裏側を2本の指でそっとはさんで、パチンとはまるまで押さえる。このソケットの抜き差し耐性は30回までらしい。

 

1.2 PC側はWindowsが安定している。OSXは動かないツールがあったりEdisonをFAT32でフォーマットし直す必要があったり不便。Intel Developer ZoneからYocto complete image(Linuxイメージのzipファイル)をダウンロードし、適当なフォルダに展開する。

 

 

1.3 WindowsではUSBドライバのインストールが必須なので、ここからダウンロードして実行。以下のドライバを含む。

    •    Composite Device Class (CDC) for programming the board via the Arduino* IDE
    •    Remote Network Driver Interface Spec (RNDIS) for Ethernet over USB
    •    Device Firmware Upgrade (DFU) for updating firmware on devices

 

1.4 12V/1.5A DC電源をJ1に挿すとLinuxが立ち上がる。SW1を左に設定し、J16のマイクロUSB端子にPCを接続するとEdisonがマスストレージとして認識される(ドライブE:など)。何かファイルがあれば削除し、上で展開したファイルをドラッグ&ドロップする。

※J16の説明が間違っていたので訂正しました(9/16)

 

EdisonはSW1を左にするとデバイスモード、右にするとホストモードになる(ハードウェアマニュアル)。J16はType A(ホスト)とType B(デバイス)の両方のタイプのマイクロUSBコネクタを挿すことが出来るOTG(On-the-Go)なので、PCをホスト、Edisonをデバイスとして接続する時はSW1を左にしてType Bコネクタを使う。EdisonをホストとしてType Aコネクタを使ってJ16に周辺機器をつなぐ時は、SW1は右になる。J6は常にデバイスモードになると思う。

 

1.5 J3のシリアル端子とPCを接続し、WindowsのデバイスマネージャでCOMポート番号を確認する。PuTTYをダウンロードし(こちらから)、適当なフォルダに展開する。インストールする必要はない。PuTTYを立ち上げ、シリアルモードで先に確認したCOMポートに接続する。rootで初回はパスワードなしでログインする。

 

1.6 J16をつないだままrebootする。

 

$ reboot

 

1.7 立ち上がってきたら何かキーを押してスタンドバイモードに入る。ここでrun do_otaを実行する。この方法だと、reboot otaコマンドでは完全に書き換えられない場合や、rootでログイン出来ない状況でもリカバリが可能(MATSUP'S BLOG)。 =>追記:WindowsでPhoneFlashLiteするのが安全(セクションB5)。

 

boot> run do_ota

 

1.8 Linuxのイメージが書き換えられてシステムが再起動するので、rootで再度ログインする。バージョンチェックは、

$ configure_edison --version

$ cat /etc/version

$ uname -a

 

1.9 EdisonをWiFi接続する前に、DHCPによる自動アドレシングを避けて自分のルータ環境に合ったアドレス(wlan0)を指定するために、/etc/wpa_supplicant/wpa_cli-actions.shのコピーをバックアップしてから以下のように編集する(IT Media PC USER)。

 

$ cp /etc/wpa_supplicant/wpa_cli-actions.sh /etc/wpa_supplicant/wpa_cli-actions.bak

$ vi /etc/wpa_supplicant/wpa_cli-actions.sh

 

if [ "$CMD" = "CONNECTED" ]; then
    kill_daemon udhcpc /var/run/udhcpc-$IFNAME.pid
    udhcpc -i $IFNAME -p /var/run/udhcpc-$IFNAME.pid -S
fi

 

これを次のように変更する。

 

if [ "$CMD" = "CONNECTED" ]; then
    kill_daemon udhcpc /var/run/udhcpc-$IFNAME.pid
#    udhcpc -i $IFNAME -p /var/run/udhcpc-$IFNAME.pid -S

ifconfig $IFNAME 192.168.1.15 netmask 255.255.255.0
route add default gw 192.168.1.1
fi

 

1.10 configure edison --wifiでルータに接続する。ネットワークアドレスの確認や再起動などは

$ ifconfig

$ ifconfig usb0 down

$ ifconfig wlan0 down

$ ifconfig usb0 up

$ ifconfig wlan0 up

 

WiFiがつながると、PCのブラウザからhttp://edison.localで見れるようになる。

 

1.11 最後にssh2接続。EdisonのJ16にUSBケーブルで接続するとEdison側のUSBアドレスは/etc/network/interfaceファイルで192.168.2.15に自動設定される。ホストのPCのネットワーク設定に新しい接続が表示されるので、IPアドレスを同じドメインの192.168.2.1に、マスクを255.255.255.0に手動設定する。WindowsではPuTTYのSSHで192.168.2.15に接続出来るようになる。Macでは、ターミナルウィンドウから

$ ssh root@192.168.2.15

を打つ。これで、J16ケーブル1本でEdisonに給電しPCからアクセスすることも出来る。MCU SDK(セクションA3)ではsshを介してスケッチをQuarkにDownloadしている。OSXだとターミナルウィンドウからscpコマンドでファイルを転送することもできる。

$ scp <filename> root@192.168.2.15:~/

 

 

2.ATOMベンチマーク


 

sysbenchをUSBフラッシュドライブにコピーしてEdisonにインスコする話。

 

2.1 sysbenchのソースzipファイルをダウンロードし(こちらから)、USBフラッシュメモリにコピーする。WiFiがつながってる環境ならwgetでいいかも。

 

2.2 EdisonのSW1を右にして、J6のUSB端子にフラッシュメモリを刺す。J3のシリアルコンソールは接続したまま。以下のコマンドでUSBドライブをマウントする。

 

$ fdisk -l /dev/sda(デバイスの割り当て一覧を表示)

$ mkdir /mnt/usb

$ mount /dev/sda1 /mnt/usb(今回はsda1に割り当てられていた)

 

因みに、Windows側からマスストレージとして見えているFATパーティションにコピーして、これをEdison側からマウントする手もある(OSXではうまく行かない)。Intel Community

 

$ rmmod g_multi

$ mkdir /mnt/update

$ losetup -o 8192 /dev/loop0 /dev/disk/by-partlabel/update

$ mount /dev/loop0 /mnt/update

 

元に戻すには、

 

$ cd /

$ unmount /mnt/update

$ modprobe g_multi

 

J16のUSBケーブルを一度抜いてから差し直し。

 

2.3 続いてsysbenchをunzipし、Edison上でコンパイルする。

 

$ unzip sysbench-0.5.zip

$ cd sysbench-0.5

$ chmod u+x autogen.sh

$ ./autogen.sh

$ ./configure --without-mysql

$ make

 

2.4 ではいよいよベンチマーク。Mid 2011のMacBook Air(Sandy Bridge Core i7)と、 最速Xeon E5-2678W x 2台が走るDellサーバでも同じ様にベンチしてみた。EdisonのATOMはZ3400シリーズで2コア、2スレッド。1スレッドでの動作とスレッド全部を使った時の速度を比較。

 

$ cd sysbench

$ ./sysbench -–test=cpu --num-threads=1 run

名前の(数字)はスレッドの数、横軸は秒の対数目盛でもちろん小さい方が速い。具体的な数値では、シングルスレッド当たりEdison: 225.71 sec, MacBook Core i7: 12.76 sec, Dell Xeon E5-2678W: 9.27 secとなった。最速Xeonと比べて24倍の差を大きいと見るか小さいと見るか。もちろん全コアを回したら250倍になるんだけど。Linuxとしてはふつうに動く。

 

3.Quarkマイコン制御


 

EdisonはATOM (Host CPU)の他にリアルタイム制御のためにQuarkというx86系の32ビットマイクロプロセッサ(MCU)を搭載している。QuarkはArduinoのARM系ATmega328に相当する外部制御機構だけど、ATmega328は8ビットのRISCでQuarkとの互換性は全く無い。Quarkは100MHzで動作するためATmega328より高性能とされるが、現在はまだAPIが不十分で、Arduinoでしか動かない時間制約の厳しい周辺機器も多い。

 

Quarkへのアクセスは5月のファームウェアアップデートで可能になった。QuarkはLinuxではなく"Viper"というRTOS(リアルタイムOS)で動作している。Linux側からコントロールされ、直接ユーザがQuarkを操作することは出来なくて、開発ソフトの上でのみアプリをダウンロード出来るようになっている。

 

3.1 Quarkアプリを開発するためのEclipseベースのアプリIntel MCU SDKをインストールする(ここから)。

 

3.2 MCU SDKを立ち上げる。Quarkアプリは、メニューのMCU > New MCU Projectから作成する。Quark版のLチカはこんな感じ。Arduino互換ボード上のLED DS2がGPIO 13につながっているので、これを使う。ArduinoのDIG番号とEdisonのGPIO番号はぜんぜん違うので、対応表を見て確認する必要がある。MCUアプリの中ではEdisonのGPIOアドレスを使う。

 

#include "mcu_api.h"
#include "mcu_errno.h"

void mcu_main()
{
    gpio_setup(40, 1);                           /* GPIO 40 connects to DIG 13 and DS2 */
    while (1)
    {
            gpio_write(40, 1);
            mcu_delay(1000);                   /* delay for 1000 microsec */
            gpio_write(40, 0);
            mcu_sleep(100);                     /* sleep for ticks in 10 ms */
    }
}

 

MCU > Build Projectでビルドし、続いてMCU > DownloadでアプリをQuarkにコピーする。Edisonが自動的に再起動される。

 

3.3 EdisonのGPIOピンはマルチプレキシングと言って複数の機能を割り当てることが出来る(セクションB.4.3)。GPIOを使う前に、どのような機能をアサインするか設定してやる必要がある。そのためのシェルスクリプトが用意されている(セクションB.4.4)。

 

$ sh init_Dig.sh -o 13 -d output

 

これは、Arduino互換ボードのピン13を出力に割り当てるという意味。Arduinoのピン13がEdison内部のGPIO 40に相当する。ピン13はボード上のLED DS2につながっているので、これをLチカさせることが出来る。結構・・地雷だらけだったので、うれしくて涙でたよ・・ヽ(^o^)丿

 

 

 

3.4 MCU SDKには時間制御関数として、sleep()とdelay()がある。sleepは10ミリ秒単位で、delayは1マイクロ秒単位でプロセスを止めることが出来る。ここで使ったtime_us()関数は、Edisonが立ち上がってからの経過時間が保存された専用レジストリの値をマイクロ秒(ミリ秒の1000分の1)単位で読み出す。1000マイクロ秒は1ミリ秒で、上のスケッチだと1秒毎に1ミリ秒LEDを点滅させることになる。もちろんもっと短く設定することも出来るけど、そうするとPWM(パルス幅変調)そのものになって光らなくなるんだよ。スゲ。Quarkの動作クロック100MHzは、100,000,000/秒なので、1サイクル=10ナノ秒に相当する。マイクロ秒に対して100倍速いため、十分な精度があると予想される。また、データ出力もgpio.write()ではなくmraaライブラリのmraa_gpio_write()で直接メモリに書き込んだ方が安定するだろうと思う。簡易オシロでも作って検証してみたいな(って言うか、誰かやってくらさい)。しかし、Intel CommunityではQuark(のAPI)に否定的な意見が根強い。

 

3.5 MCU SDKはOSXでは走らない。NullPointerExceptionエラーを吐いて怒られる。原因ははっきりしない。EdisonとMacがJ16でSSH接続されててもダメ。=>解決。ただ原因は不明。

 

3.6 MCUのGPIO出力速度を計測した。テストスケッチは、

#include "mcu_api.h"
#include "mcu_errno.h"
void mcu_main() {
    unsigned long start;
    unsigned long stop;
    char buf[21];
    int len;
    int i;
    gpio_setup(40, 1);
    uart_setup(2, 115200);
    while (1) {
        start = time_us();
        for (i = 0; i < 100000; i++) {
            gpio_write(40, 1);
            gpio_write(40, 0);
            gpio_write(40, 1);
            gpio_write(40, 0);
            gpio_write(40, 1);
            gpio_write(40, 0);
            gpio_write(40, 1);
            gpio_write(40, 0);
        }
        stop = time_us();
        len = mcu_snprintf(buf, 21, "%d us\n", (int) (stop - start));
        uart_write(2, (unsigned char*) buf, len);
    }
}

mcu_delay関数も入れずにオン・オフを書き込んでいる。前後のシステム時間を呼び出して引き算をしたものをシリアルコンソールに出力する。結果は70.69μs/cycle、即ち1ビット当たりGPIOピンに出力するだけで8.8μ秒掛かってしまう。約113 KHz。DMX512の1ビットは4μsだから、このGPIO関数では無理だ。Galileoのように直接GPIOレジストリに書き込むfastGpioDitigalWriteDestructive関数が欲しい。これはIntelがAPIを作る意志があるかどうかだ。

 

(10/13 IntelのPedroさんから回答:EdisonのQuarkはGalileoのそれとは違ってAPIを実装するのに必要な機能に削られた(streamlined)仕様になっていて、fastGpioDigitalWriteDestructiveがMPUに新たに実装される予定は無い)

 

Developer Zoneに投げてたGPIO速度に関する質問に回答があった。MCU Digital Pin Toggle On/Off Speed 何とピンによって速度が全然違う。早速、スケッチでArduino互換ボードのすべてのピンの出力速度を測定してみた(1と0の2つのwrite操作に掛かる時間を2で割った値)。

※Intelの資料はGPIOの一部しか調べていなかったので、Arduino互換ボードすべてのピンを調査した。Quarkは100MHz動作なので1クロック10ナノ秒であるが、これは最下段の1インストラクションループとブランクループとの差分から確認できる。

 

 

 

4.Grove Starter Kit Plus - Intel IoT Editionを使ったスケッチの練習(香港Seeedから来る予定)

 

 

5.ポケットガイガーを使った放射線測定とクラウド解析

Radiation Watchは石巻市のメーカーで、比較的安価なDIY放射線センサを販売している。いのししに線量計をくっつけて森林の放射線を位置情報と一緒にクラウドにアップするとか、ワイルドすぐるプロジェクトをやってたりする。とても面白い。

 

震災と原発事故の直後、ロシア産とかあやしげなガイガーミューラー管が出回ってた時期があったが買わなかった。最近偶然RADIATION WATCHを見つけて、安いのと自分で測定条件をいろいろ試せそうなのでやってみたいと思っていたところ、これまた偶然Edisonを使わせて頂く事になって渡りに船となった。

 

5.1 電子工作

 

工作自体は何も無いと言うか、プルアップ抵抗以外は、センサとノイズの信号をデジタル入力につなぐだけ。センサの方は定常状態がHIGHで、信号が発生するとLOWになる。ノイズの方はセンサの振動によって発生して、定常状態でLOW、信号はHIGHになる。Edison内部でプルアップ抵抗をオンにすることも出来るが、推奨されている抵抗値が10~22KΩで、Edison内部の48KΩだと1回の信号の時間が長くなってしまうので、外部抵抗で対応する。

 

ポケガのSIGをデジタルIO2、NSをデジタルIO5につないで、それぞれプルアップ抵抗を介して5Vとも接続する。ポケガの+VとGNDをEdisonの5VとGNDにそれぞれ接続。

 

 

5.2 RadiationWatchのオリジナルスケッチで動作確認

 

スケッチもArduino向けに用意されているが、Edisonと互換性のないところが2つあって修正が必要。1つはループ回数の変数indexがEdisonでは使えない(予約語?)、もう一つはdouble floatをストリングに変換するのにArduinoではdtostrf()が用意されているが、Edisonは素直にsprintf()が使えること。

 

//dtostrf(cpm / min, -1, 3, cpmBuff);
//dtostrf(cpm / min / alpha, -1, 3, uSvBuff);
//dtostrf(sqrt(cpm) / min / alpha, -1, 3, uSvdBuff);
sprintf(cpmBuff, "%-1.3lf", cpm / min);
sprintf(uSvBuff, "%-1.3lf", cpm /min / alpha);
sprintf(uSvdBuff, "%-1.3lf", sqrt(cpm) / min / alpha);

 

んで、モニタリング用のアプリもWindowsなら提供されている。

ーん、ゼロシグナル。動いてるのかどうか、今ひとつ分からない。震災直後は雨樋の下とかに放射能が蓄積してたはずだから、ちょっと土を集めてくるか・・・

 

5.3 一定時間測定するようにスケッチを変更

 

で、RadiationWatchのスケッチだとループする回数を決めてその間のカウントを表示するようになってる(測定時間は不定)けど、測定する時間を何秒間とか決めた方が分かりやすいと思うので、Edisonのサンプルスケッチを参考にしながら書き直す。

 

サンプルスケッチ:01.Basics>DigitalReadSerial, 02.Digital>Button,

 

// RadiatinWatch Pocket Gaiger Type 5 for Edison
// sorrow@zigsow

const int SIGNAL = 2; // シグナル入力ピン(プルアップ抵抗10KΩ)
const int NOISE = 5; // ノイズ入力ピン
const int LED = 13; // LED出力ピン
const double ALPHA = 53.032; // シーベルト単位変換係数
const int LAP = 15; // 測定時間(秒)

int signalCount;
int noiseCount;
char cpm[20];
char uSv[20];
char uSvd[20];
char msg[256];
int signalFlag;
int noiseFlag;
int countFlag;
int lap0;
int lap1;
double minutes;
int i;

 

void setup() {
 Serial.begin(9600); // シリアル通信開始
  pinMode(SIGNAL, INPUT); // シグナル入力設定
  pinMode(NOISE, INPUT); // ノイズ入力設定
  pinMode(LED, OUTPUT); // LED出力設定
  signalFlag = 0;
  noiseFlag = 0;
  countFlag = 0;
  i = 0;
}

 

void loop() {
 signalCount = 0;
 noiseCount = 0;
 lap0 = millis(); // 測定開始時刻を取得(ミリ秒)
 do {
  int _signal = digitalRead(SIGNAL); // シグナル読み込み
  int _noise = digitalRead(NOISE); // ノイズ読み込み
  if (_signal == 0 && signalFlag == 0) { // シグナル電圧が下がった瞬間にカウントフラグを立てる
    signalFlag = 1;
    countFlag = 1;
    digitalWrite(LED, 1); // LEDを点灯する
  } else if (_signal == 1 && signalFlag == 1) {
    signalFlag = 0;
    digitalWrite(LED, 0); // LEDを消す
  }
  if (_noise == 1 && noiseFlag == 0) { // ノイズ電圧が上がった瞬間にカウントする
    noiseCount++;
    noiseFlag = 1;
  } else if (_noise == 0 && noiseFlag == 1) {
    noiseFlag = 0;
  }
  if (countFlag == 1 && noiseFlag == 0) { // ノイズがない時のみシグナルをカウントする
    signalCount++;
    countFlag = 0;
  }
  lap1 = millis(); // 現在時刻を取得(ミリ秒)
  } while ((lap1 - lap0) < (LAP * 1000)); // 測定時間まで繰り返す

  minutes = (lap1 - lap0) / 60000.0; // 実際の測定時間をミリ秒から分単位に換算
  sprintf(cpm, "%-1.3lf", signalCount / minutes);
  sprintf(uSv, "%-1.3lf", signalCount / ALPHA / minutes);
  //sprintf(uSvd, "%-1.3lf", sqrt(signalCount) / ALPHA / minutes);
  sprintf(msg, "%03d: Count:%03d CPM:%s uSv:%s Noise:%d", i, signalCount, cpm, uSv, noiseCount);
  Serial.println(msg); // シリアルポートに書き出し
  i++;
}

 

5.4 WiFiでリモートPCから見れるようにWebサーバを立てる

 

 サンプルスケッチ:WiFi>SimpleWebserverWiFi

 

調査中

 

5.5 Intel IoT Analyticsに送る

 

Intel IoT Platforms: Getting Started: Cloud Analytics

 

日本語のガイドではこちらが参考になる:Developers.IO

 

結構手順が多い。大まかには、

 (1)IoT Analyticsのアカウント取得とアクチベーションコードの発行

 (2)Edisonでiotkit-agentを起動し、EdisonをIot Analyticsに登録する

 (3)モニタするデータの種類(コンポーネント)を定義する

 (4)IoT Kit Arduinoライブラリのサンプルコードを使ってデータ送信

というステップになる。

 

5.5.1 IoT Analyticsのアカウント設定

 

IoT Analyticsサイトから、Singn Up Hereで新規ユーザ登録。

 

ログインしてダッシュボードの右上のボタンを押すと下にメニューが出る。

EdisonをデバイスとしてIoT Analyticsに登録するために、IoT AnalyticsでActivation Codeを発行する。メニューからAccountを選んで、

Activation Codeの右の発行ボタン、目ボタンを順に押してコードを取得。

 

5.5.2 Edisonでiotkit-agentを起動する

 

続いて、Edisonの方をセットアップ。Edisonに始めからインストールされてるiotkit-agentってやつを起動する。これは一回やればEdisonを再起動してもOK。

 

# systemctl enable iotkit-agen

# systemctl start iotkit-agent

# iotkit-admin test(ネットワークにつながっているかどうか確認)

# iotkit-admin device-id(Edisonのdevice-ideを確認)

 

次のactivateコマンドにIoT Analyticsでゲットしたコードを渡す。

 

# iotkit-admin activate xxxxxxxx(上で発行したActivation Code)

 

すると、EdisonからIoT Analyticsにつながってダッシュボードのデバイスの欄に1 Activeと表示されるようになる。これをクリックすると、Edisonのdevice-idが登録されているのが分かる。

 

※iotkit-adminコマンドリスト

 

Usage: iotkit-admin [options] [command]

 

Commands:

 

test                                         Tries to reach the server (using the current protocol).
activate <activation_code>       Activates the device.
register <comp_name> <catalogid> Registers a component in the device.
reset-components                    Clears the component list.
observation <comp_name> <value> Sends an observation for the device, for the specific component.
catalog                                    Displays the Catalog from the device's account.
components                             Displays components registered for this device.
initialize                                   Resets both the token and the component's list.
update                                     Send update device request to dashboard
pull-actuations                          Fetches actuations from last time action was executed or 24h if never and executes them one by one
protocol <protocol>                  Set the protocol to 'mqtt' or 'rest' or 'rest+ws'
host <host> [<port>]               Sets the cloud hostname for the current protocol.
device-id                                  Displays the device id.
set-device-id <id>                    Overrides the device id.
clear-device-id                          Reverts to using the default device id.
save-code <activation_code>    Adds the activation code to the device.
reset-code                                Clears the activation code of the device.
proxy <host> <port>               Sets proxy For REST protocol.
reset-proxy                              Clears proxy For REST protocol.
set-logger-level <level>            Set the logger level to 'debug', 'info', 'warn', 'error'
set-data-directory <path>         Sets path of directory that contains sensor data.
reset-data-directory                  Resets to default the path of directory that contains sensor data.
move-data-directory <path>     Change directory where data will be stored
gateway-id                               Displays the geteway id.
set-gateway-id <id>                 Overrides the geteway id.
set-device-name <name>         Change device name
reset-device-name                    Resets to default device name.
set-udp-port <udp_port>          Overrides the port UDP listener binds to

*                                             Error message for non valid command

 

Options:

 

-h, --help output usage information
-V, --version output the version number
-C, --config [path] Set the config file path

 

※何か動かなくなってリセットしたいときは、

 

# iotkit-admin initialize

 

5.5.3 モニタするデータ(コンポーネント)を定義する

 

先にIoT Analyticsで受信するデータの種類を定義して、それからEdisonでそのデータを送りますよという設定を行う。

 

IoT Analyticsの左側ペインのメニューからAccountでMy Accountを開いて、右側のCatalogボタンを押すと、始めからhumidity, powerswitch, temperatureというデータが定義されている。新しいデータを定義するには、下のAdd a New Catalog Itemボタンを押して、データ名やタイプ、種類、型などを選択する。Unit of measure(単位)を適当に入力しないとエラーになる。MinとMaxは入れなくても大丈夫。

IoT Analyticsの変更をEdisonに反映させるには、iotkit-agentを再起動する必要がある。

 

# systemctl stop iotkit-agent

# systemctl start iotkit-agent

# iotkit-admin catalog

# iotkit-admin register アライアス データ名

# iotkit-admin components (登録したデータタイプを表示)

 

 

5.5.4 サンプルコードでデータ送信

 

Arduino IDEで使えるiotkitのサンプルコードはgithubからDL。解凍しない。

 

Arduino IDEのSketchメニューから >Include Library > Add .ZIP Library... でDLしたZIPファイルを指定する。これでFile > Example >IoTkitが選べるようになる。

 

#include <IoTkit.h> // include IoTkit.h to use the Intel IoT Kit
#include <Ethernet.h> // must be included to use IoTkit
#include <aJSON.h>
#include <SPI.h>
#include <WiFi.h>

const int SIGNAL = 2; // シグナル入力ピン(プルアップ抵抗10KΩ)
const int NOISE = 5; // ノイズ入力ピン
const int LED = 13; // LED出力ピン
const double ALPHA = 53.032; // シーベルト単位変換係数
const int LAP = 15; // 測定時間(秒)

int signalCount;
int noiseCount;
char cpm[20];
char uSv[20];
char uSvd[20];
char msg[256];
int signalFlag;
int noiseFlag;
int countFlag;
int lap0;
int lap1;
double minutes;
int i;

IoTkit iotkit;
float radiation;

void setup() {
Serial.begin(115200);
iotkit.begin();
pinMode(SIGNAL, INPUT); // シグナル入力設定
pinMode(NOISE, INPUT); // ノイズ入力設定
pinMode(LED, OUTPUT); // LED出力設定
signalFlag = 0;
noiseFlag = 0;
countFlag = 0;
i = 0;
}

void loop() {
countRadiation();
iotkit.send("radiation", radiation);
delay(2000);
}

void countRadiation() {
signalCount = 0;
noiseCount = 0;
lap0 = millis(); // 測定開始時刻を取得(ミリ秒)
do {
int _signal = digitalRead(SIGNAL); // シグナル読み込み
int _noise = digitalRead(NOISE); // ノイズ読み込み
if (_signal == 0 && signalFlag == 0) { // シグナル電圧が下がった瞬間にカウントフラグを立てる
signalFlag = 1;
countFlag = 1;
digitalWrite(LED, 1); // LEDを点灯する
} else if (_signal == 1 && signalFlag == 1) {
signalFlag = 0;
digitalWrite(LED, 0); // LEDを消す
}
if (_noise == 1 && noiseFlag == 0) { // ノイズ電圧が上がった瞬間にカウントする
noiseCount++;
noiseFlag = 1;
} else if (_noise == 0 && noiseFlag == 1) {
noiseFlag = 0;
}
if (countFlag == 1 && noiseFlag == 0) { // ノイズがない時のみシグナルをカウントする
signalCount++;
countFlag = 0;
}
lap1 = millis(); // 現在時刻を取得(ミリ秒)
} while ((lap1 - lap0) < (LAP * 1000)); // 測定時間まで繰り返す

minutes = (lap1 - lap0) / 60000.0; // 実際の測定時間をミリ秒から分単位に換算
//sprintf(cpm, "%-1.3lf", signalCount / minutes);
//sprintf(uSv, "%-1.3lf", signalCount / ALPHA / minutes);
//sprintf(uSvd, "%-1.3lf", sqrt(signalCount) / ALPHA / minutes);
//sprintf(msg, "%03d: Count:%03d CPM:%s uSv:%s Noise:%d", i, signalCount, cpm, uSv, noiseCount);
i++;
radiation = signalCount / minutes;
}

 

IoT AnalyticsのChartメニューからいろいろ設定してこんなグラフがやっと出来た。-ん、た・い・へ・ん。

 

 

 

6.ArduinoをつないでシリアルLEDを光らせる

 

(結論から)Edisonを使ってシリアルLEDを制御するというこのセクションの当初の目標は、結論から言うと頓挫した。理由は二つあって、一つはEdisonのMPUではシリアルLEDの制御プロトコルであるDMX512信号を生成できないこと、もう一つは、MPUの代わりにArduinoを使おうとすると、Arduinoのシリアルポートが1つしか無いためシリアルLEDと制御用のEdisonの両方をArduinoに接続することが出来ない。回避策は、シリアルLEDをあきらめてただのLEDをEdisonで制御する。ま、車の方向指示器と思えば・・・しかし、とおい回り道だった orz

 

6.1 シリアルLEDの制御に使われるDMX512という通信規格について

 

ATmega328向けのライブラリしか無くて、EdisonのマイコンであるQuarkには開発されていなかった。ところが、なにげにMCU SDKの説明を見てると、何とこんな一文が。

 

・MCU provides a microsecond-level (1 µs) high accuracy delay API. 

 

そして、

 

mcu_delay

This API pauses the application for a period of time; it does not make the application sleep. Always call mcu_sleep if an application needs to sleep for more than one tick (10 ms).

int mcu_delay(int delay_us)

...where:

・delay_us: the number of microsecond to pause.

・return value: 0 if successful

 

エエッー!ミリ秒じゃなくてμ秒って書いてあるじゃん。DMXのビットシグナルは4μ秒だから、簡単にパケット送信関数が書けるじゃん。ってことで、書きました。一番クリティカルなのは、Start BitからStop bitまでの間にOSのインタラプトが入らないことと、GPIOへの書き込みとデータビットのロードに要する時間が4μ秒に対して無視できる程小さいこと。実際に使えるかどうかは実験してみるのが一番。=>セクション3.6参照

 

結果は、100MHzのQuarkでは、ちょっと速さが足りない。Galileoの400MHzあれば何とか行けた。

 

 6.2 WS2822s on "あちゃんでいいの"

 

シリアルLEDをEdisonで直接ドライブするのは不可能に近い(Quarkのレジスタを直接操作するAPIが提供されれば可能性はある)ので、現場のお仕事はArduinoに任せてEdisonから司令を出すようにするという手しかない。とりあえず、あちゃんでいいのにつないでスイッチサイエンスのライブラリを入れると光ってくれた。最初のスケッチでアドレスを書き込み、ここで一旦あちゃんでいいののUSBを外して付け直すという動作をはさんで、二つ目のスケッチでLEDを光らせるデモ。

 

 

 ああーっ、まぶしっ。なんだこれ。(輝度を0xFFマックスにしてたせいです)

 

6.3 Serila LED on "Achandiino" on "Edison"

 

これ、何か難しい。Edisonから色情報をArduinoにシリアルで転送して、Arduinoにはシリアル受信する待受ソフトを入れておいて、何か送られてきたらそれをシリアルLEDに送っちゃうという。

 

まずは、USBシリアル接続したあいちゃんでいいのに、右方向、左方向、ストップのLED発光モードをインスコして、1文字コマンド(r, l, s)で制御することに。

 

サンプルスケッチ:04.Communication>SerialEvent, 05.Control>switchCase


#include "Ws2822s.h"
#define NUM_PIXELS 10
#define LED_PIN 7

Ws2822s LED(LED_PIN, NUM_PIXELS);
int numRepeats = 10; //LEDを光らせる回数(表示時間)

void setup()
{
  Serial.begin(9600); //Edisonからシリアル通信で司令を受け取る
}

void loop()
{
  while(Serial.available() > 0) {  //シリアルポートから1文字コマンド(r, l, s)を読みます
    int inByte = Serial.read();
    int i = 0;
    switch (inByte) {
      case 'r':
        for (i = 0; i < numRepeats; i++) {
          setRight();
        }
        setOff();
        break;
      case 'l':
        for (i = 0; i < numRepeats; i++) {
          setLeft();
        }
        setOff();
        break;
      case 's':
        for (i = 0; i < numRepeats; i++) {
          setStop();
        }
        setOff();
        break;
      default:
        setOff();
    }

  setOff();
  delay(1);
  }
}

void setRight() //右インジケータのルーチン
{
  for (int i = 0; i < NUM_PIXELS; ++i) {
    LED.setColor((i + 0) % NUM_PIXELS, 0xFF, 0x00, 0x00);
    LED.setColor((i + 1) % NUM_PIXELS, 0xFF, 0xFF, 0x00);
    LED.setColor((i + 2) % NUM_PIXELS, 0x00, 0xFF, 0x00);
    LED.setColor((i + 3) % NUM_PIXELS, 0x00, 0xFF, 0xFF);
    LED.setColor((i + 4) % NUM_PIXELS, 0x00, 0x00, 0xFF);
    LED.setColor((i + 5) % NUM_PIXELS, 0xFF, 0x00, 0xFF);
    LED.setColor((i + 6) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.setColor((i + 7) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.setColor((i + 8) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.setColor((i + 9) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.send();
    delay(50);
  }
}

void setLeft() //左インジケータのルーチン
{
  for (int i = 0; i < NUM_PIXELS; i++) {
    LED.setColor(((NUM_PIXELS - i) + 9) % NUM_PIXELS, 0xFF, 0x00, 0x00);
    LED.setColor(((NUM_PIXELS - i) + 8) % NUM_PIXELS, 0xFF, 0xFF, 0x00);
    LED.setColor(((NUM_PIXELS - i) + 7) % NUM_PIXELS, 0x00, 0xFF, 0x00);
    LED.setColor(((NUM_PIXELS - i) + 6) % NUM_PIXELS, 0x00, 0xFF, 0xFF);
    LED.setColor(((NUM_PIXELS - i) + 5) % NUM_PIXELS, 0x00, 0x00, 0xFF);
    LED.setColor(((NUM_PIXELS - i) + 4) % NUM_PIXELS, 0xFF, 0x00, 0xFF);
    LED.setColor(((NUM_PIXELS - i) + 3) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.setColor(((NUM_PIXELS - i) + 2) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.setColor(((NUM_PIXELS - i) + 1) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.setColor(((NUM_PIXELS - i) + 0) % NUM_PIXELS, 0x00, 0x00, 0x00);
    LED.send();
    delay(50);
  }
}

void setStop() //ストップインジケータのルーチン
{
  for (int i = 0; i < NUM_PIXELS; i++) {
    LED.setColor(i, 0xFF, 0x00, 0x00);
    LED.send();
    delay(50);
  }
}

void setOff() //オフにするルーチン
{
  for (int i = 0; i < NUM_PIXELS; i++) {
    LED.setColor(i , 0x00, 0x00, 0x00);
    LED.send();
    delay(50);
  }
}

 

 

むむむっ、これってバイクの方向指示器になるかな?

 

あとは、Edisonとあちゃんでいいのをシリアル接続してやれば、Edisonから制御できるはず。

 

>>いや、出来ないって。あちゃんでいいのには一度に一つしかシリアル接続できない。EdisonとシリアルLEDを同時につなぐことは出来ない。むりむりむり、むりなんだよ。

 

 

6.4 加速度センサを使って頭の動きでLED発光を制御する

 

加速度センサのアナログ情報を読み取ってLEDの点滅する方向を変える(右・左・ストップインジケータ)。加速度センサはInvenSense社のMPU 6050のブレークアウトボードGY-521のaitendo製格安版をゲット。端子はメスソケットを買ってきて半田付けした。

MPU 6050に関するサイトの情報が古くなっていて、動かない。さんざん徘徊した挙句、やっとたどり着いた動くスクリプトがこちら > 素人がつくってみた(やっぱり)

参考になるサイトは、androciti wiki MPU-6050三軸加速度三軸ジャイロセンサーモジュール

 

!!!注意点!!!

6.4.1 配線>4本つなぐ

VCC:3.3V

GND: GND

SCL: A5(またはSCL)

SDA: A4(またはSDA)

INT: DIGITAL IO2(インタラプト制御)

 

6.4.2 MPU 6050のドライバをArduinoライブラリにコピー

ドライバはこちら

Arduinoのスケッチを保存してるフォルダ(ドキュメント>Arduino)の中にあるlibrariesフォルダに、I2CdevフォルダとMPU6050フォルダをコピー。MPU6050フォルダの中にあるExamplesフォルダは使わない(動かない)。

 

6.4.3 3DプロットアプリProcessing 3.0をダウンロード

DLページはこちら

インスコする必要はないので、適当な場所に解凍する。Processing 3.0のsketchbookフォルダの中にスクリプトを保存する。

 

6.4.4 Edisonを立ち上げる

SSH2でログインして、I2Cセットアップのスクリプトを実行する(セクションB4.5参照)。

sh init_i2c8.sh

※これをやっておかないと、Edisonを立ち上げただけではI2Cがつながらないと思う。

 

6.4.5 シリアルコンソールを開いた状態でArduinoスケッチをEdisonにダウンロード

※ダウンロード直後にMPU 6050との通信に成功したかどうか表示される。

//「素人がつくってみた」サイトからコピペ

#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"

MPU6050 accelgyro;

int16_t ax, ay, az;
int16_t gx, gy, gz;

#define LED_PIN 13
bool blinkState = false;

String str_out;

void setup() {
Wire.begin();
Serial.begin(115200);

// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();

// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");

// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}

void loop() {
// read raw accel/gyro measurements from device
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

str_out = String(ax) + "," + String(ay) + "," + String(az) + "," + String(gx) + "," + String(gy) + "," + String(gz);
Serial.println(str_out);

// blink LED to indicate activity
blinkState = !blinkState;
//delay(100);
digitalWrite(LED_PIN, blinkState);
}

6.4.6 Arduinoのシリアルコンソールを閉じてからProcessing 3.0のスケッチを実行

※シリアルコンソールを閉じておかないとコンフリクトエラーになる。

import processing.serial.*;

PShape box1;
PVector v_center, v_camera;
Serial myPort;
int lf = 10;
String str_get_data = null;
String buf[];
int ax,ay,az;

void setup(){
size(700,700,P3D);
v_center = new PVector(0.0,0.0,0.0);
v_camera = new PVector(900.0,1100.0,900.0);
box1 = createShape(BOX,100,100,100);
box1.translate(50,50,50);
myPort = new Serial(this, "COM4", 115200); //COMポートの番号は自分のに合わせて
}

void draw(){
background(200);
noFill();
strokeWeight(1);
stroke(0,0,0);
translate(250, 250, 250);
box(500, 500, 500);
translate(-250, -250, -250);
strokeWeight(3);
stroke(255,0,0);
line(0,0,0,500,0,0);
stroke(0,255,0);
line(0,0,0,0,500,0);
stroke(0,0,255);
line(0,0,0,0,0,500);

shape(box1);
camera(v_camera.x, v_camera.y, v_camera.z, v_center.x,v_center.y,v_center.z, 0.0, 0.0, -1.0);
}

void serialEvent(Serial myPort){
str_get_data = myPort.readStringUntil(lf);
if (str_get_data != null){
str_get_data = trim(str_get_data);
buf = split(str_get_data,",");
try{
fill(255,127,0);
stroke(0,0,0);
ax = int(buf[0])/100*2;
ay = int(buf[1])/100*2;
az = int(buf[2])/100*2;
box1 = createShape(BOX,ax,ay,az);
box1.translate(ax/2,ay/2,az/2);
} catch(Exception e) {
e.printStackTrace();
}
}
}

センサを基盤に書いてあるX軸、Y軸、Z軸(上下)に傾けると、そっち方向のボックスの大きさが変化する。動画では緑がX軸、赤がY軸、青がZ軸に相当する。いろいろ動かしてみると、MPU 6050は加速度センサって言うけど実際は傾きセンサだということが分かる。水平移動では信号が出ない。軸の周りに傾きをつけると信号が発生する。また、MPU 6050のジャイロセンサの方は、軸の周りに回転させた時の動きによって信号が発生する。つまり、傾こうとしている「動き」とどれくらい傾いているかという「状態」の二つが検出される。

例えば、バイクのヘルメットにこれを付けて頭を傾けた方に方向指示器を出そうとすると、センサの軸の周りの回転の動きは小さくて傾きの変化の方が大きいと思うから、使うとしたら傾きの方だろう。ヘルメットの水平移動を検出しようとすると、慣性(モーメント)センサが必要になる。IMU (Inertia Measurement Unit)という名前で、数千円する。いや、6050でとりあえずやってみよ。

 

6.5 バッテリ駆動への対応

 

バッテリー駆動にするため、Lipoly電池850mAをゲット。ただし、これは3.7V出力なのでUSBブースタで5.2VにDC/DC変換する。

 

よくよく調べてみると、Edisonは3.7Vで駆動するらしい。ブースタは必要なかった。

 

Edison本体の近くにあるJ2ピン(BATT)にLiPolyをつなぐと、LED (DS3)が光って充電を始める。

 

 

 

B.資料編

 

1.略語・用語の一覧と心の準備


 

1.1 最初のハードル

 

電子工作、やっぱり辛い・・・orz  何がって?何言ってるのかさっぱり分かんないんだよ。なに、この訳のわからん3文字略語?とりあえず、この程度は理解しておかないとマニュアルも読めないっていうのをまとめてみた。

 

API: Application Programming Interface(ソフト開発におけるシステムレベルの呼び出し関数)

CISC: Complex Istruction Set Computer(拡張命令セットコンピュータ、x86系のATOM、Quarkなど)

GPIO: General Purpose Input/Output(汎用入出力)

I2C: Inter-Integrated Circuit(アイスクエアドシー、シリアル通信規格)

IDE: Integrated Development Environment(統合開発環境、アプリを開発するために必要なツールをまとめてグラフィカルユーザインタフェース上で使いやすくしてある)

IoT: Internet of Things(モノのインターネットと訳されるが、生物や機械を含め森羅万象がインターネットでPCを介さずに直接つながっている世界観を表す)

MCU: Micro-controller Unit(組み込み集積回路)

PWM: Pulse Width Modulation(パルス幅変調、電圧を制御する方法)

RISC: Reduced Instruction Set Computer(縮小命令セットコンピュータ、ARM系のATmega328など)

SDK: Software Development Kit(ソフトウェア開発キット)

SPI: Serial Peripheral Interface(シリアル通信規格)

RTOS: Real Time Operating System(アプリの呼び出しやタスクの優先j度といった時間的制約を保証するオペレーティングシステム)

UART:Universal Asynchronous Receiver Transmitter(シリアル通信とパラレル通信のデータ変換装置)

 

Breadboard: 元々はその名の通りパン切り台、しかし電子工作ヲタクの世界では半田付けせずに回路を作るための実験台を意味する。誰かすのこ状の見かけが似てると思ったんだ

Breakout Board: マイコンの入出力信号線を引き出して使いやすくするための拡張基盤

Sketch: スケッチとは、マイコンヲタクの間ではスクリプトのことを意味する

Shield: シールドとは、センサなどの回路を1枚の基盤にまとめてマイコン本体と簡単につなげられるようにしたもの

 

1.2 次のハードル

 

それから、Edisonはとにかく情報が散逸していて、何かもうグチャグチャになってる。だいたい日本語の情報が少ない。初心者にとって一番分かりにくいのが、Arduino互換ボードのマニュアルを見てもボードの説明図がどこにもないことだ。Breakout Boardの方は、マニュアルに各ピンの説明図がある。Edisonのブロックダイアグラムはあるが、これを見ただけではArduino互換ボードのどこに何を接続したらいいのか皆目見当もつかない。そんな、人の堪忍袋の大きさを測定するかのような仕様になっている理由のひとつは、恐らく通常はArduino互換ボードに直接何かを接続するのではなく、サードパーティー製のベース基盤(こちらには説明図がある)を介してセンサ類をつなぐとか、シールド基盤をソケットに刺すだけといった使い方をするからかも知れない。でも初心者は戸惑う。もう一つ、互換ボードの各ピンにはマルチプレキシングと言って複数の信号を割り当てることが出来るため、何番のピンは何の信号と決まっていないことも、初心者をパニックに陥れる。いちいちLinuxのコマンドラインから命令を打って指定してやる必要があるのだ。 そんなもんGUIで設定できるようにして欲しい。

 

1.3 心の準備

 

”スケッチ”って、C++言語って言うとなんかハードル高い、だからラフスケッチを描くように簡単にアプリが作れるよっていう意図、かな?最初は真似するのが学習効率が良いのは確かだけど。でも、電子回路とかブレッドボードとか、へ?ってレベルの人間にとって、マイコンはとにかくハードル高い。心理的に。しかもEdisonはちゃんとしたLinuxシステムで、(GUIコンソールが無いけど、それはリモート接続のサーバと一緒)、アプリ開発環境の知識も必要で、Edisonの性能はやっぱり(shutdownもせずに電源切っちゃうような)素人レベルが相手じゃないでしょ、はっきし言って。Edisonを使いこなすには専門的な知識を持った人じゃないと難しいと思うし、実際Developer Zoneに出没する人たちにはWiFiがチップに組み込まれた(拡張ボードではない)Edisonはものすごいインパクトがあったみたいだ。しかしプロですらIntelの資料がないっていってる状況だから、素人は。まぁ、だからこそ面白い、と思える人じゃないとちょっと大変な一面はあるかな。

 

 

2.Arduino互換性に関する見解


 

IntelはArduinoのエコシステムを引き継ぐように設計されているが、Edisonの本質は実はArduinoと互換性が無い。むしろ、発売から1年になる現在でもプロセスの管理はEdison、リアルタイム制御はArduinoと、両者を併用することが想定されているようだ。Arduinoとの互換性について、Intelの中の人が「HANDS ON INTEL EDISON」で次のように言っている(下にsorrow訳)。

 

Programming & Arduino Compatibility

 

Similar to the Galileo, Edison contains an Arduino implementation as a userland Linux program. The Intel-reengineered Arduino IDE is a collection of cross-compiler tools to upload an application to the module. This design decision to emulate Arduino is a longstanding frustration — and in my personal opinion — the most poorly designed aspect of the product. Problems stemming back to Galileo — including library compatibility, shield support, and GPIO speed weren't 'fixed' in Edison — a fact that is not surprising given the emulated implementation. Want to drive a string of WS2811 LEDs? No such luck.

 

As embedded Linux developers know, hardware-level programming in Linux is usually a function of writing and reading data from file descriptors known to the kernel. Any programming language capable of reading and writing to a file is capable of controlling GPIO pins along with a host of other protocols like I2C and SPI. The underlying Arduino library shipping with the IDE is a great reference for this method of programming, illustrating the support logic necessary to configure pins prior to use.

 

Another aspect of the platform (at launch) is programming library availability. The Yocto binary comes pre-installed with recent versions of NodeJS and Python, but there are no convenience libraries to unravel the tangle of descriptors and hardware capabilities. On the bright side, this is likely to evolve quickly given the drive of the open-source community to create accessible and easy-to-consume libraries.

 

Over the course of validation, my preferred prototyping experience involved performing high-level messaging and compute in Linux. What do I mean by this? The Edison excels at applications involving networking/messaging (BLE/HTTP/Websockets) and peripherals like USB cameras, audio interfaces, and MIDI controllers. In particular, NodeJS shines for this functionality on Edison. However, for hardware I/O, it's much simpler to pair Edison with an ATmega chip via UART rather than mess with the on-board I/O capabilities. Prototyping using a combination of NodeJS on Edison along with at ATmega is a solid experience. I'll buy yet another beer for the first person to port Node-Red to Edison.

プログラミングとArduino互換性(sorrow訳)

 

Galileoと同じく、EdisonにおけるArduinoの実装はユーザーランドLinuxプログラム[カーネル以外のアプリ]という位置づけだ。 IntelはArduino開発環境をリエンジニアリングして、アプリをEdisonにアップロードするための一連のクロスコンパイラ・ツールをそろえている。Arduinoをエミュレートするという設計思想は長く不満・失望の種で、私個人はこの製品において一番失敗している部分だと考えている。Galieoまで遡る問題、即ちライブラリ互換性、シールドのサポート、GPIOスピードなどが、Edisonでも未解決のままだ。エミュレーションによる実装であることを考えれば驚くことではない。WS2811 LEDストリップを動作させたいと思っても、出来ないのだ。

 

埋め込みLinux開発者なら知っているが、ハードウェア・レベルのLinuxプログラミングは、通常カーネルに見えているファイル・ディスクリプタからのデータの読み書きによる。ファイルを読み書きできるプログラミング言語であれば、GPIOピンとI2CやSPIといった多くのプロトコルを制御することが出来る。Edisonの開発環境にバンドルされているArduinoの基本ライブラリは、このようなプログラミング手法ではとても参考になるし、それぞれのピンを使用するに当って必要となる設定の手助けとなるロジックを分かりやすく提供してくれる。

 

別の観点から、(立ち上げの時点での)プラットフォームではプログラミング・ライブラリがあるか無いかということがある。Yoctoバイナリには、NodeJSとPythonの新しいバージョンが予めインストールされている。しかし、複雑に絡み合ったディスクリプタやハードウェアの性能を解きほぐしてくれる便利なライブラリがない。明るい面を見れば、オープンソース・コミュニティが手頃な使いやすいライブラリを作ってくれるだろうから、急速に改善するとは思う。

 

検証の過程で私が好んだプロトタイピングの方法はLinuxでハイレベルのメッセージングと計算を行うというものだ。これはどういうことか?Edisonが秀でているのは、ネットワーク・メッセージング(BLE/HTTP/Websokets)やUSBカメラ、オーディオ・インターフェース、MIDIコントローラといった周辺機器に関連したアプリだ。特に、NodeJSがこのようなEdisonの機能では際立っている。一方で、ハードウェアI/Oでは、EdisonとATmegaチップをUARTでつなぐ方が、オンボードI/Oをこねくり回すより遥かにシンプルだ。Edisonで動くNodeJSとATmegaの組み合わせを使ったプロトタイピングは堅実な方法だ。EdisonにNode-Redをポートしてくれた最初の人にビールを一杯!

 

下線の部分が、Edisonの特徴を捉えている。harmankardonさんやcapivara3さんのEdisonプレミアムレビューでシリアルLEDを動かすためのArduinoスケッチがコンパイル出来なかったり動かなかったりしたのは、Arduinoスケッチが8-bitマイコンであるATmega328のインストラクションセットを用いたインライン・アセンブリ言語で記述されているのが原因だ。EdisonがATOM (x86系) x ATmega328 (ARM系)のデュアルプロセッサなら互換性の問題は無かった。x86系のAndroidとARM系のAndroidの間の互換性問題を彷彿とさせる(関係ないか)。

 

GalileoはQuark SoCシングルプロセッサだが、EdisonはもともとQurak x Qurakのデュアルプロセッサとしてスタートしたといううわさがある。それがATOM x Quarkのデュアルプロセッサになった理由は固より推測する術もないが、恐らくホビーストではなく業界を主なターゲットにしているIntelのマーケティングと関係してるんだろう。Quarkは昨年Edisonが発表された時点では有効化されておらず、今年の5月に行われたファームウェアのバージョンアップで始めて動くようになった。それに伴ってQuarkのためのアプリ開発環境Intel MCU SDK(次のセクション3で説明)が公開されている。ただ、現時点ではQuarkのローレベルプログラミングによってリアルタイム制御を行うという動きはほとんど見られず、上のブログにあるようにEdisonとArduino (ATmega328)を併用することがデファクト・スタンダードになっているようだ。

 

 

3.Edisonの開発環境について


 

Edisonのアプリ開発には少なくとも5つの環境が用意されている(Developer Zone)。

  • Intel Arduino IDE(Arduinoライブラリ)
  • Intel XDK IoT Edition (Node.js, JavaScript)
  • Eclipse (C++, Python, Librmaaライブラリ, UPM, IoTkitcommライブラリ)
  • Intel MCU SDK  (Quark開発)
  • Intel System Studio for IoT (System Studio 2015 evaluation)
  • Wyliodrin(Webベースの開発ツール、現在はGalileoのみ対応)

 

3.1 Intel Arduino IDE

 

IntelのEdisonページはもう支離滅裂でついて行けない。 Arduino IDEをインストールしようとすると、いきなりこれだ、Nextボタンがグレーアウトされてどこにも行けない。Arduino IDEをどこから手に入れたらいいかも分からない。恐らくサポートページをぐだぐだ作ってるうちに自分たちでもわけ分かんなくなってそのまま放置プレーし てるんだと思う。

 

ということで、あちこち嗅ぎまわってるうちにこんなページが。

 

どうやら、Arduino IDEは本家のHPからDLするらしい。

 

やっ と見つかった。zipファイルをDLして展開するとインストールする必要がないので分かりやすいと思う。Arduino IDEを立ち上げて最初にするのが、Edison用のプラグインのDL。

 これを入れると、ツール>ボード>Intel(R) Edisonが選べるようになる。それから、ツール>ポートから、デバイスマネージャでIntel Edison Virtual Com Portと表示されているCOMポートを指定する。USB Serial Portの方ではない。ここも地雷のひとつ。

 

3.2 MCU SDK

 

お次はMCU SDKだけど、さっきのページにはDL先が見当たらない。結局、下のページにあるリンクからMCU SDKをDL。何でSDKのDL先を1箇所にまとめてくれないのか、理解に苦しむ。

 

 

4.Edisonのハードウェア


 

4.1 Edisonのカタログスペック

 

・ATOM 32-bit processor

コードネームTangier

22 nmプロセス

Silvermont x 2コア2スレッド

500 MHz

Yocto Linux 1.6(Debianも可)

・Quark 32-bit processor

100 MHz

"Viper" Real Time Operating System (UART, I2C, GPIOサポート)

・1GB LPDDR3メモリ

・4GB eMMCストレージ

・Broadcom 43340 WiFiモジュール(802.11 a/b/g/n, 2.4/5 GHz)

・Bluetooth 4.0

 

 

4.2 MCUのスペック

 

4.2.1 Intel MCU SDKのページに、MCUアプリの動作が少し説明してある。

 

 

”EdisonボードにおけるMCUアプリは、ViperというWind Riverが提供するリアルタイムOSの上で走るユーザアプリケーションである。MCUアプリのバイナリファイルはLinux RootFS [root file system]に保存され、Linuxカーネルがブートする時にMCUドライバによって[MCUに]ダウンロードされる。MCUアプリは[ホストから]独立してGPIOとUARTの制御、センサデータの収集・前処理、ホストCPU(EdisonボードのAtomプロセッサ)とのコミュニケーションを行う。MCUが走っている間もホストCPUは省電力モードに入ることが出来る。Intelが提供するMCU SDKと一連のAPIが、ユーザのMCUアプリ開発を支援する。”

※[ ]内はsorrowによる補足

 

ってことは、件のフォルダに任意のバイナリコードを放り込んでリブートしてやれば、MCUが勝手に読み込んで実行してくれるってことじゃん。でも、Intel Developer ZoneのIntel関係者は、MCUにバイナリを送り込めるのはMCU SDKだけだと言ってたなぁ。=>バイナリをMCUにロードするスクリプトは、

/etc/intel_mcu/mcu_fw_loader.sh

 

#!/bin/sh

#author: JiuJin Hong (jiujinx.hong@intel.com)

if [ ! -d "sys/devices/platform/intel_mcu" ];then

        exit

fi

if [ ! -f "/lib/firmware/intel_mcu.bin" ];then

        exit

fi

echo "load mcu app" > /sys/devices/platform/intel_mcu/control

 

この簡単なシェルスクリプトは、/sys/devices/platformにintel_mcuというデバイスが存在し、かつ/lib/firmwareフォルダにintel_mcu.binというバイナリファイルが存在する時に、/sys/devices/platform/intel_mcu/controlという仮想デバイスにload mcu appというコマンドを書き込むことを意味する。MCU SDKのMCU > DownloadというコマンドはビルドしたReleaseフォルダの中にあるintel_mcu.binというファイルをEdisonに転送し、MCU > UninstallというコマンドはEdisonからintel_mcu.binファイルを削除するという分かりやすい機能だ。EdisonのMCUと同じQuarkが動いているGalileoのバイナリがそのままEdisonのMCUで走るかどうか、非常に興味が持たれる。(検討中)

 

 

4.2.2 MCUサブシステムの概要

  • Intel 486にPentium IA ISA互換性を加えた極小アーキテクチャ
  • 全開のD0パワーステートの100MHzから”アクティブ・アイドル”のS0ixスリープステートの38.4MHzまで
  • コードとデータを含めて192KBのSRAM
  • MCUサブシステムの制御とMCUとAtomとのやりとりを支援するプロセッサ間通信メカニズム
  • システム制御ユニット(SCU)のI2C8とI2C9はMCUに割り当て
  • MCUはUART1とUART2にアクセス可、ただしLinuxカーネルコンソールにも使われる
  • MCUはすべてのGPIOポートにアクセス可
  • MCUはすべてのPWMをホストAtomと共有する
  • MCUはμ秒レベルの高精度遅延を提供する。詳しくは付録APIセクション参照・・わぁお
  • 複数のレベルでデバッグ可能
  • MCUアプリを開発するためのMCU SDKはWindows, OSX, Linuxで使える

 

4.2.3 ユーザスペースのLinuxアプリからアクセスできるMCU側のインターフェースとしては、TTYとファイルシステムが挙げられている。

  • /dev/ttymcu0(メッセージ・データの転送、MCU側はhost_sendとhost_recieveを使う)
  • /dev/ttymcu1(MCUのログメッセージ)
  • /sys/devices/platform/intel_mcu/control(MCUアプリの書き込み専用ノード、内部使用のみ許可されている)
  • /sys/devices/platform/intel_mcu/fw_version(MCU SDKのバージョン)
  • /sys/devices/platform/intel_mcu/log_level(ログレベルを設定するための読み・書きノード:fatal, error, warning, info, debug)

 

4.2.4 制限事項

  • 一度ロードしたMCUアプリは再起動しないと削除できない(/dev/ttymcu0は書き込み専用!)
  • MCUアプリをロードするには再起動が必要
  • MCUアプリの大きさは最大120KBまで
  • MCU OSのtick valueは10ms(何だろ?)
  • SDKをインスコするフォルダの名前はスペースを含んではいけない
  • 浮動小数点は扱えない
  • I2Cは2つまで
  • シングルスレッドのみ
  • 先にLinuxがブートしないとMCUがブートしない
  • AtomとMCUは同じI/Oにアクセスできるが、競合しないようユーザが管理する必要がある
  • MCU SDK (Eclipse)はAtom C/C++ Eclipseとは別物である
  • MCUのI/O APIとAtomのI/O APIは同列ではない(not aligned)ので、移植するにはコードの書き換えが必要
  • MCUはwatchdog timerを持たない(エラー復帰?)
  • SPIは使えない
  • MCUを起動する前にLinux側でピンのマルチプレクシング(Arduino拡張ボード)を設定する
  • MCUからPWMにアクセスするには、Linux側でPWMランタイム電源管理を無効化しておく
  • プログラム可能な割り込みタイマーは無い

 

4.3 ボタンとインジケータ

 

4.4 GPIOマッピング(Arduiono互換ボードハードウェアマニュアル)

※シールドピン番号とEdison(Linux)内部のGPIO番号の対応とマルチプレックス機能の割り当て

 

※マルチプレックス機能を設定するためのコントロールGPIO番号

 

※出力有効化及びプルアップ有効化のGPIO番号

 

4.5 GPIOマッピングをしてくれるシェルスクリプトのリンク一覧


init_DIG.sh
init_i2c8.sh
init_mcu_PWM.sh
set_DIG.sh
read_DIG.sh
init_UART1.sh

 

 

5.WindowsのRNDISドライバ障害からの復帰


 

Windows環境はOSX環境より安定だと思うが、ある時突然RNDISドライバの起動に失敗するようになった。結局Linuxをクリーンインストールし直すまで、何をやってもだめだった。

 

Windows 7 Home 64 bit。ネットワークアダプタでUSB RNDIS Deviceにビックリマークが付いてて動いてない。他のシリアルポートは問題なく認識されてる。

 

とりあえずドライバの再インストールを試みる。IntelのドライバはWindows Standalone Driver 1.2.1(Developer Zone)に入っているもの。

 

やっぱり起動に失敗する。

 

それではということで、Microsoft CorporationのRNDISドライバ(Windows 7にデフォルトで入っている)を再インストールしてみる。

 

警告が出るけど無視。

 

これも起動に失敗する。どうなってんだ、いったい???

 

シリアルコンソールからふつうにログイン出来てる。usb0のネットワークアドレスも問題ない。

 

Linuxをリフレッシュするために、WindowsのPhoneFlashLiteをインストールする。ここでIntel DnX USB Driverというのも一緒にインストールされるんだけど、良く読むとパワーサイクルをしろと書いてある。つまり、ボードのパワーボタンを10秒長押ししてシャットダウンし、それから同じくパワーボタンを1秒押して起動する。こういう盲点でドツボにはまる。ひっかかるものか。

 

一応成功。これが、OSXではまともに動かない。

 

おっ、新しいネットワーク接続が認識されてる。RNDISドライバが通ったぽい。

 

やっぱりだ。RNDIS Deviceが認識されてる。

 

Edisonのusb0が自動設定で192.168.2.15になってるから、PCの方も同じイントラネットに設定する。

 

デバイスマネージャでもRNDIS Deviceのビックリマークがなくなってる。

 

フラッシュした直後。/home/rootに置いてあったファイルも全部無くなってて、クリーンインストールされたっぽい。reboot otaとかrun do_otaでは/home/rootのファイルは残るから、PhoneFlashToolLiteの方がいい。OSXでは PhoneFlashToolLiteはまともに動かないから、やっぱりEdisonやるならWindowsしかないってことか。

 

 

更新: 2015/10/15
総評

開発言語に強い人が居て、しかもチームで何か創っていくという感じかな。素人には厳しい。

すごいハードウェアだと思う。こんな大きさでデュアルプロセッサ動作。ターミナル接続でふつうにLinuxコマンドが打てて、ベンチマークが走る。うーん、すごい。

 

ただ、まったくの素人にはかなり厳しい。一人では特に。現時点で残念ながらまだ整備されてない部分が高い高~いハードルになると思う、て言うか、なった。なかなか苦労した。

 

一番のEdisonらしさは単体でWiFiにつながって、サーバにもクライエントにもなって、他のモノやPCとどんどんネットワークがつながっていくというコンセプトだと思う。面白い。ただ、それを活かすには、かなりの技術とアイデアと経験を要する。これ出来てる人、ホント尊敬ものだと思う。

 

MCUについては、Edisonの中でなんとも中途半端な立ち位置になっている。今のファームウェアとAPIでは、リアルタイムOSが走るというメリットを享受できないからだ。ただ、消費電力がATOMの10分の1ということで、ウェアラブルのようにMCUで動かすことが必須になる領域というのはあると思う。APIがもっと整備されたらガラッと状況が変わる可能性は高い。

 

素人としては、もっと、まとまった情報が欲しいと思った。ハードウェアしかり、開発環境しかり。Intel本家のサイトは基本的にほぼ英語情報のみ。これも、何か問題解決を探そうという時に足かせになるだろう。Windowsの開発環境は比較的安定しているが、OSXのシステムにはバグがあると思う。

 

一番いいなと思ったのは、Developer ZoneのEdison Community、質問を投げると即座にIntelの中の人が反応してくれて、結構丁寧に教えてくれる。解決にならないことも多いけど、Intelの開発の人に質問できるって、すばらしい。

25人がこのレビューをCOOLしました!

コメント (7)

  • harmankardonさん

    2015/09/14

    レビュー,お疲れ様です.

    Intel MCU SDKで,Lチカを動作させるなんて,さすがです.

    それにEdisonとArduinoの違いについての考察もわかりやすく,暗い森の中で灯りを見つけた感じがしました.でも,その森はとても深くて,私には太刀打ちできないことを改めて思い知らされました.

    レビュー後半も頑張ってください.
    そして,自ら進んで地雷を踏まないようにしてください.
  • jakeさん

    2015/09/14

    おおー、自分以上にいばらの道に挑んでる人がいたことにびっくりです。
    ※出たばっかりのころにNode.js側だけでプログラムを書いたんです。苦労しました。

    MCUを自由自在に動かせるようになると、Linuxコンピューターとして動かしながらハード寄りの処理を並行できるようになる、ようです。
    人間の大脳と小脳みたいな関係ですかね。
  • sorrowさん

    2015/09/15

    harmankardonさん

    有難うございます。QuarkはIntelのCommunityで検索しても今年の始め頃のSDKはいつ出るんだという質問がヒットする程度で、英語でも情報が少ないです。

    EdisonでQuarkは搭載されたけど実用化までには時間がかかるのかも知れません。その理由の一つは、恐らくIntel対ARM Cortexという競争が背景にあって(Appleも今後Cortexに置き換わると言ってる人も居ます)、開発が追いついてないんじゃないかという気がします。ただ、Edisonの潜在的な力に対しては特に業界の人たちの期待が大きいようです。

    MCU SDKのインストールはWindowsでは特に地雷はなかったのでぜひ試して下さい。ただし、Arduino IDEのようにスケッチを開いてロードするやり方ではなくて、メニューバーにあるMCUからNew MCU Projectで新しいプロジェクトを作ってそこにスケッチをコピペして書き込むというやり方です。Quarkへの書き込みも同じMCUメニューからDownloadします。
他4件のコメントを表示

ZIGSOWにログインするとコメントやこのアイテムを持っているユーザー全員に質問できます。

YouTube の動画を挿入

YouTube の URL または動画の ID を入力してください

動画の ID が取得できません。ID もしくは URL を正しく入力してください。

ニコニコ動画の動画を挿入

ニコニコ動画の URL または動画の ID を入力してください

動画の ID が取得できません。ID もしくは URL を正しく入力してください。

ZIGSOWリンク挿入

検索対象とキーワードを入力してください

    外部リンクを挿入

    リンク先の URL とタイトルを入力してください

    URL を正しく入力してください。

    画像を挿入(最大サイズ20MB)

    画像を選択してください

    ファイルサイズが20MBを超えています

    別の画像を追加

    ほかのユーザーのレビュー

    ZIGSOW にログイン

    ZIGSOW会員登録(無料)はこちらから