0

IRKitのブートローダーを破壊したので直した

ファームウェアを改造していたら、ブートローダーを壊した。
その結果、新しいファームウェアを書き込めなくなり、文鎮と化した。
AVRライターかArduinoがあれば直せる。

壊した原因

プログラムが28672byteを超えたため、Arduino互換機であるIRKitのブートローダー領域を上書きした。Arduinoはブートローダーと実行プログラムが同じプログラムメモリ上に共存しているのだ。
普通のArduino IDEを使っていれば書き込み前にサイズチェックして、こういう事にはならないのだが、inoだと考慮てくれないらしい。

githubでissueを立てたら助けてもらえた。


28672 byte以上書き込むとbootloader領域破壊する

書き込む前に.hexのサイズをチェックする
% /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-size -B .build/irkit/firmware.hex | tail -n 1 | cut -b 11-15
Arduino IDEの中にあるavr-sizeを使う。


直し方


3手必要

  1. IRKitにArduinoのブートローダーを書き込む
  2. IRKitにEEPROMを初期化するツールを書き込む
  3. IRkitのファームウェアを書き込む

前提としてIRKitのファームウェアを改造してセンサー読めるようにするに書いた、inoのインストールやboards.txtへパッチを当てる、などの作業が必要。
また、IRKitの基板上のAVRマイコンに書き込む「AVRライター」も必要。

1. IRKitにArduinoのbootloaderを書き込む


Arduino IDEのバージョンは1.0.5(現在の最新版)

基盤を取り出す


ケース背面のネジを4つ外せば取り出せる。
AVRライターを接続するためのピンヘッダ(オス)を付けた。ケースの蓋を閉めるためにピンヘッダのハンダ付けした側を少し削った。

IRKit

AVRライターを作る


純正のライターが今家に無いので、Arduino UNOをAVR書き込み器にした。
純正のSTK500やAVR-ISP、あるいはusbaspを持ってるなら必要なし。

Arduino – ArduinoISPを参考にした。

  • [ファイル]→[スケッチの例]→[ArduinoISP]

を適当なArduinoに書き込むだけ。


これでSTK500と同等のISPライターになる。
In System Programmingライター、つまり回路からターゲットCPUを取り出さずにプログラムを書き込む事ができる。

うまく書き込めない場合がある

このままライターとして使ってもうまく動かなかった。
"avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14"
というエラーがでた。
Arduino UNOだからだろうか?他のArduinoだと大丈夫かもしれない。


のパッチをArdunoISPに当てる。empty_reply()を1回だけしか送らないようにする。
-
+int initSent=0;
int error=0;
int pmode=0;
// address for reading and writing, set by 'U' command
@@ -399,7 +399,8 @@
uint8_t ch = getch();
switch (ch) {
case '0': // signon
- empty_reply();
+ if(! initSent) empty_reply();
+ initSent = 1;
break;
case '1':
if (getch() == CRC_EOP) {
これをライター用Arduinoに書き込み直した。


IRKitとAVRライターを接続


IRKitの回路図を見ると、基板上のICPSコネクタにMISO/MOSI/SCK/RESET/5V/GNDの6ピンがある。これは上から見た図。

ICSPコネクタ
Arduino – ArduinoISPを参考に、オス-メスのジャンパワイヤ

  • Arduinoのピン13 → IRKitのSCK
  • ピン12 → MISO
  • ピン11 → MOSI
  • ピン10 → RESET
  • GND → GND
  • VCC → 5V
と接続する。

IRKit


ブートローダーを書き込む

  • [ツール]→[マイコンボード]→[IRKit]
  • [ツール]→[書込装置]→[Arduino as ISP]
  • [ツール]→[ブートローダを書き込む]

で「ブートローダの書き込みが完了しました。」と出ればok。
書き込み中はArduinoのRXとTXのLEDが点滅する。



2. IRKitにEEPROMを初期化するツールを書き込む

このままファームウェアを書き込んでも、IRKitがWiFiに接続できない。
ブートローダの書き込みにより、EEPROMが初期化されてしまっている為。(これはArduinoISPの設定でなんとかできるかもしれない)

EEPROMにはiOSアプリで設定した接続先のWiFiアクセスポイントの情報だけでなく、IRKit本体の設定用アドホックWiFiアクセスポイントの情報や、赤外線データの解析用のデータ構造も含まれている。

EEPROM初期化ツールをビルドしてIRKitに書き込む

前提としてIRKitのファームウェアを改造してセンサー読めるようにするに書いたinoのインストールやboards.txtへパッチを当てる、などの作業が必要。

IRKitのリポジトリからファームウェアやEEPROM初期化ツールのソースコードを持ってくる

% git clone git@github.com:irkit/device.git
% cd device/firmware/t/initialize-eeprom
% ino build -m irkit
% ino upload -m irkit

電源入れてすぐuploadすると書き込める。

設定用のアドホックWiFi APのパスワードはfirmware/t/initialize-eeprom/src/initialize.inoのsaveLimitedAPPassword関数で指定されている。

フルカラーLEDが赤→青に変わるとEEPROMの設定は終了。


3. IRKitにファームウェアを書き込む

IRKitのリポジトリからファームウェアをビルドする

% cd device/firmware
% ino build -m irkit
% ino upload -m irkit

なおmasterブランチが動かなければ
% git tag
% git checkout v1.3.5
などして安定版のファームウェアを書き込むと良い。


これで出荷時状態に戻る(パスワードはsaveLimitedAPPassword関数で指定したものだが)
iOSアプリで自宅のWiFiに接続する設定をして完了。

0

IRKitのファームウェアを改造してセンサー読めるようにする

読めるようにソフトウェアは改造してみたけど、肝心のセンサー自体はまだ何もつないでない。

IRKitはArduino派生のハードウェアなので、ファームウェアの改造もできる。
ファームウェアに関しては特にドキュメント読まなかった(というか何も無かった)けど、Arduinoの作法に従ってやればさくさくといじれた。プラットフォームは偉大。

とりあえずGET /messagesすると赤外線データだけでなくADコンバータ0〜5を読んでJSONに混ぜて返すようにできた

freqの次のsensorの配列がそれ。



Macでやる。多分Linuxでもできる。Windowsでは使ってるツール(ino)が動かなくて無理な気がする。


ソースをgithubからclone

https://github.com/irkit/device/wiki

% git clone git@github.com:irkit/device.git
% cd device

firmwareディレクトリ以下がソレ。

なお今いじってるリビジョンはMar 18 16:03:26 の 992a4a58b4d73d213f4083c285c8d7bac39533b3

なんか動かなくなったら
% git checkout v1.3.5
して安定版でビルドして書き込めば治せると思う。多分。


inoとは

ビルドとファームウェアの書き込みにはinoを使う。そういえば以前紹介してた。
ino使うとCUIでArduinoをビルドできて便利
inoはArduino.appを参照して使うpythonスクリプトなのでArduino.appもインストールしておく


update boards.txt

inoはboards.txtを読んでビルドや書き込み時の設定とするので、boards.txtにirkitを追加する。

それぞれ以下にある

Mac
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/boards.txt

Ubuntu
/usr/share/arduino/hardware/arduino/boards.txt

% patch -u /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/boards.txt < firmware/boards.txt.patch

irkitが使えるようになってるかチェック
% ino list-models


build


firmware/build.shを参考にした。しかし中でなんかrmしてたり、~/src/ino/bin/inoを使っていたりとハードコーディングしていたのでbuild.shを使わず手動でやった。
% cd firmware
% VERSION=`git describe --tags --long | sed -e "s/^v//" | sed -e "s/\-/./g"`
% sed -e "s/__VERSION__/$VERSION/" src/IRKit/version.template > src/IRKit/version.c
% ino build -m irkit
これでうまくいけばfirmware.hexができる。


upload hex

IRKitをMacにUSB接続してすぐ書き込む。
Arduinoは電源入ってから数秒間だけファームウェア書き込みを受け付ける為。
% ino upload -m irkit

※注意:ブートローダー破壊する可能性あり(追記)

28672 byte以上書き込むとbootloader領域破壊するので、書き込み前にhexのサイズを確認するべき。詳しくは→IRKitのブートローダーを破壊したので直した

serial monitor

なおシリアルモニタで見るとIRKitがDNSをlookupしたり色々通信しているのが見れる。
% ino serial
ctrl+a ctrl+xで終了。


ファームウェア改造


return analog sensor values on HTTP-GET /messages · 8a89128 · shokai/irkit-device


firmware/src/IRKit/IRKitHTTPHandler.cpp がHTTPのハンドラなので、
static int8_t on_get_messages_request関数にanalogReadを追加するなどした。
     gs.write("{\"format\":\"raw\",\"freq\":"); // format fixed to "raw" for now
gs.write(IrCtrl.freq);
+
+ gs.write(",\"sensor\":[");
+ for(char i = 0; i < 6; i++){
+ gs.write((uint8_t) analogRead(i));
+ if(i < 5) gs.write(",");
+ }
+ gs.write("]");
+
gs.write(",\"data\":[");
for (uint16_t i=0; i gs.write( IR_get() );

gs.write関数はGSwifi.cppに書かれている。

0

irkitコマンドで家の外からIRKitを操作する

前:赤外線学習リモコンIRKitのrubygemを作った


irkit gemに付属のirkitコマンドは、Internet APIも使えるので家の外からIRKitを操作できます。
解説しておく。

インストール

% gem install irkit
% irkit --help

デバイスをirkitコマンドに登録する

最初のこの設定だけはIRKitと同じLANの中にいなければならない。

% irkit -device:add デバイス名

なお2つ以上IRKitを持っている場合は、-addressでIPアドレスを指定すればそれぞれ保存できる。
% irkit -device:add デバイス名 -address 192.168.1.123

登録されているか確認

デバイスリストと赤外線データのリストが見れる。LAN内のIRKitもbonjourで探す。
% irkit -list

なおこのデータはホームディレクトリ直下にjson形式で保存されている。
Ruby使ってるならirkit gemをrequireすればこのように取り出せる。普通学習は1回しかしなくて、発射ばかりするはずなので、学習とデータ管理はirkitコマンドに任せてもいいと思う。
require 'irkit'

IRKit::App::Data["IR"] ## 赤外線データ
IRKit::App::Data["Device"] ## デバイスデータ
もちろんRuby以外の言語でも、ホームディレクトリ下の.irkit.jsonを直接読める。


外に出る

ここからはIRKitを家に置いて、外にでても操作できる。

赤外線を学習する

% irkit -get 赤外線データ名 -device デバイス名


赤外線を発射する

% irkit -post 赤外線データ名 -device デバイス名


おわり。

1

赤外線学習リモコンIRKitのrubygemを作った

IRKitはよく「iOSから操作できる赤外線リモコン」と説明されるけど、そのAPIはHTTPなのでiOS以外からももちろん使えます。
というわけでRubyから使いやすいようにした。

ソースコードはgithubにある。不具合等はissuetwitterにお願いします。

irkitコマンドという便利ツールも入れておいた。
bonjourでLAN内のIRKitを発見する機能や、赤外線データのgetとpost(と保存)、家のLANの外からIRKitを操作するInternet API関連が実装されているので
プログラムを書かなくてもirkit gemをインストールすればすぐIRKitが使える。


なんでこういうツールが付いているかというと、デバイス系はコマンド一発で全部実行できるテストコードが書きにくい部分がかなりあって、しょうがないから各機能をテストしやすい実行可能コマンドを作るぐらいしかない。

IRKit


先週買った。うちのエアコンの赤外線はデータが長くて、既存の学習リモコンで学習できない事が多いんだけどIRKitだとokだった。
置き場所もカーテンレールの上に適当に置いてるだけなんだけど、エアコンの赤外線受光部は死角のはずなのに壁で反射してるのかちゃんと届いてる。よくできてると思う。


インストール

https://rubygems.org/gems/irkit
実行にはRuby2.0.0以上が必要。1.8.7は非サポート。(1.9.3でももしかしたら動くかもしれない)
% gem install irkit

なおubuntuやdebianでは事前にavahiをインストールしておく必要がある。これはLAN内のIRKitを見つけるのにbonjourを使っている為。
% sudo apt-get install libavahi-compat-libdnssd-dev

使い方


https://github.com/shokai/ruby-irkit#usageに書いた。サンプルコードもある。

BonjourでLAN内のIRKitを見つけて、赤外線が読み書きできる。
require 'irkit'

irkit = IRKit::Device.find.first
ir_data = irkit.get_messages

irkit.post_messages ir_data

また、Internet APIというプロキシを使うとLAN外からも操作できるんだけど、そのためのclientkeyやdeviceid等の発行もできる。

くわしくはgithubのREADMEとサンプルコード見てほしい。


irkitコマンド

gemをインストールすると実行可能コマンドも付いてくる。
普通のHTTP APIとInternet API両方とも使える。
コマンドからリモコン操作できるので、crontabで朝あらかじめ暖房をつけるとかできる。
エアコンのリモコン探すよりCUI使ったほうが速いので、shellの履歴から「暖房」で検索して「irkit -post 居間エアコンOFF」を探してenter押せば暖房が消せる。

% irkit --help
% irkit --get tv_on # tv_onという名前を付けて赤外線データを保存
% irkit --post tv_on # tv_onを赤外線発射
% irkit --list # デバイスやデータのリストを見る
% irkit --post tv_on --address 192.168.0.123 # IPアドレスを指定してtv_on赤外線発射
% irkit --device:add myhouse # myhouseという名前でInternet APIのclientkey等を保存
% irkit --device myhouse --post tv_on # 自宅のIRKitをLAN外からtv_on発射