Arduino Yun cheat sheet

From misc notes
Jump to navigation Jump to search

Arduino Yún / Arduino Yun

はじめに

Arduino Uno である程度なれたし、プロトタイプつくったので、そろそろ TCP/IP 喋る段階になって、技適もとれた Arduino Yun に挑戦してみた。

インターネットに接続して AWS 上にある time series database に計測データをストア。(いわゆる IoT ですかね 火暴)
AWS IoT なるものも触ってみたかったし。

ダガシカシ、簡単に Yun に移行できるかと思っていたら、なかなか結構大変(現在も学習中)なのでいろいろメモ。

SRL と LLC

SRL:

http://www.arduino.org/
Arduino | Labs | Arduino Yún
https://github.com/arduino-org
Schematic

LLC:

https://www.arduino.cc/
Arduino - ArduinoYun
https://github.com/arduino
Schematics

私がスイッチサイエンス社から購入した Yun は製造は SRL。Atheros AR9331 に組み込まれていたのが Linino ではなく OpenWrt-Yun なので LLC 。

実際 github 上の動きをみても LLC のほうが好ましい。

IDE も LLC 版は Java8 に上がっている。
ウェブサイトも LLC は https だし。

ソフトウェアは LLC を信頼したほうが良いと思われる。(最近 SRL の github が活発になってきた。stay, tuned)

回路図も微妙に違うような...

朗報! Two Arduinos Become One http://www.arduino.org/blog/two-arduinos-become-one

おや! LLC 版の Yún が変わった Arduino Yún LininoOS

2016年12月2日にウェブサイトが更新された模様。SRL と LLC 和解の成果か。
2014年10月以降に出荷された Yún は LininoOS だったと。(歴史改ざんしてる気がするwww)
おそらく(大人の事情で) LLC で Yún の出荷がとまった(Web から消えた)のが 2014年10月ごろか...
その後 LLC では Yún Shield なる製品が出荷されて LininoOS ではなく OpenWrt-Yun が載ってたはず。
この Yún Shield も(大人の事情で)出荷がとまった(Web から消えた)が、現在は出荷されている。技適とれてないので日本では触れない。
なので本サイトの以下↓の情報は古いです。(LEDE + Arduino-OS + Ciao のファーム作るか...)
差分を追っかけてみる

諸注意

Arduino Yun は Atmel ATmega32U4 と Atheros AR9331 の二つのマイコンがあり、それぞれソフトウェアが稼働する。さらに開発環境のコンピュータもあるので、以下の記事中のコード等がどの環境の話かを区別できるように ("Leonardo") ("OpenWrt") ("開発環境") を入れるようにした。明らかに区別できるものは注記はいれていない。

ATmega32U4 マイコン部をどう言うのがわかりやすいかを考えて、結局 Leonardo と呼ぶことにした。

検証機 ハードウェアは SRL 製。

ソフトウェアの情報は LLC に合わせている。

Arduino Yun の面白さ(逆に難しさ)はマイコン屋の知識と、UNIX屋・ネットワーク屋の知識と、Web屋の知識がすべて必要なところ。それぞれの専門家からみたら他方はブラックボックスに見えて理解の妨げになっているようだ。Arduino Yun の使い方・付き合い方は多方面から見てあげることが大切だ。

導入

電源

Uno では(ACアダプターからの)DC入力ジャック(5.5mm/2.1mm Center Plus | 7~12V) があったが Yun には無い。

  1. micro-USB から 5V 供給するのが推奨。
  2. (びみょうに斜めに付く) PoE モジュールをつければ Ethernet RJ45ジャックから給電も可。
  3. VIN pin に定電圧レギュレータの5Vをいれるのも可。

USB Serial

Yun は Arduino Leonardo(ATmega32U4)ベースに作られている。Uno のように USB 通信用のペリフェラル(ATmega16U2がUSBを受け持つ)をもっていない。そのかわりに ATmega32U4 は USB 制御器を内蔵している(Uno の ATmega328P にはその回路はない)。そこで大きな使い勝手の差がある。

micro-USB ケーブルには充電専用というのが紛れ込んでいるので要注意。

紐ほどくために Arduino Leonardo ガイドの日本語訳

Guide/ArduinoLeonardo – スイッチサイエンス

ハードウェア構成が違うので Leonardo とも微妙な差異があるが、ほぼ同様とはいえる。

OpenWrt WiFi 設定

工場出荷状態なら、WiFi AP モードで Yun (OpenWrt) が起動するので、開発環境からそのアクセスポイントに接続してごにょごにょ。SSID が WiFiの MACアドレスになっているので、もしフィルタリングをしてる場合はこれを使う。

ご参考 : 高木浩光@自宅の日記 - 無線LANのMACアドレス制限の無意味さがあまり理解されていない

初心者向け記事:

Arduino Yúnを使ってみよう (1) Yúnを設定する | スイッチサイエンス マガジン
Arduino Yúnを使ってみよう (2) YúnをPCから操作する | スイッチサイエンス マガジン
AWS IoTがリリースされました(Yúnを繋ぎました) | スイッチサイエンス マガジン
AWS IoTをArduino Yúnで使う(少し詳しく書いてみた) | スイッチサイエンス マガジン
LambdaからIoT経由でArduino Yúnへ(前編) | スイッチサイエンス マガジン
LambdaからIoT経由でArduino Yúnへ(後編) | スイッチサイエンス マガジン
Arduino YUNを使ってみる(1) - フィジカル・コンピューティング
Arduino YUNを使ってみる(2) - フィジカル・コンピューティング
Arduino YUNを使ってみる(3) - フィジカル・コンピューティング
Arduino YUNを使ってみる(4) - フィジカル・コンピューティング
Arduino YUNを使ってみる(5) - フィジカル・コンピューティング

メモ: 初期パスワードは arduino (ちなみに Linino の場合は doghunter)

注意: 開発環境が Windows の場合は Apple から Bonjour のドライバーをとってきてインストールしておく。

注意: WiFi ルーターが「アイソレーション」「ネットワーク分離機能」「プライバシーセパレータ」等の名前の端末間通信を拒否する設定になっていると同一ネットワークに有る機器は Yun (OpenWrt) に接続できない。WiFi ルーターの該当を機能を解除する事。

重要: TIMEZONE は正しく設定する事(Asia/Tokyo)。でないと技適的にまずいはず...

ネットワーク設定に失敗したら

AR9331 OpenWrt のシリアルコンソールを使って設定を修正する。

YunSerialTerminal

micro-USB を接続し Arduino IDE で

ファイル -> スケッチの例 -> Bridge -> YunSerialTerminal

このスケッチをコンパイルして Leonardo にアップロードする。これは、OpenWrt のコンソールを Serial1 経由で micro-USB シリアル (Serial) へつなげるプログラムである。

Arduino IDE の シリアルモニターでは使い勝手がわるいので、picocom 等で シリアルポートにつなげる。

この状態は UNIX 端末の通常のシリアルコンソールをつかっていることになる。つまりネットワーク設定こけたらシリアル端末つなげてホゲるというルーティーンw

(開発環境側で)

picocom -b 115200 /dev/ttyS4

# for Emacsian
picocom -b 115200 -e t /dev/ttyS4
(それぞれの開発環境でのお好きなシリアルターミナルソフトでそれぞれのシリアルポート名で。ボーレートは 115200 bps)

シリアルコンソールで OpenWrt に(ログインフェーズは無しで)接続して、

(OpenWrt側で)

/etc/config/arduino
/etc/config/wireless

を確認して修正する。平文で WiFi のパスワードが書かれているのでこのファイルの扱いは要注意。

もちろん uci でも WiFi パスワードは平文。
Arduino Yún(OpenWRTYun)の設定情報書き出しには注意 - XX-Prime's blog

細かな設定は LuCI で

WiFi の設定を解除して有線に変えるとか、PPPoE とかの詳細設定は LuCI とよばれる GUI で行う。

Arduino Webpanel にログインして、上部にある "CONFIGURE" ボタンを押して次のページに遷移し、そのページの上部にある、

advanced configuration panel (luci)

のリンクをクリックする。OpenWrt の LuCI で設定する。


Yun は WiFi ルータでよくつかわれている AR9331 を使用しており、かつ OpenWrt なので、WiFi ルータとしても十分つかえる。

OpenWrt-Yun のアップデート

Arduino LLC 純正システムイメージ: Other Software, ARDUINO YÚN LINUX OS OPENWRT-YÚN

Remember that updating the OpenWrt-Yun image will cause the loss of all files and configurations you previously saved on the flash memory of the Yún.

注意 : すべての設定やデータが消えます。(luci の backup / restore を使う方法もあり)

注意 : アップデート後、もういちどWiFiの設定を最初からやり直す事。

注意 : μSD カードや USB 装置は抜いておく事。

注意 : /tmp (tmpfs) に大きなファイルを置くので、空きメモリーが少ない場合は不要なプロセスを落とす事。

導入後最初にやったほうがよさそう。(私が購入した Yun はそのままでは opkg の整合性が合わなかった)

http://crossbar.io/iotcookbook/Arduino-Yun-Basic-Setup/
http://crossbar.io/iotcookbook/Arduino-Yun-Expanding-Disk-Space/
http://crossbar.io/iotcookbook/Arduino-Yun-System-Update/
http://crossbar.io/iotcookbook/Arduino-Yun-Prepare-Image/
step1.sh
crossbar.io ここがマニアックでいいかんじ。

安全のために YunSerialTerminal を使ったシリアルコンソールで作業する。(もちろん OpenWrt 側で wget するので Internet にはつながってことは前提)

(OpenWrt側で)

opkg update
opkg install unzip
### ファイルのバージョンは確認のこと
### https://www.arduino.cc/en/Main/Software
cd /tmp
wget http://downloads.arduino.cc/openwrtyun/1/YunSysupgradeImage_v1.5.3.zip
unzip YunSysupgradeImage_v1.5.3.zip
sysupgrade -v -n openwrt-ar71xx-generic-yun-16M-squashfs-sysupgrade.bin

いろいろ echo されるが無視して(キーを叩かず)待ち続けること。ひたすら待つと自動的にリブートする。

boot 時のコンソール出力(さまざまなログ)が落ち着いたところ(WiFi のログ wlan0: associated がでたところぐらい)でリターンキーを押すとプロンプトが出る。

心配 : OpenWrt-yun も opkg のパッケージもアップデートが遅い。すでにいろいろヤバい

ディスクの容量を増やす

必要なソフトウェアを導入したらすぐにディスクフルになるので、micro SD をつかってディスク容量を増やす。(この要因があるので Arduino Yun Mini は残念...)

http://crossbar.io/iotcookbook/Arduino-Yun-Expanding-Disk-Space/
を参考に
Overlayfs がポイント
Rootfs on External Storage (extroot)

Yun は 32GB までは対応している。できたら class 10 の micro SD カードを準備して挿入する。

Alcor Micro AU6350-MGL USB2.0 Hub-Reader Controller が AR9331 につながっており、これがμSDのインタフェースになっている。

(OpenWrt側で)

opkg update
opkg upgrade temboo
opkg install e2fsprogs mkdosfs fdisk rsync
umount /dev/sda1
### パーティション情報を壊す
dd if=/dev/zero of=/dev/sda bs=4096 count=1000
### FAT32 に 15G、ext4 に残り
(echo o; echo n; echo p; echo 1; echo; echo +15G; echo n; echo p; echo 2; echo; echo; echo t; echo 1; echo c; echo w) | fdisk /dev/sda
mkfs.vfat /dev/sda1
# mkfs.fat /dev/sda1
mkfs.ext4 /dev/sda2
mkdir -p /mnt/sda2
mount /dev/sda2 /mnt/sda2
rsync -a --exclude=/mnt/ --exclude=/www/sd /overlay/ /mnt/sda2/
umount /dev/sda2
rm -rf /mnt/sda2
### uci というのは OpenWrt の汎用設定インターフェースシステム
### https://wiki.openwrt.org/doc/uci
uci add fstab mount
uci set fstab.@mount[0].target=/overlay
uci set fstab.@mount[0].device=/dev/sda2
uci set fstab.@mount[0].fstype=ext4
uci set fstab.@mount[0].enabled=1
uci set fstab.@mount[0].enabled_fsck=0
uci set fstab.@mount[0].options=rw,sync,noatime,nodiratime
uci commit
reboot

ブートしたら、

(OpenWrt側で)

df -h

で増えた事を確認する。

root@Arduino:~# df -h
Filesystem                Size      Used Available Use% Mounted on
rootfs                   14.7G    380.6M     13.6G   3% /
/dev/root                 7.5M      7.5M         0 100% /rom
tmpfs                    29.8M    392.0K     29.5M   1% /tmp
tmpfs                   512.0K         0    512.0K   0% /dev
/dev/sda2                14.7G    380.6M     13.6G   3% /overlay
overlayfs:/overlay       14.7G    380.6M     13.6G   3% /
/dev/sda1                15.0G     18.6M     15.0G   0% /mnt/sda1

ディスク容量は必ず増やしてから OpenWrt の作業をすること。32GB が高価であれば 8GB class 10 でもよい。かならず増やすこと。

上記の micro-SD を取り出すには、

poweroff

shutdown したら micro-SD を取り出す。

"YUN RST" ボタンをおして再起動する。起動したら、

uci delete fstab.@mount[0]
uci commit

/etc/fstab の記述を消す必要あり。

RESET

Resetting the processors (AR9331, WiFi, and 32U4)
  1. OpenWrt が稼働する AR9331 をリスタートするには、いっぱい LED がある側の、アナログピンの横の "YÚN RST" を押す。
  2. AVR マイコン ATmega32U4 (Leonardo) をリスタートするには、イーサネットポートの横にある、"32U4 RST" を押す。
    1回だけなら通常のリセットになる。2回速く押す事で bootloader mode に入り LED 13 が赤く点灯し 8 秒待機した後、起動する。
    Reset to Bootloader
  3. WiFi ボードをリセットするには、USB-A ポートの横にある "WLAN RST" を押す。
  4. WiFi 設定を初期化するには、"WLAN RST" を 5 秒以上かつ 30 秒以下押し続ける。AR9331 がリスタートして 初期のWiFi設定モードになる。
  5. OpenWrt-Yun を工場出荷の状態(正確には最後に導入した OpenWrt-Yun)に戻すには、"WLAN RST"を 30 秒以上押し続ける。この場合すべての設定が初期化される。
    micro SD を使って Overlayfs で拡張している場合は micro SD を安全に抜いておく。
    /etc/config/fstab の 該当の config 'mount' セクションを削除して micro-SD のファイルシステムを umount し micro-SD カードを抜く。
  6. OpenWrt-Yun の root ログインパスワードを忘れた場合は、YunSerialTerminal をロードしてシリアルコンソールから変更する。

LED

ボードの刻印と意味が違うところがあるので要注意

  1. USB の刻印がある白色 LED は OpenWrt ブート完了時( rc.local 実行時) に点灯する。つまり AR9331 OpenWrt が正常に稼働したというサイン。
    AR9331 GPIO1 OpenWrt /sys/class/leds/ds:green:usb boot-complete-notify
  2. WLAN の刻印がある青色 LED は WiFi ボードに何等かの操作(動作確認・初期化・リセット)をしている際にブリンクする。通常は消灯。
    AR9331 GPIO0 OpenWrt /sys/class/leds/ds:green:wlan blink-start blink-stop
  3. ON の刻印がある緑色 LED は刻印通り通電しているサイン。
    接地
  4. WAN (私は未検証) 電源投入後しばらくオレンジ色に点灯し消灯。
    AR9331 GPIO17 OpenWrt
  5. L13 の刻印のある赤色 LED はおなじみの L つまり 13 ピン。
    ATmega32U4 PC7 (ICP3/CLKO/OC4A)
  6. TX の刻印のあるオレンジ色 LED は micro-USB のシリアル通信 TX。
    ATmega32U4 PD5 (~XCK/CTS) Caterina bootloader
  7. RX の刻印のあるオレンジ色 LED は micro-USB のシリアル通信 RX、回路は ハードウェア SPI の SS と接続されている。
    ATmega32U4 PB0 (~SS/PCINT0) Caterina bootloader

Yun 特有な開発

avrdude

USBシリアル経由でプログラムをアップロードするのにいろいろはまった。

Leonardo 側が割り込み禁止になっていれば USB シリアルは使えない。

また SLEEP のモードによっても USB シリアルは使えない。

データシートによると SLEEP_MODE_IDLE と SLEEP_MODE_ADC であれば USB 割り込みから復帰可能であり、割り込み可能の場合は IDE で USBシリアルがつかえる。
ATmega32U4 は USB の回路を内蔵していて Yun の micro-USB 端子に D+ D- VBUS (USB)GND が繋がっている。

スピードは極端におそいが、TCP/IP ネットワーク経由(AR9331 OpenWrt を AVR ライタとして使う)にしておくのが無難だとわかった。(SPI デバイスを使用する場合は問題あり)

Arduino-Makefile

avrdude のところでおかしくなる。

例の 1200bps でリセットするところでこける。

私の開発環境が Windows の Cygwin なので、新しく接続された USB デバイスを Cygwin 側からは認識しないという事情によるものだった。
あとは 上記と同様な理由で、割り込み禁止にしているか、SLEEP_MODE_PWR_DOWN 等では USB シリアルは使えない。TCP/IP ネットワーク経由(AR9331 OpenWrt を AVR ライタとして使う)で使う方法/パッチ探すことにする...

memo:

(開発環境側で)

scp sketch.hex root@arduino.local:/tmp/
ssh root@arduino.local 'kill-bridge'
### ssh root@arduino.local '/usr/bin/merge-sketch-with-bootloader.lua /tmp/sketch.hex'
ssh root@arduino.local '/usr/bin/run-avrdude /tmp/sketch.hex'
下手にやると文鎮になりそうなので要注意。もっと遊んでからこの実験をすることにしたので放置。

割り込み禁止 もしくは SLEEP_MODE_PWR_DOWN という状況で micro USB 経由で avrdude

IDE でコンパイルが終了するところで "32U4 RST" をダブルクリック(bootloader mode に)すると、タイミングが合えばプログラムを転送できる。

(SPI デバイスを接続している場合は、これのほうが便利かも)

2つのマイコン・3つの状態

How to improve reboot/reset stability

Arduino Yun は AVR ATmega32U4 と MIPS 24K 系の Atheros AR9331 の2つのマイコンを搭載している。

Uno も2つのマイコンを搭載しているが ATmega16U2 は USB通信をつかさどっている。(ATmega16U2 専用の ICSP 端子があるのでプログラミンは可能)

Yun の AR9331 は U-boot と呼ばれる汎用ブートローダを持ち、LLC 版では GNU/Linux の組み込み系ディストリビューションである OpenWrt-yun が起動する。Yun でのプログラムは Arduino 環境で開発するプログラム(スケッチ)、つまり Arduino Leonardo のプログラムと OpenWrt プログラムとの連携がポイントになる。連携は Bridge ライブラリを利用する。

2つのマイコンは以下の3つの状態を取りうる。

  1. Leonardo と OpenWrt が同時に起動する(電源投入時)場合。Leonardo が瞬時に立ち上がり、OpenWrt は init rc 等上がりきるまで20数秒かかる。
  2. Leonardo がリセットされた時(スケッチがアップロードされた・ボードの Leonardo リセットボタンを押した・OpenWrt から reset-mcu を実行した)、この場合は OpenWrt が稼働し続けている。
  3. OpenWrt がリブートされた時(reboot コマンドを実行した・OpenWrt リセットボタンを押した・OpenWrt をアップグレードした)、この場合は Leonardo は稼働し続けている。

Leonardo と OpenWrt の連携をする場合はこの3つの状態を意識してプログラムをしなければならない。

OpenWrt の boot 完了を待つ処理

Bridge は OpenWrt の起動直後(Serial1活性確認つまり OpenWrt のシリアルコンソール活性後・ブートシーケンスの最初の頃)、Leonardo 側からシリアルコンソールで OpenWrt にログインして run-bridge スクリプトを起動する。つまり、

  Bridge.begin();

は OpenWrt の起動確認後、run-bridge スクリプトを起動し処理を抜ける。つまり、OpenWrt のシリアルコンソールが使えるまで待つ。

もちろん OpenWrt がすでに稼働済みであるばあいは即座に run-bridge を起動して抜ける。

Bridge.cpp:

  // Wait for U-boot to finish startup
  do {
    dropAll();
    delay(1000);
  } while (stream.available() > 0);
void BridgeClass::dropAll() {
  while (stream.available() > 0) {
    stream.read();
  }
}
    // Bridge startup:
    // - If the bridge is not running starts it safely
    stream.print(CTRL_C);
    delay(250);
    stream.print(F("\n"));
    delay(250);
    stream.print(F("\n"));
    delay(500);
    // Wait for OpenWRT message
    // "Press enter to activate console"
    stream.print(F("run-bridge\n"));
    delay(500);
    dropAll();

/usr/bin/run-bridge:

python -u bridge.py

このスクリプトの処理を設定後、次の処理にわたす。

Bridge について詳しい記事:

Arduino YunのBridgeメモ

OpenWrt 側ソース:

https://github.com/arduino/YunBridge

Bridge は破棄することができなさそう。もし Leonardo が稼働中に、OpenWrt が再起動したばあい、bridge.py は起動しておらず、その条件下で再度 Leonardo で Bridge.begin() を呼んでも、private のフラグがセットされていて、bridge.py を呼び出すことはない。

Bridge.cpp:

void BridgeClass::begin() {
  if (started)
    return;
  started = true;
Bridge が動いていないことを検知したら、美しくはないが Leonardo を自らリセットするのがいまのところよさそう。
  asm volatile ("jmp 0");

OpenWrt の init script 完了を待つ処理

USB LED (明るい白色)が点灯する時点で OpenWrt が起動済み(rc.local 実行時)ということを利用して、

/etc/rc.local の boot-complete-notify 実行直前は brightness は 0 である。boot-complete-notify 実行後に 255 である。
白色 LED を消灯するために trigger に none を入力後も brightness は 255 である。
どうもバグと認識されたようで最新の OpenWrt では none を設定すると brightness は 0 になる。

(Leonardo側で)

/* Check OpenWrt USB White LED ON (after rc.local boot-complete-notify) */
boolean CheckOpenWrtUsbnLed(void) {
  Process yun_proc;
  String yun_str;
  char c;
  boolean ret = false;

  /* USB LED ON ? */
  yun_proc.begin("/bin/cat");
  yun_proc.addParameter("/sys/class/leds/ds:green:usb/brightness");
  yun_proc.run();
  while(yun_proc.available() > 0) {
    c = yun_proc.read();
    if(c != '\n') {
      yun_str+= c;
    }
  }
  if (yun_str == "255") {
    ret = true;
  }
  return ret;
}

この関数で /sys/class/leds/ds:green:usb/brightness の値を状態を監視。0 から 255 になったことを確認したら OpenWrt のブートの一連の処理完了とみなせる。

NTP 時刻同期完了確認

OpenWrt 起動直後は、ネットワークの設定処理が終わっていないことや、NTP で時刻同期がまだできていない状態で、Leonardo 側の処理が動く場合がある。

ちなみに OpenWrt 側のマイコンには RTC がなく、ブート直後は、時刻が大幅に違っている。(/etc ディレクトリにあるファイルの最新日付を boot 時に設定している)

上記の関数で OpenWrt のブートシーケンス完了確認後、NTP (BusyBox sysntpd) の同期を待つ(25秒ほどで同期する)処理を配置しておく。もちろん、OpenWrt 稼働済みの状態で Leonardo が起動する場合は待つ必要は無い。

Leonardo

I/O

D0/INT2, D1/INT3 は AR9331 との Serial1 用に接続されている。Yun で外部割り込みで使えるのは D2/INT1 と D3/INI0 とのこと。D7/INT4 は AR9331 の ハンドシェイク用(予定)なので使わない。

I2C(TWI)の SDA/SCL が Uno は A4/A5。Yun は D2/D3 。

Uno で使っていた INT1/INT0 の外部割り込みが使えない...
I2C使わないように、SPI に回路変えるか...
SPI で気象データセンサーなら
Adafruit BME280 I2C or SPI Temperature Humidity Pressure Sensor ID: 2652
5V対応
SparkFun Atmospheric Sensor Breakout - BME280 - SEN-13676
3.3Vのみ。5Vマシンならロジックレベルシフタが必要。
SPI でRTC なら
SparkFun DeadOn RTC Breakout - DS3234 - BOB-10160
ハードウェアSPI も UNO と異なる。UNO はICSP 端子と PIN 10, 11, 12 だが YUN は ICSP 端子のみだ。
Yun で ハードウェア SPI のために ICSP 端子に接続する場合は問題がある。network 経由の avrdude でエラーがでる。
Pin による割り込みを他の Pin で可能にする方法がある。
Leonardo - using I2C and external interrupts
Pin Change Interrupt library for the Arduino

Pin Change Interrupt

PinChangeInt の更新版である EnableInterrupt があった。

https://github.com/GreyGnome/EnableInterrupt

これによると Yun と同じ Leonardo の割り込みの拡張・変更は、

外部割り込み  : D0, D1, D2, D3, D7
Pin Change 割り込み : D8, D9, D10, D11, SCK, MOSI, MISO

ポートB の変更になる。

実際に Yun で試したみたところ、割り込みは検知できた。

enableInterrupt() で RISING を設定したが、たしかに 割り込みハンドラは RISING(LOW->HIGH) でのみ起動はした。
しかし AVR の SLEEP が RISING(LOW->HIGH) だけでなく FALLING(HIGH->LOW)でも解除された。
おそらく AVR ポートB の仕様によるものというか、Pin Change Interrupt という文字通りの挙動で、enableInterrupt ライブラリが割り込みハンドルを横取りしてソフト的に RISING, FALLING, CHANGE の制御をおこなっているのであろう。

EnableInterrupt に記述されている Leonardo の割り込みの種類

Pin     Interrupt Port 

 3      INT0      PD0      // External Interrupt (I2C SCL)
 2      INT1      PD1      // External Interrupt (I2C SDA)
 0      INT2      PD2      // External Interrupt (Serial1 RX)
 1      INT3      PD3      // External Interrupt (Serial1 TX)
 7      INT6      PE6      // External Interrupt (AR9331 handshake)
 8      PCINT4    PB4      // Pin Change Interrupt
 9      PCINT5    PB5      // Pin Change Interrupt
10      PCINT6    PB6      // Pin Change Interrupt
11      PCINT7    PB7      // Pin Change Interrupt
SCK/15  PCINT1    PB1      // Pin Change Interrupt
MOSI/16 PCINT2    PB2      // Pin Change Interrupt
MISO/14 PCINT3    PB3      // Pin Change Interrupt
ATmega32U4 DATA SHEET
ATmega32U4 データシート 日本語訳
Arduino のスリープと、Pin Change 割込 | FIRMLOGICS
(Arduino のスリープと、Pin Change 割込 - 私の二次記憶) : はてな版

PINOUT DIAGRAM

これはありがたい。

THE UNOFFICIAL ARDUINO PINOUT DIAGRAM 本家

SLEEP

Leonardo では sleep_bod_disable が未定義になる。

USB(micro-USB)つかうなら sleep mode は SLEEP_MODE_IDLE か SLEEP_MODE_ADC で。(USB制御回路の割り込みでスリープから復帰する)

Timer 2

Timer 2 がない。Uno にはない Timer 3, Timer 4がある

Console

ssh root@arduino.local 'telnet localhost 6571'
たぶん Uno で Serial ってかいてるところをすべて Console ってかいてやれば最初のハードルは越えられそう...

OpenWrt 側からの Console 接続待ち

  while(!Console);
OpenWrt 側から ポート 6571 に接続するまで待つための Leonardo 側プログラム処理。

注意: loop で待っているので OpenWrt 側の bridge.py が OpenWrt 側の CPU を食う。早い目に OpenWrt 側で yun console に繋げて、この loop を抜けるようにしてあげる事。

Process

なんと Leonardo 側から OpenWrt のコマンドを実行できる。

Arduino - Process
邪悪だ...;)
Arduino yunで放射線センサのデータをxivelyとM2Xにアップロードする - XX-Prime's blog
IFTTTを用いてArduinoからツイートする
https://github.com/itman83/ArduinoYun

YUN と SPI と ICSP と avrdude

Yun で ハードウェアSPI の構成をとる場合、ICSP 端子を使うのだが、ICSP 端子からデバイスに接続している場合、ネットワーク経由での avrdude でエラーがでる。

/usr/bin/run-avrdude /tmp/sketch.hex
avrdude: AVR device not responding
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

/usr/bin/run-avrdude: line 5: can't open /tmp/efuse: no such file

avrdude: AVR device not responding
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.


avrdude done.  Thank you.

ICSP 端子からデバイスの接続を抜くと avrdude は成功する。プログラムを送信後、再度デバイスを ICSP 端子に接続して reset-mcu するとよい。

私はマイコンのプログラムは通常 HALT/SLEEP で、処理は割り込み駆動で書くべきだとおもっているので YUN の場合 USB での avrdude は使わない・使えない。("32U4 RST" ダブルクリックの bootloader mode 作戦で使える)
https://www.arduino.cc/en/Main/ArduinoBoardYun

の Documentation -> Input and Output -> SPI によると、

SPI: on the ICSP header. These pins support SPI communication using the SPI library. Note that the SPI pins are not connected to any of the digital I/O pins as they are on the Uno, They are only available on the ICSP connector. This means that if you have a shield that uses SPI, but does NOT have a 6-pin ICSP connector that connects to the Yún's 6-pin ICSP header, the shield will not work. The SPI pins are also connected to the AR9331 gpio pins, where it has been implemented in software the SPI interface. This means that the ATMega32u4 and the AR9331 can also communicate using the SPI protocol.

AR9331 の GPIO と共有しているらしい。それを利用してまさしく ICSP でプログラムを書き込んでいる。ネットワーク経由でプログラムを書き込む(AR9331 OpenWrt を AVR ライタとして使う)場合は、ICSP 端子には何もつながないようにすること。

YUN と SPI と RX LED

SPI 構成時になぜか RX LED がオレンジ色で点灯しっぱなし。

回路図みると RX LED は ~SS につながってるっぽい。ハードウェア SPI 使う場合は点灯しっぱなしなのか?
調べると Caterina bootloader が micro-USB 通信時で TX LED, RX LED の制御をおこなっている。もし SPI 構成時に micro-USB データ転送がおこなわれたら RX LED は消灯する。SPI 構成時に micro-USB のデータ転送がなかった場合 RX LED は点灯のままになる。
Arduino Yun SPI on ICSP connector (try to connect to a isd 1760 shield)
SPI on Yun

SPI Library によると、

void SPIClass::begin()
{
  uint8_t sreg = SREG;
  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
  if (!initialized) {
    // Set SS to high so a connected chip will be "deselected" by default
    uint8_t port = digitalPinToPort(SS);
    uint8_t bit = digitalPinToBitMask(SS);
    volatile uint8_t *reg = portModeRegister(port);

    // if the SS pin is not already configured as an output
    // then set it high (to enable the internal pull-up resistor)
    if(!(*reg & bit)){
      digitalWrite(SS, HIGH);
    }

    // When the SS pin is set as OUTPUT, it can be used as
    // a general purpose output port (it doesn't influence
    // SPI operations).
    pinMode(SS, OUTPUT);

    // Warning: if the SS pin ever becomes a LOW INPUT then SPI
    // automatically switches to Slave, so the data direction of
    // the SS pin MUST be kept as OUTPUT.
    SPCR |= _BV(MSTR);
    SPCR |= _BV(SPE);

なので SPI 初期化のあとは、SS (PB0/~SS/PCINT0)は普通のデジタル出力ピンとしてつかえる。

(Leonardo側で)

SPI.begin();
digitalWrite(SS, HIGH);

で RX LED が付きっぱなしの条件でも RX LED は消灯することができる。

ちなみに、複数の SPI デバイスを使う場合は、SPI Library で初期化する前に、すべての SPI デバイスの CS を必ず HIGH にしておくこと。

/* Prepare for using multiple SPI devices */
pinMode(SPI1_CS, OUTPUT);
digitalWrite(SPI1_CS, HIGH);
pinMode(SPI2_CS, OUTPUT);
digitalWrite(SPI2_CS, HIGH);

/* Init SPI lib */
SPI.begin();

DS3234 の SQW と Alarm

Alarm ので割り込みのあとは Alarm flag clear しないと次の割り込みが来ない。

RTClib 改 DS3224 版を fork して clearAlarmFlag という関数つくった。

https://github.com/nxhack/rtclib
SQW の停止もすこし変更した。

OpenWrt

https://github.com/arduino/openwrt-yun
https://github.com/arduino/openwrt-packages-yun
https://github.com/arduino/YunBridge
Documenting the Yun - Code Snippets
unitn / YunTricks / wiki / Home — Bitbucket
Getting started with Arduino Yun and Autobahn


ふつうの PC UNIX とはいろいろ異なる。特に軽量化重視でいろんな設計がされている。

init rc

/etc/rc.d/:

K50dropbear
K90network
K95luci_fixtime
K98boot
K99umount
K99usd
S05defconfig
S05luci_fixtime
S09handle_wifi_reset
S10boot
S11sysctl
S11ubus
S18rename-wifi-if-access-point
S19firewall
S20fstab
S20network
S39usb
S48rngd
S49delete_uhttpd_cert
S49generate_new_gpg_key
S50cron
S50dropbear
S50uhttpd
S59luci_dhcp_migrate
S60dbus
S60dnsmasq
S61avahi-daemon
S93triggerhappy
S95done
S96led
S97watchdog
S98sysntpd
S99rngd-turn-off
S99usd

ボードのLED

/sys/class/leds:

ath9k-phy0
ds:green:usb
ds:green:wlan
brightness
device
max_brightness
subsystem
trigger
uevent

点灯と消灯:

(OpenWrt側で)

echo "default-on" > /sys/class/leds/ds\:green\:wlan/trigger
echo "none" > /sys/class/leds/ds\:green\:wlan/trigger

echo "default-on" > /sys/class/leds/ds\:green\:usb/trigger
echo "none" > /sys/class/leds/ds\:green\:usb/trigger

(OpenWrt側で)

echo "255" > /sys/class/leds/ds\:green\:wlan/brightness
echo "0" > /sys/class/leds/ds\:green\:wlan/brightness

echo "255" > /sys/class/leds/ds\:green\:usb/brightness
echo "0" > /sys/class/leds/ds\:green\:usb/brightness
brightness は文字通り明るさ。0 は消灯。1から255は点灯。実際 明るさをコントロールする回路(PWMとか)が組み込まれていない場合は 1 でも 255 でも点灯は点灯。
trigger が default-on で brightness が 0 の場合の意味は、電気はつけたが明るさを絞りきっているという意味で事実消灯。

まぶしい白色LED(usb)を消灯するスケッチ

(Leonardo側で)

/* Turn off OpenWrt usb led (White LED) */
void TurnOffUsbLed(void) {
  Process yun_proc;

  yun_proc.runShellCommand("echo none > /sys/class/leds/ds:green:usb/trigger");
}

カーネルモジュール

標準インストール済み:

ledtrig_timer 
ledtrig_default_on

opkg で提供されているのも:

kmod-ledtrig-default-on - 3.3.8-1 - Kernel module that allows LEDs to be initialised in the ON state.
kmod-ledtrig-gpio - 3.3.8-1 - Kernel module that allows LEDs to be controlled by gpio events.
kmod-ledtrig-heartbeat - 3.3.8-1 - LED Heartbeat Trigger
kmod-ledtrig-morse - 3.3.8-1 - Kernel module to show morse coded messages on LEDs.
kmod-ledtrig-netdev - 3.3.8-1 - Kernel module to drive LEDs based on network activity.
kmod-ledtrig-netfilter - 3.3.8-1 - Kernel module to flash LED when a particular packets passing through your machine.  For example to create an LED trigger for incoming SSH traffic: iptables -A INPUT -p tcp --dport 22 -j LED --led-trigger-id ssh --led-delay 1000 Then attach the new trigger to an LED on your system: echo netfilter-ssh > /sys/class/leds/<ledname>/trigger
kmod-ledtrig-timer - 3.3.8-1 - Kernel module that allows LEDs to be controlled by a programmable timer via sysfs.
kmod-ledtrig-usbdev - 3.3.8-1 - Kernel module to drive LEDs based on USB device presence/activity.
LED handling under Linux

起動後の LED の点減

USB LED (まぶしい白色) は /etc/rc.local の boot-complete-notify で常時点灯に設定される。

boot-complete-notify

WLAN LED (暗い青色) は WiFi モジュールの動作確認・初期化・リセット等の操作時にブリンクするようになっている。処理が終わったら消灯される。

wifi-live-or-reset
wifi-reset-button-released
blink-start
blink-stop

U-boot

http://www.denx.de/wiki/U-Boot

汎用ブートローダ。GPL。

BusyBox

http://busybox.net/downloads/BusyBox.html

GNU Coreutils 等を1つのプログラムファイルに固めたもの。コードの重複等のさまざまな無駄をはぶいてファイルサイズを少なくし、メモリー使用も少なく、起動を速くしたもの。組み込み系には嬉しい。

Dropbear SSH

https://matt.ucc.asn.au/dropbear/dropbear.html

SSH の軽量実装。OpenSSL を使っていない。zlib を省くことも可能。主な SSH の機能は装備されている。

openssh の ssh-keygen で作ったキーを使おうとしたら

dbclient: Exited: String too long

dropbear 用に変換する必要がある

opkg install dropbearconvert
dropbearconvert openssh dropbear id_dsa id_dsa.db

OpenWrt 版には SSHKeepAlive 対応のパッチがあたっているらしい

Dropbear Configuration

が、OpenWrt-yun のはまだかも...要確認

UCI

https://wiki.openwrt.org/doc/uci

UCI を調査...

uci show

OpenWrt 側から Leonardo のリセット

reset-mcu

yun scripts

openwrt-packages-yun/arduino/yun-scripts/files/usr/bin/
おもしろいのがいっぱい。
reset-to-factory-anyway
豪快
upgrade-all
これいいね

opkg

最初にこれだけは

opkg update
opkg list-upgradable
### なになあればそれを upgrade
### opkg upgrade temboo
opkg install ca-certificates
opkg install unzip
opkg install screen
opkg install logrotate
opkg install diffutils
opkg install dosfsck
# opkg install dosfstools
umount /dev/sdb1
dosfsck -t -a -w /dev/sdb1
# fsck.fat -t -a -w /dev/sda1
/sbin/block mount
mkdir -p -m 0755 /usr/local/var/lib/logrotate
crontab -e
### logrotal の記述かく
### 25 6 * * * /usr/sbin/logrotate -s /usr/local/var/lib/logrotate/status /etc/logrotate.conf > /dev/null 2>&1
### もしくは crontab ファイル
/etc/init.d/cron restart
Homepage V. 5.1 - Rotating lighhtpd logs on OpenWRT

注意:FAT32 で作ったファイルを ext4 に持って行くと x 属性がついてしまっている。logrotate.d 配下に置くファイルはこれが問題になった。

ps aux や w のたびに悲しい思いするのを避けるために

opkg update
opkg install procps --force-overwrite
root@Arduino:~# opkg install procps
Installing procps (3.2.8-1) to root...
Downloading http://downloads.arduino.cc/openwrtyun/1/packages/procps_3.2.8-1_ar71xx.ipk.
Collected errors:
 * check_data_file_clashes: Package procps wants to install file /usr/bin/free
        But that file is already provided by package  * busybox
 * check_data_file_clashes: Package procps wants to install file /usr/bin/pgrep
        But that file is already provided by package  * busybox
 * check_data_file_clashes: Package procps wants to install file /usr/bin/top
        But that file is already provided by package  * busybox
 * opkg_install_cmd: Cannot install package procps.

競合するらしいが、手癖のリズムを優先したいのでリスクを負って --force-overwrite した。

cd /bin
ln -s busybox free
ln -s busybox pgrep
ln -s busybox top

念のため競合したプログラムを復活しておく。

/root/.profile:

alias ps=/usr/bin/ps
alias top='TERM=xterm; export TERM;/usr/bin/top'

PATHを変えるのは影響がでかそうなので alias しておく。

emacs もどき...

opkg install coreutils-ls
opkg install mg

/root/.profile:

alias ls='/usr/bin/ls -F --color=auto'
alias ll='ls -alF --color=auto'
alias emacs="TERM=xterm; export TERM;PATH='/usr/bin:/usr/sbin:/bin:/sbin'; /usr/bin/mg"
(setq-default truncate-lines nil) の挙動がないので、長い行を改行しないことを意識すること。

syslog

syslogd が -C16 というオプション付きで起動されている。

/sbin/syslogd -C16

これは ログメッセージを RAM 上のリングバッファにストアするオプション。

logread

これで表示。もちろんリングバッファということで古いものは消えていく。

logread -f

で tail 表示

python beaver

ELK stack / Elastic Stack (Logstash + Elasticsearch + Kibana) に計測データを送るために、軽量 shipper beaver を導入。もちろん経路の安全性や接続先の厳密化のために SSH Tunneling を使用する。

本当は filebeat が良いのだが、Golang が MIPS に対応してない。

導入する前に micro-SD でディスク容量を増やしておく事。

opkg update
opkg install distribute
opkg install python-openssl
opkg install python-bzip2
easy_install pip
opkg install python-sqlite3
pip install beaver==36.2.0

SSH Tunneling の設定するため OpenWrt-Yun の 軽量 ssh である Dropbear SSH のための key 変換ツール。これで Dropbear 用に変換する。

opkg install dropbearconvert
/usr/bin/beaver -D -c /mnt/sda1/beaver/beaver.conf -P /mnt/sda1/beaver/beaver.pid

とりあえず動いたっぽい。

opkg install python-expat
pip install supervisor
Supervisor/initscripts
python supervisor startup script for OpenWrt-yun
OpenWrt 用作った。

いろいろ設定して意外とさっくり supervisord 配下で beaver が動いた。

ついでに、外部からの接続用 ssh tunnel も稼働中...

init script で ssh を起動する場合、 HOME が設定されていないので、ssh 関連のファイルの操作ができない。

HOME=/root
export HOME
init script に HOME を設定しておく事。

なんかいろいろやろうとすると supervisor も daemontools とおなじカホリを感じたな...

AR9331 メモリー

AR9331 の主メモリーは 64MB ということで、busybox や dropbear などを使って工夫している。 python supervisor と beaver を稼働させるともちろんメモリーは圧迫されるので無駄をなくす事が重要。 本当は OpenSSH client インストールして ssh tunnel のいろんなオプションつけたいのだけど我慢。ntpd も同様。

(最終的には、ExitOnForwardFailure=yes が必要だったので OpenSSH-client は入れた。)
root@Arduino:~# free
             total       used       free     shared    buffers     cached
Mem:         61116      56088       5028          0       5572      15992
-/+ buffers/cache:      34524      26592
Swap:            0          0          0

python supervisor と beaver を稼働させた状態。

ちなみに、AR9331 は MIPS 24Kc で FPU は無し。

メンテ用トンネル

おなじみのサーバサイドの sshd_config をホゲる

TCPKeepAlive no
ClientAliveInterval 15
ClientAliveCountMax 3

ssh tunnel サービス は python supervisord 配下で稼働させた。

shell script を supervisord で管理する場合、最終的なプログラム(この場合は ssh)は exec 付きで起動すること。でないと supervisord が ssh のプロセス追えない。

dropbear の client dbclient のオプションを調査したが、 -o は無視するようだ。

やっぱり -o ExitOnForwardFailure=yes をつかわないとマズイ状態になる。なので

opkg install openssh-client --force-overwrite

OpenSSH いれてテストしてみる。

init script

Init Scripts
#!/bin/sh /etc/rc.common
/etc/init.d/hoge enable

要調査...

ssh-agent

OpenWrt側に入ってテストすることがおおいので(開発環境側で)

eval `ssh-agent -s`
ssh-add ./.ssh/id_rsa
とかやっとく

OpenWrt 側は Dropbear SSH なので、

~/.ssh/authorized_keys

ではなく

/etc/dropbear/authorized_keys

自分の公開キーを書いておく。

Yun を 無線(Wi-Fi) 有線(Ethernet) コンバータとして使う

Wifi Extender or Repeater or Bridge Configuration
Routed Client with relayd (Pseudobridge)
http://ultimania.org/trac/yuna/wiki/linux/OpenWrt2
opkg update 
opkg install relayd
opkg install luci-proto-relay
/etc/init.d/relayd enable
/etc/init.d/relayd start

Luci 使えば簡単だった。

↓は LEDE 公式資料なので IF 名が Yun と違うので注意。(Yun は wan が eth1、lan が wifi)

wifirepeater_interfaces_lan.png
wifirepeater_newinterface.png
wifirepeater_relaybridge1.png
wifirepeater_relaybridge2.png
wifirepeater_firewall.png


↓を再度確認のこと。(Yun は wan が eth1) eth1 に ダミーの IP を振る。

config interface 'wan'
        option ifname 'eth1'
        option proto 'static'
        option ipaddr '192.168.2.1'
        option netmask '255.255.255.0'
        
config interface 'repeater_bridge'
        option proto 'relay'
        list network 'lan'
        list network 'wan'

最後に relayd を restart

/etc/init.d/relayd restart

relayd の '-I' オプションは ARP cache を頻繁に行うようで気持ち悪い '-i' に変えてみた。が、動かなかった。'-I' に戻した。

最終的に ARP storm 問題が気になったので、いろいろ試したが解決せず、relayd を使わずに、静的な bridge 構成にした。

bridge しているインターフェースには proxy_arp を有効にすること。

Security

ArduWorm: A Malware for Your Arduino Yun
あーーー出てしまった...
ATmega32u4に侵入して、bridge でお好きに的...

Arduino Yun の OpenWrt と AVR の脆弱性(要 Flash Plugin):

TFM - Arduino Yun - Security IoT
Linux environment
・ROOT as default user:
  No local access control.
・Vulnerable components (Kali -> Nmap,Nessus):
  Dropbeard ssh 2011.54 -> DoS, remote execution...
  BusyBox v1.19.4 -> execute arbitrary commands...
  Kernel v3.3.8 -> DoS, gain privileges...
・Critical paths:
  /var/hosts -> pharming attack
  /etc/opkg -> fake repository (SSLsniff)
  /usr/bin/kill-bridge -> DoS, own malicious bridge
  /rom/ -> persistence
・No integrity file checks on boot.
・No redirection to 443 (https).
・Remote insecure configuration:
  Deauthentication attack to create new free
  hotspot, capturing WPA/WPA2 handshakes...

Arduino environment:
・Device sensors no authenticated.
・No memory controls (Heap Overflow & Stack Overflow)

Arduino の性質上しかたのないものもあるが、ネットワークからの侵入や使用不能攻撃はさけたい。

Compromised firmware:

Are your devices secure? Firmware hacking | Fabytes.com

Update ヲタクとして作業中: OpenWrt for Arduino Yun Security Upgrade

Arduino Yún LininoOS 差分

  • Arduino LLC 版 Arduino IDE で「ライブラリを管理...」から MCU 側の Ciao Library がインストールできるようになっていた。
  • Bridge Library か Ciao Library かは選択可能のように記述されている。(どちらか推奨があるわけではないみたい)
  • luci-app-arduino-webpanel (Linino 版) と Arduino-OS (arduinoos) かはこれも様子見っぽい。Arduino-OS は野心的なので安定するまでは様子見したほうがよさげ。
  • LininoIO はまだ水面下っぽい。(MCUIO driver 系) コンセプトは素晴らしいが、vanilla kernel に取り込まれる勢いで OpenWrt / LEDE に入らないと将来はあやしい。
  • 公式版 LininoOS (LininoIO 版) は Barrier Breaker(14.07) ベース。 (/etc/linino_version には attitude_adjustment とあるが)(あかん..)
  • Chaos Calmer(15.05) ベースの LininoOS もあることはある。

link

Documenting the Yún:

http://codesnippets.altervista.org/documentation/yun/index.html

ibuyopenwrt:

http://www.ibuyopenwrt.com/index.php

Filebeat を動かすための mips Golang 情報:

Golang on OpenWrt · Akagi201

Yun 濃い議論:

Is The Arduino Yun Open Hardware? | Hackaday

linux USB RTC:

USB Real Time Clock (USBRTC)

ToDo メモ

秋月 006P安定化電源モジュールキット
電流足りないね。