ScratchをArduinoと連携させて赤外線リモコンの信号を出す(Scratch側からArduinoスケッチ内に書いた処理を呼び出す)

Scratchはみなさんご存知でしょうか。昨今のプログラミング教育ブームで今ぐいぐい来てる、MITメディアラボが開発したプログラミング学習環境です。

f:id:slideglide:20180616224735p:plain

こういう感じのグラフィカルな画面でプログラミングができます。日本語表示にも対応。
画面のまんなかに並んでるブロックが命令で、それを組み合わせて右側にプログラムを組み立てていきます。左側のネコがいるところが実行結果の出力画面です。

上のキャプチャのプログラムはFizzBuzzです。拡大してみましょう。

f:id:slideglide:20180616224731p:plain

こんな感じになります。

いまちょっと思いついたことがあって、そのScratchを使った別のプロジェクトを進めているのですが、その過程で赤外線リモコンができるようになったのでいったん共有します。というか赤外線は実験のためにやっただけで、実際にはScratch側からArduinoスケッチ内に書いたいろんな処理を呼び出すことができます。

(追記:別のプロジェクトも完成しました )
nomolk.hatenablog.com

この記事のゴール

Scratchのプログラムから赤外線リモコンの信号を出し、リモコン対応機器を操作します。今回はカメラのシャッターを切ります。
具体的にはこんな感じのプログラムになります。

f:id:slideglide:20180616224740p:plain

なんか言ったり鳴らしたりしてるのは味付けで、実際にカメラのシャッター信号を出すのは「send [IR1]」のブロック一つです。

Scratchだけで完結したいところですが、パソコンの画面から赤外線が出せるわけではないので、ハードウェアとしてArduinoを使います。

使うもの

ソフトウェア

Scratch 2 offline editor(Scratchのオフライン開発環境)
Arduino IDE
Scrattino2(ScratchとArduinoを連携させる。この後の手順でインストールします)

ハードウェア

・Arduino(今回はUnoを使用)

【永久保証付き】Arduino Uno

【永久保証付き】Arduino Uno

赤外線LED
ブレッドボード
ジャンパ線
・抵抗(今回は47Ωを使用)

※以下は、自分でリモコンの信号を調べる場合のみ(後述)
赤外線センサ
・純正のリモコン

Scrattino2のインストール

Scratchと、Arduino IDEはあらかじめインストール済みとして話を進めます。あと筆者の環境はWindows10なので、別OSの方は適宜読み替えてください。

まずはScrattino2のGitHubから、ファイルを2つダウンロードします。今回使う機能の入った ver 0.3.0 はリリースされたばかりなので、インストール済みの人も入れ直しましょう。

f:id:slideglide:20180616224723p:plain

exeがインストーラで、zipの方には別途必要なファイルが入っています。両方DLしましょう。
DLが終わったらインストーラを実行します。

f:id:slideglide:20180616224716p:plain

なんか不安な画面が出てきますが、強い気持ちで「詳細情報」→「実行」を押します。うまくいかない場合はこちら

無事インストールが終わると、自動的にScrattinoが立ち上がります。

f:id:slideglide:20180616225257p:plain

ここまで来たら一旦放置して、次はArduino側の作業をします。

Scrattino2+Arduino の連携確認

Arduino UnoをPCにUSB接続し、Arduino IDEを起動します。
起動したら File>Examples>Firmata>StandardFirmata を開きます。

f:id:slideglide:20180616225253p:plain

新しいウィンドウが開いて StandardFirmata.ino のスケッチが出てくるので、そのまま書き込みボタンでArduinoに書き込みます。
これでScrattino2との通信に必要なプログラムが書き込めました。

さっき出てきたScrattino2の画面に戻って、Scan Port のボタンを押します。そうすると下図の赤丸のスイッチが出てきます。

f:id:slideglide:20180616230846p:plain

これをクリックすると

f:id:slideglide:20180616230935p:plain

こんな感じでArduinoの各ピンのステータスが出てきます。これで、Arduino ⇔ Scrattino 間はつながりました。

Scrattino2+Scratch の連携確認

次にScratchを開いて、Shiftを押しながら「ファイル」メニューを開きます。こうすると「実験的なHTTP拡張を読み込み」という隠しメニューが出ます。裏技です。

f:id:slideglide:20180616230931p:plain

それをクリックして、scrattino2_resources.zip に入っている extension/scrattino2.s2e を読み込みます。

f:id:slideglide:20180616230927p:plain

ブロックの「その他」のところに、Scrattinoの見出しがついた黒いブロックが出てきましたか?
見出しの横のランプが緑色なら、正常にArduinoがつながっています。

f:id:slideglide:20180616230925p:plain

ためしにOUTPUTと書かれたブロックを右側にドラッグ&ドロップして、こんなブロックを作ってみてください。
下のブロックをダブルクリックすると、Arduino本体の「L」と書かれたLEDが点灯します。上のブロックをダブルクリックすると消えます。
これで Scratch ⇔ Scrattino ⇔ Arduino がすべてつながりました!

Arduinoから赤外線を出す

ここまでが環境設定で、ここからいよいよ実装です。

まずはいったんScratchを離れまして、Arduinoから赤外線信号を出す方法を考えます。
回路から先に組んでいきましょう。

f:id:slideglide:20180617001843p:plain

シンプルですね。LEDの向きに注意しましょう。(図だと逆に見えるけど足が長い方が抵抗側)
抵抗は今回47Ωを使いましたが、適当に小さいのを入れておけばいいです。あともしかしたらArduinoの機種が違うと接続するデジタルピンが変わるかもしれない(ライブラリ側で固定なので。UNOはD3でOK)。

回路ができたら、次にArduino IDEに赤外線リモコンのライブラリをインストールします。
Sketch>Inclued library>Manage Libraries... から、IRremote を検索してインストールです。

できたら、ここからが正念場です。赤外線信号を出すスケッチを書いていきます。ここは自分で書くしかないので頑張ろう。

#include <IRremote.h>
IRsend irsend;

void setup() {
}

void loop() {
  for (int i = 0; i < 3; ++i) {
    irsend.sendSony(0xB4B8F, 20);
    delay(5);
  }
  delay(10000);
}

これは僕が使っているNEX-5Tのシャッターを10秒おきに切るスケッチです。

    irsend.sendSony(0xB4B8F, 20);

のところだけ変えれば大抵のリモコンに対応できると思います。(3回ループさせてますが、ほかのメーカーも3回送る必要があるかは不明です)

sendSonyメソッドはSonyの信号のフォーマットで送るメソッドで、ほかにsendNEC、sendRC5等のメソッドも用意されています。
SonyフォーマットはSony製品のみ、ほかの国産家電はNECフォーマットが多いようです。
引数は0xB4B8Fのところが送る値、20が信号の長さです。

ここに何を入れればいいかは、運が良ければ「IRremote Arduino 機種名」とかで検索すると見つかります。見つからない場合は簡単な回路とライブラリのサンプルコードを使って、自分で調べることができます。

Arduinoで赤外線リモコンの値を読み取り、送信する方法 : 試行錯誤な日々
→「読み取り回路を作成」以降を参照

無事に赤外線信号を出すスケッチができたらArduinoに書き込んで、本当に動作するか試してみます。
本物のリモコンほど遠くまでは届かないので、テスト時はご注意ください。

Scrattino2への組み込み

リモコンのスケッチができたら、いよいよScrattino2に組み込んでいきます。
Arduino IDEで、scrattino2_resources.zip に入っている arduino/Scrattino2/Scrattino2.ino を開きます。
これは動作確認にも使った StandardFirmata.ino をベースに、Scratch側から特定の処理を呼び出せるように改変されたものです。
755行目、sendStringCallback関数の定義部分を探しましょう。

void sendStringCallback(char *str)
{
  // Sample code for testing
  if (strcmp(str, "LED ON") == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else if (strcmp(str, "LED OFF") == 0) {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

ここに処理を書くことで、それをScratchのブロックから呼び出すことができます。
Scratch側でこんなブロックがあったのを覚えているでしょうか。

f:id:slideglide:20180616230856p:plain

この「LED ON」が、スケッチ中の"LED ON"と対応しています。つまりこのブロックが実行されると

  digitalWrite(LED_BUILTIN, HIGH);

これが実行されるということです。

そこへ今回は赤外線を送る「IR1」というのを新たに追加し、次のように書き換えました。

void sendStringCallback(char *str)
{
  // Sample code for testing
  if (strcmp(str, "LED ON") == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else if (strcmp(str, "LED OFF") == 0) {
    digitalWrite(LED_BUILTIN, LOW);
  } else if (strcmp(str, "IR1") == 0) {
    for (int i = 0; i < 3; ++i) {
      irsend.sendSony(0xB4B8F, 20);
      delay(5);
    }
  }
}

これだけだとライブラリが読み込まれてなくてコンパイルエラーになるので、最初の方に

#include <IRremote.h>
IRsend irsend;

このへんを入れるのも忘れないでください。一応、僕が書き換えたスケッチ全文をGistに置いておきます
完成したらArduinoに書き込んでおきます。

Scratchから動かす

いよいよ、Scratchから実際に赤外線を飛ばす処理を呼び出してみます!

f:id:slideglide:20180616230849p:plain

こんなブロックを作って、ダブルクリックしてみましょう。

見事、シャッターが切れました!
なお、動画では動作がわかりやすいように、赤外線と並列に赤色のLEDをつけています。赤外線LEDはふつう肉眼では見えませんのでご注意を。

せっかくなのでもうちょっといい感じに味付けしてみます。

f:id:slideglide:20180616224740p:plain

いつもは画面の中にいるScratchのネコが、画面の外で実際に写真を撮ってくれます。胸が熱くなりますね。

これができたことで、インターバル撮影にも使えそうですね。たとえば、10秒おきに5枚、自動的に写真を撮るようにしてみました。

f:id:slideglide:20180616224713p:plain

まとめ

Arduinoのスケッチを書かなきゃいけないので子供にはちょっと難しいかもしれませんが、設定だけ大人がやって、Scratchのできる子供に触らせてあげるとめっちゃ喜びそうですね。
いま、この応用編的なプロジェクトを考えているので、続きはそのうちまたここに書きます。

謝辞

Scrattino2のsendブロックですが、実は僕の技術相談への対応として作者のyokobond氏が実装してくれたものです。まさに神対応。どうもありがとうございました!