MixJuice をサーバー化して paprika ロボットを動かす

1. はじめに

IchigoJam などの シリアル通信機器から利用できる ネットワークボード MixJuice ですが、 HTTPクライアント機能に加え、HTTPサーバ機能にも対応してみました。(現状はベータ版。)

MixJuice にPOSTでデータを送信するとシリアル通信のTXDに転送されるようになりました。

下記よりダウンロードしてファームウエアを書き換えてお試しいただけます。
http://mixjuice.shizentai.jp/MixJuice.1.3b1.zip

2. 試し方

今回追加したコマンドは下記です。

SERV START:
HTTPサーバの起動。(デフォルトポート: 80, 追加のパラメータで変更可)

SERV STOP:
HTTPサーバの停止。

SERV NAME ****:
mDNS名の設定。(デフォルト値: “mixjuice”, ****.local の ****部分を指定)

IchogoJam BASIC の場合、下記のようなプログラムでHTTPサーバが起動します。

10 ?"MJ APC ******** ********"
20 ?"MJ SERV START"

データの送信先となる MixJuice の IPアドレス はDHCPで自動的に割り当てられますが、4. MixJuice の IPアドレスの調べ方 を参考にご確認ください。
※ macOS や iOS、Windows 10(1809以降) を使っている場合、mixjuice.local 等のDNS名でアクセスできる場合があります。

データ送信を試すには、MixJuice と同じLANに属するパソコンで下記のようなコマンドを発行します。

macOS/Linux の端末から(LEDをONにする、文字列を送信する)

$ curl -X POST -d payload=LED1%0A http://[MixJuiceのIPアドレス]
$ curl -X POST -d "payload='Hello,World!%0A" http://[MixJuiceのIPアドレス]

Windows のPowerShellから(LEDをONにする、文字列を送信する)

> Invoke-RestMethod -Method POST -Body payload=LED1%0A -Uri http://[MixJuiceのIPアドレス]
> Invoke-RestMethod -Method POST -Body "payload='Hello,World!%0A" -Uri http://[MixJuiceのIPアドレス]

3. サンプルアプリケーション

paprika ロボットを動作させるサンプルアプリケーションはこちらです。
http://mixjuice.shizentai.jp/webapps/1.3b1_robo_c/

MixJuice URL: に http://[MixJuiceのIPアドレス] を入力した状態で矢印のボタンなどをタップ/クリックすると、ロボットを制御するOUTコマンドがIchigoJamに送られます。
※ macOS/iOSのSafari や Windows 10(1809以降)など、mDNSに対応した動作環境では mixjuice.local 等のDNS名が利用できる場合があります。

動作環境ごとのmDNS対応状況(筆者確認分)
macOS (10.12) / Safari
macOS (10.12) / Chrome×
macOS (10.12) / Firefox
Windows 10 (1809) / Edge
Windows 10 (1809) / Chrome
Windows 10 (1809) / Firefox
Windows 10 (1803) / Edge×
Windows 10 (1803) / Chrome×
Windows 10 (1803) / Firefox×
iOS (8.1.2) / Safari
Android (8.1) / Chrome×

4. MixJuice の IPアドレスの調べ方

I. 接続時に画面で確認する(IchigoJamなど)

MixJuice は APCコマンドの成功時に自機に割り当てられたIPアドレスを報告するので、 IchigoJam の画面などで確認できます。
割り当てられるIPアドレスは起動毎に変わる可能性がありますが、一般的に一定時間内は同じ機材(MACアドレス)には同じIPアドレスが割り当てられることが多いため、ロボット等に載せる前にIchigoJam の画面で確認しておくことができます。

II. mDNSを使って確認する(macOS/Windowsの一部のバージョン)

MixJuice は mDNSに対応しているため、同じく対応している macOS や iOS、Windows 10(1809以降) からはDNS名でアクセスすることができます。
また、DNS名でのアクセスがおそい場合は、下記のコマンドでDNS名からIPアドレスを確認してIPアドレスでアクセスしてもよいでしょう。

macOS の ターミナル から

$ dns-sd -G v4 mixjuice.local

Windows 10(1809以降) の PowerShell から

> Resolve-DnsName mixjuice.local

III. ARP を使って確認する

パソコン等は自機が属するLAN内の機器のMACアドレスとIPアドレスの組み合わせ表(ARPテーブル)を 管理しているので、ARP関連のコマンドを使って確認できます。
MixJuice の MACアドレスは MACコマンドで確認できます。

?"MJ MAC"

ARPテーブルには最近通信した機器の情報のみ保持されるため、事前にマルチキャストでpingを打つなどの準備が必要になりますが、下記が参考になるでしょう。(上級者向け)
http://d.hatena.ne.jp/nattou_curry_2/20090906/1252203651

5. まとめと課題

  • MixJuice に HTTPサーバ機能を追加したのでロボットの操作などに使えるようになりました。
  • 現状、IPアドレスを調べるのが少し大変ですが、環境は改善されてきています。
  • IPアドレスを調べるツールを探すか作りたい。
  • mDNSやARPについてもっと詳しくなりたい。
  • パソコン: 最新の環境に限れば、Scratch 対応できそう。
  • スマホ/タブレット: iOSとWindowsに限れば、Scratch 対応できそう。

シリアル通信とブラウザJavaScriptをブリッジする IchigoLink

この記事は、IchigoJam Advent Calendar 2018 8日目の記事です。

1. はじめに

IchigoLink は Scratch 3.0 と IchigoJam を連携させるために開発している、
シリアル通信とブラウザJavaScriptのブリッジです。

Windows, Mac, Linux でコマンドラインアプリケーションとして動作し、
WebSocket を使って ローカルのシリアルポート と ブラウザのJavaScriptをつなぎます。
(ちなみに、micro:bit は同様のツールの BLE版を提供しています。)

本来は Scratch連携用 のツールですが、それ以外にも面白いことができます。

2. 何ができるのか

下記の動画にあるような IchigoJamと連携する作品を JavaScript と HTML だけで作成できます。

IchigoJam  のボタン操作でWebページを変化させる

IchigoJam から取得したアナログ値で Webページを変化させる

WebページからIchigoJam を操作する

3. [使い方] 準備するもの

  • パソコン
  • IchigoJam
  • シリアル通信に必要なデバイス(USBシリアル変換アダプタなど)
  • IchigoJamで使いたいデバイス(LED、ボタン、可変抵抗、各種センサー、各種モーターなど)

4. [使い方] ダウンロードから起動まで

開発中ということで仮の場所になりますが、下記からダウンロードできます。
http://shizentai.jp/ichigolink/
IchigoLink は下記からダウンロードできます。
http://ichigolink.shizentai.jp/downloads.html

zip ファイルを解凍すると下記のような中身になっているので、コマンドプロンプトやターミナルを立ち上げて、このディレクトリに移動します。

パソコンとシリアル通信デバイス、IchigoJamを接続します。
参考: イチゴジャム レシピ — 周辺機器 パソコンと接続

下記のコマンドをたたきます。

Windows の場合

> ichigo-link [シリアルデバイス名]

Mac/Linux の場合

$ ./ichigo-link [シリアルデバイス名]

シリアルデバイス名は Windows の場合はCOM3やCOM4、Linux の場合は /dev/ttyUSB0 などになることが多いようです。
参考: IchigoLink: Find serial port

コマンドプロンプトやターミナルが上のような表示になり、
ブラウザで、 http://localhost:30110 を表示したときに下記のような画面になれば起動成功です。箇条書き程度ですが、仕様をまとめてあるので参考にしてください。

また、このページが ichigo-link-www フォルダの index.html に対応しており、ichigo-link-www フォルダ以下にファイルを置くと、localhost:30110 以下で公開されるようになっています。

5. [使い方] 付属デモアプリケーション

デモツールとして、簡易的なターミナルとコード送信ツールを添付しています。
ichigo-link-www/demo の下にファイルが存在します。

簡易ターミナル

http://localhost:30110/demo/terminal.html

connect ボタンを押すと接続します。
上のテキストボックスに入力したものを行単位で送信し、受信したものを下のテキストエリアに表示します。
RUNを中断したいときなどに esc ボタンを押してエスケープシーケンスも送れます。

現状、テキストエリアにデータを追加しているだけで解放処理をしていないので、
大量のデータを受け取ったり、長時間使用すると固まったりするかもしれません。あしからず。

コード送信ツール

http://localhost:30110/demo/send_source.html

まとめて何行か送りたいとき用のツールです。

6. 動画で紹介した作品の作り方

下記のソースコードをテキストエディタなどに貼り付けて、ichigo-link-www 以下に適当なファイル名で保存すれば、localhost:30110 以下でブラウザからアクセスできます。

IchigoJam 側のプログラムを最初に送って RUNするようにしていますが、この部分だけ IchigoJam 側に最初から用意しておいてもよいと思います。

IchigoJam のボタンを押すと背景色がつくページ

<!DOCTYPE html>
<html>
<head>
  <title>IchigoJamのボタンを押すと緑になるページ</title>
  <meta charset="UTF-8"/>
  <script>
    window.addEventListener('load', function () {
      var ws = new WebSocket('ws://localhost:30110/serial');
      ws.addEventListener('open', function () {
        ws.send(JSON.stringify({"type":"esc"}));
        ws.send(JSON.stringify({"type":"text","value":"NEW"}));
        ws.send(JSON.stringify({"type":"text","value":"10 ?BTN():WAIT3:GOTO10"}));
        ws.send(JSON.stringify({"type":"text","value":"RUN"}));
      });
    
      ws.addEventListener('message', function (event) {
        var obj = JSON.parse(event.data);
        if(obj.value == "0") {
          document.body.style.backgroundColor = "white";
        }
        if(obj.value == "1") {
          document.body.style.backgroundColor = "#00C000";
        }
      });
    
    });
  </script>
</head>
<body>
    <h2>IchigoJamのボタンを押すと画面が緑になるページ</h2>
  
</body>
</html>

ANA(2)の値で背景色の濃さが変わるページ

背景色の計算ロジック、地味に苦労しました。改善求む!

<!DOCTYPE html>
<html>
<head>
  <title>ANA(2)の値で緑の濃さが変わるページ</title>
  <meta charset="UTF-8"/>
  <script>
    window.addEventListener('load', function () {
      var ws = new WebSocket('ws://localhost:30110/serial');
      ws.addEventListener('open', function () {
        ws.send(JSON.stringify({"type":"esc"}));
        ws.send(JSON.stringify({"type":"text","value":"NEW"}));
        ws.send(JSON.stringify({"type":"text","value":"10 ?ANA(2):WAIT3:GOTO10"}));
        ws.send(JSON.stringify({"type":"text","value":"RUN"}));
      });
    
      ws.addEventListener('message', function (event) {
        var obj = JSON.parse(event.data);
        var a = parseInt(obj.value,10);
        var b = Math.floor(a/2);
        var c, d;
        if ( b < 256 ) {
	  c = 255 - b;
	  d = 255;
        } else {
	  c = 0;
	  d = 255 - (b-255);
        }
	var color = "rgb(" + c + "," + d + "," + c + ")";
	console.log(color);	 
	document.body.style.backgroundColor = color;
      });
    
    });
  </script>
</head>
<body>
    <h2>ANA(2)の値で緑の濃さが変わるページ</h2>
  
</body>
</html>

LEDとPWMをコントロールするページ

<!DOCTYPE html>
<html>
<head>
  <title>IchigoJamのLEDとPWMをコントロールするページ</title>
  <meta charset="UTF-8"/>
  <script>
    window.addEventListener('load', function () {
      var ws = new WebSocket('ws://localhost:30110/serial');
      ws.addEventListener('open', function () {
        ws.send(JSON.stringify({"type":"esc"}));
        ws.send(JSON.stringify({"type":"text","value":"LED0"}));
        ws.send(JSON.stringify({"type":"text","value":"PWM3,50"}));
        ws.send(JSON.stringify({"type":"text","value":"PWM4,50"}));
        document.getElementById('ledon').addEventListener('click',function() {
          ws.send(JSON.stringify({"type":"text","value":"LED1"}));
        });
        document.getElementById('ledoff').addEventListener('click',function() {
          ws.send(JSON.stringify({"type":"text","value":"LED0"}));
        });
        document.getElementById('pwm3').addEventListener('change',function() {
          var a = parseInt(document.getElementById('pwm3').value,10);
          ws.send(JSON.stringify({"type":"text","value":"PWM3," + a}));
        });
        document.getElementById('pwm4').addEventListener('change',function() {
          var a = parseInt(document.getElementById('pwm4').value,10);
          ws.send(JSON.stringify({"type":"text","value":"PWM4," + a}));
        });
      });
    });
  </script>
</head>
<body>
  <h1>IchigoJamのLEDとPWMをコントロールするページ</h1>
  <form>
    <h3>LED</h3>
    <input type="radio" name="led" id="ledon" />On
    &nbsp;
    <input type="radio" name="led" id="ledoff" checked="checked"/>Off
    
    <h3>PWM3</h3>
    50 <input type="range" id="pwm3" value="0" min="50" max="240" step="10"/> 240
    
    <h3>PWM4</h3>
    50 <input type="range" id="pwm4" value="0" min="50" max="240" step="10"/> 240

  </form>

  
</body>
</html>  

7. まとめと課題

  • IchigoLink を使うと IchigoJam と連携するブラウザアプリケーションを簡単に作れます。
  • Scratch 対応として配布するまでに GUI化したいです。
  • Windows 版の反応がよくない気がするのが少々気になる。
  • IchigoLink 公式サイトhttp://ichigolink.shizentai.jp/

IchigoJam BASIC RPi を USBメモリから起動する

IchigoJam BASIC RPi を USBメモリ から起動。 意外と簡単でした!

準備物

USBメモリからの起動には、Pi 3から対応しているようです。

  • Raspberry Pi 3 Model B
  • IchigoJam BASIC RPi を コピーした micro SDカード
  • IchigoJam BASIC RPi を コピーした USBメモリ

ご注意!

config.txt に program_usb_boot_mode=1 を追加して起動することで、ラズパイの OTP memory という領域が書き換えられて、USBメモリからのブートが可能になるとのこと。ただ、この設定は元に戻すことができないとのこと。試してみる方は自己責任でお願いします!

やりかた

基本的には、下記を参考にすればOKです。
HOW TO BOOT FROM A USB MASS STORAGE DEVICE ON A RASPBERRY PI 3

  1.  micro SDカード の config.txt の最後に  program_usb_boot_mode=1 を追加する
  2.  micro SDカード から一旦起動する
  3.  micro SDカード を抜いて、 USBメモリ を差して起動する
  4.  micro SDカード の config.txt を元に戻す(お忘れなく)

その他

  • USBメモリから起動するときは、いつもより少し時間がかかります。
  • だめもとで USBハードディスク(USB3.0, 500GB)でも試してみましたが、成功しませんでした。なにか工夫すればできるのかも。
  • 大きな領域が使えるとなると、IchigoJam BASIC にもファイルの WRITE/READ が欲しくなってきますね。

ラズパイ版 IchigoJam でアナログ入力

この記事は、IchigoJam Advent Calendar 2017 8日目の記事です。

1. はじめに

LPC1114版 IchigoJam にあって ラズパイ版にないものはけっこうあります。

  • ディスプレイ関連機能 (VIDEO/SWITCH コマンド)
  • サウンド関連機能 (BEEP/PLAY/TEMPO/SOUND コマンド)
  • マシン語関連機能 (USR コマンド)
  • 省電力機能 (SLEEP コマンド)
  • アナログ入力 (ANA コマンド)

その中でもとくに重要なアナログ入力ですが、今後も本体への実装は厳しそうなので、
回避策をご紹介したいと思います。

今回は、I2C通信対応のADコンバータを外部接続し、
ラズパイ版の IchigoJam BASIC でアナログ入力を実現してみます。

とはいえ、アナログ入力が使えないという課題自体は、Raspbian などのOSで
Raspberry Pi を利用している人にも共通しているため、ネット上にたくさんの情報がありました。

特にこちらの記事がとてもわかりやすく参考になりました。
http://kinokotimes.com/2017/02/02/python-mcp3425-16bits/

2. 準備物

Raspberry Pi本体

今回はPi3で試しました。

ADコンバータ

MCP3425というADコンバータのDIP化モジュールを秋月電子さんで購入しました。
http://akizukidenshi.com/catalog/g/gK-08018/

アナログセンサ

弊社によく転がっているシャープ製 測距センサ GP2Y0A02YK を使いました。
http://akizukidenshi.com/catalog/g/gI-03158/

3. ADコンバータの仕様

I2Cアドレス

上位4bit がデバイスアドレスで 0b1101
下位3bit は発注時に指定がなければ 0b000
ということなので、普通に購入した場合、0b1101000 = 0x68 になります。

設定の書き込み

1バイト送信して設定を行います。
bit7: 1に固定
bit4: (1:設定後、連続して読み取り可能; 0: 読み取りのたびに設定必要;)
bit3,2: (0b00:12ビット値を取得; 0b01:14ビット値を取得; 0b10:16ビット値を取得;)

今回は連続読み取り、12bitモードを試しました。(0b10010000)

電圧の読み取り

2バイト受信して読み取ります。(コマンドは0x00)
0バイト目: 上位8bit(右詰め)
1バイト目: 下位8bit

12bit,14bit,16bit の各先頭のビットは符号ビットなので、
実際の数値は 11bit, 13bit, 15bit マスクして取得するようです。

4. 配線

下記の接続でうまくいきました。(あとで図を載せたいです!)

測距センサ

VDD — RPi(5V)
VSS — RPi(GND)
VO — ADC(VIN+)

ADコンバータ

VIN+ — センサー(VO)
VIN- — RPi(GND)
VSS — RPi(GND)
VDD — RPi(3.3V)
SCL — RPi(SCL)
SDA — RPi(SDA)

5. BASIC コード

下記のコードで、なんとなくそれらしい値が取得できました。

10 POKE #700,`10010000
20 POKE #701,#00
30 R=I2CW(#68,#700,1)
40 R=I2CR(#68,#701,1,#702,2)
50 ?((PEEK(#702)<<8)|PEEK(#703))&`11111111111
60 WAIT5:GOTO40

6. 今後の課題

  • 14bitモードや16bitモードも試してみましたが、うまくいきませんでした。
  • 下位3bitのI2Cアドレスを指定できれば、切り替えて複数アナログ入力もできるかもしれません。