先日ルネサスさんのmrubyを使ってGR-CITRUSでIoTデバイスを扱うというワークショップに参加させてもらったところ、MacBookProおよび(El capitan以上?)macOSにてハマるポイントがあったのでクイックハックで逃げたので、雑なスクリプト付きでメモ。
2016年11月30日現在のファームウェア(WAKAYAMA.RB Board Ver.CITRUS-2.19(2016/11/19)f3(256KB), mruby 1.2.0)を基にした情報なので、将来的には解決されると思います。
- 2016.12.6 追記: Rubic0.9.2で問題(512バイト分しか実行されない)は解消された模様。しかし強引なリトライ機能が便利なので、そのままスクリプトを使い続けるワタクシなのであった...
環境および前提
- GR-CITRUS (2.19)
- MacBookPro(late 2013)
- macOS Sierra
- Rubic 0.9
ハマったポイント
- MBPのUSBポートによってGR-CITRUSを認識しない
- 結果として左側ポートが使え、右側は使えない。他の参加者のMBPはLate2013以外もあったんじゃないかとおもうが、同様のばらつきがあった。使用電流に差があるのではとの意見もあった(未検証)
- Rubic上での開発ということだったが15行程度のスクリプトがビルド後転送できない(ビルドはできている)。10行付近であれば問題なく動作するし、同一スクリプトをWindows上のRubicで試すと問題がない。
- ターミナル上でmrbcを直接実行してできたmrubyの中間ファイル(.rb)をCoolTermで転送すると問題なく動く。が、いちいちコマンドでmrbcしたあと、バイト数をカウントして、ファームウェア上のアップローダでXコマンドを用いて転送しないといけない。面倒すぎる
応急策
mrubyの中間ファイル生成したあと、バイト数を数えて、自動で転送するスクリプトをrubyで書いた。
rubyでバイト数カウントしてもいいのにwcを呼び出しているのは、元がシェルスクリプトだったりする。
下記スクリプトを chmod +x しておき、引数にスクリプトファイルをあたえる。
スクリプト自体はEmacsでもVimでもお好みのものを使えばいいので、CrioneやRubicで編集するよりも楽だったりした(個人の感想です)
chmod +x mt.rb
% ./mt.rb i2c_lcd82.rb
>¥r¥n>>>>¥r¥nX main 2056
Wait for upload
X main 2056¥r¥n>>>>>>>>>>¥r¥nX main 2056
Wait for upload
.
.
.
上記のようなかんじでターミナル上で実行します。
内部でSerialPortを読んでるので、事前に
% sudo gem i serialport
...とかなんとか準備しておきましょう。
mt.rb
# !/usr/local/bin/ruby
# coding: utf-8
=begin
make and transfer .mrb file
mrbc hoge.rb
wc -w < hoge.mrb
したあと、SerialPort経由でファイルを送り込み
ターミナルモードに移行
=end
require 'serialport'
port = "/dev/tty.usbmodem1_1"
bps = 9600
send_script_name = "main"
sending_timeout = 10 #sec
script_file = ARGV.shift
mrb_file = script_file.split(".").first + ".mrb"
`mrbc #{script_file}`
size = open("|wc -c <#{mrb_file}").readlines.join.chomp.strip.to_i
sp = SerialPort.new(port,bps,8,1,SerialPort::NONE)
$wait4upload = true
$buf = ""
Thread.new{ #Waiting xx xx を受信するまではアップロードまちで、受信内容を表示
loop do
line = sp.getc
$wait4upload = false if $buf =~ /Wait/
$buf += line
$buf == "" if line == "¥n"
print line
end
}
#
# sp.print "L¥r¥n"
sp.write "¥r¥n"
sleep 4
#
# Transfer .mrb file (Xコマンド送信)
#
retry_count = 0
begin
first_send_time = Time.now
cmd = "¥r¥nX #{send_script_name} #{size}"
STDERR.puts cmd
sp.write "X #{send_script_name} #{size}"
sp.write "¥r¥n"
#雑な待ち受け
STDERR.puts "Wait for upload"
while $wait4upload
raise "Time Out " if Time.now-first_send_time >= sending_timeout
end
STDERR.puts
rescue
if retry_count <= 2
retry_count += 1
retry
else
STDERR.puts "timeout error;_;"
exit
end
end
STDERR.puts " ** sending #{mrb_file} : #{size} bytes ** "
sleep 5
open(mrb_file,"rb") do |io|
io.each_byte do |b|
sp.putc b
end
end
sp.write "¥r¥n"
#
# そのままターミナルモードに移行(^Cでとまる)
#
loop do
line = gets
sp.write line
end
sp.close