NINTENDO LABOをちょっと楽しくするArduino Toy-Con
発表されたときから「絶対買う」と決めていた『NINTENDO LABO』。早速、バラエティキットを購入致しました。
本当はロボットキットの方も購入したかったのですが、奥様に難色を示されたので断念。バラエティキットの方は「子ども(一歳数ヶ月)も一緒に遊べるから!」という説得で許可が下りました。
で、実際遊びまくっているウチの長男。一緒に作ることは当然できませんでしたし、遊べて「おうち」と「ピアノ」だけなのですが、大変気に入ってくれているようで、朝起きるとまず私の部屋にやってきて「あれやらせろ」と手を伸ばします。超かわいい。
。。。さて、元々用意されている5つのToy-Con(「リモコンカー」「つり」「おうち」「バイク」「ピアノ」)でも十分楽しめるのですが、やはりこのソフトのキモは『Toy-Conガレージ』でしょう。簡単にいうと、「Switch本体とJoy-Conの機能を好きに組み合わせて、あなただけのオリジナルの遊び(Toy-Con)を発明しよう!」という内容です。早速、ネット上では色々なオリジナルToy-Conがアップされてきています。音ゲーを作ったり、ゲーム&ウォッチを再現したり、視力検査装置を作ったり、ただ自分の絵を見て褒めてくれる装置を作ったり。。。なるほどなあと思うものがたくさんあって大変楽しいです。『NINTENDO LABO』は「モノづくりは興味あるけど、電子工作とかプログラムとかムズかしいよね」と思っていた人たちを引っ張り上げてクリエイターにしてしまう、とても素晴らしいツールだと思います。
その一方で、小心者かつひねくれ者の私は、「そんなのあったら、みんな簡単におもしろいモノを作れてしまって、相対的に自分の価値が下がってしまうではないですか!」という気持ちもちょっぴりあるのです。
というわけで、自分の存在証明のため(?)、同じオリジナルToy-Conを作るにしても、モノづくり初学者にはちょっとハードルが高そうなモノを敢えて作ってみることにしました。電子工作好きなら誰でも知っているArduinoとの連携によって実現するToy-Conを作ってみます。
Joy-Conには(当たり前ですが)線を引き出せるようなGPIOなんてありません。それじゃあどうやって連携させるのかというと、実はそのヒントは任天堂が自ら教えてくれています。
これはToy-Conガレージ内での『出力』『IRひかる』の設定画面です。『これはもしかしたら…』のところに
「電子工作と組み合わせたら…?」
との記載があります。つまり、この機能がArduinoとの連携のカギになることがここで示唆されているのです。ArduinoをNINTENDO LABOと組み合わせて使うことは、任天堂にとっては想定の範囲内のようです。
任天堂の手のひらの上で転がされているようで若干悔しいですが、言われるがままに赤外線受信モジュールを買ってきました。
電子部品ショップで売られていたIRM-3638N3というモジュールです。赤外線を受信しているときはLOW、受信していないときはHIGHを出力してくれるので、この出力をArduinoで監視しておけば、「NINTENDO LABO側で◯◯が起こると、Arduino側で◯◯が起こる」という連携が可能になります。
次にToy-Conガレージ側のプログラムをどうするかです。シンプルにするなら
- 入力:「タッチ」や「ボタン」など
- 出力:「IRひかる(のばす時間0)」
を直接繋ぐだけで、「一瞬だけ赤外線が光る」というプログラムが簡単に作れます。
中間ノードの『タイマー』を使えば、もう少し複雑なことが可能になります。
これは後で紹介する遊びのプログラムですが、例えば「『↑』ボタンを押すと、ボタンを押してから0.30秒後にIRが発光して消え、ボタンを押してから0.60秒後にまたIRが発光して消える」というふうに記述されています。こうしておくと、Arduino側では、「赤外線が◯回発光したら、Xをする」というふうに処理を分けることができるようになります。
さて、以上が基本的なNINTENDO LABO – Arduino間の連携方法ですが、これには一つ問題があります。
これは先ほどと同じ、『IRひかる』の説明画面ですが、『ヒント』の部分にちょっと気になる記述があります。
「IRカメラ2つとJoy-Con5本以上を同時に使うことはできません」
これはつまりどういうことかと言うと、例えば入力をToy-Conの『ピアノ』にして、出力に『IRひかる』を使ってArduinoと連携させようとすると、エラーになります。なぜなら、Toy-Conの『ピアノ』はIRカメラの機能を内部的に使っており、上記の制約に引っかかってしまうためです。
ということは、「『ピアノ』で特定の音が鳴ったら、Arduino側で◯◯が起こる」というような遊びをつくりたい場合には、IRを使わない、別の連携方法を考える必要があります。
やりようはいくらでもあると思いますが、一番シンプルなのはJoy-Conの振動を使うことではないかと思います。振動センサを用意して、「振動を検出したら◯◯をする」というプログラムをArduino側で組んでしまえばよいのです。
ということで、振動センサも用意してみました。上記の振動モジュールは感度を調整できるので使いやすいです。なお、Joy-Conの振動は長さを変えられるので、頑張ればIRの時のように「◯秒間振動したら、Xをする」というふうに処理を分けることができるのかもしれませんが、これはちょっと面倒になりそうなので、今回はやめておきます。
さて、NINTENDO LABOとArduinoの連携方法がわかったところで、根本的な問題として「じゃあ、Arduinoと連携して何をさせよう?」というのを考えてみます。これこそ本当にアイデア次第なのですが、前々から
「何かわかったときや成長したときに、ゼルダの謎解き音やドラクエのレベルアップ音とかが実際に鳴ったりしたらおもしろいのでは?」
というのをぼんやり考えていたので、このアイデアをNINTENDO LABO向けにアレンジしてみることにします。具体的には、NINTENDO LABOに組み込まれている音声以外に、任意の音源を再生可能にする拡張モジュールのようなものを作ってみたいと思います。
では、早速作っていきましょう。まずはケースからです。
最初は適当なプラケースを買ってきて、それに入れてしまおうかと考えていたのですが、せっかくNINTENDO LABO向けにつくるので、ここはダンボールで作るのが筋(?)かと思いますので、頑張ってダンボールで作ってみます。
『NINTENDO LABO』を実際に購入された方ならわかると思いますが、同封されているダンボールは薄型でとても扱いやすいものになっています。できれば同じようなダンボールを使いたかったのですが、家にあるのは分厚いものばかりでしたので、『NINTENDO LABO』に同封されていた「はじめかた」のダンボールを使うことにしました。
こんな感じで、箱の展開図を下書きします。なお、この下書きについては、
バラエティキットに入っている、おまけの『小物入れ』の展開図を参考にして書いてみました。
こんな感じですね。勉強になります。
で、実際にカットしてみたのこちらです。さて、綺麗にできてくれるかどうか。
どっこい
しょっと。…うん、そこそこ見れる形にはなったのではないかと思います。
中を開けると、「つかいかた」のなごりがあります。
これに、電子部品を詰めていきます。回路図はこんな感じになります。
先に紹介した部品以外で使用しているものは以下になります。
私の工作ではおなじみ、というかほとんどこれしか使っていません。
一つポイントなのは、振動センサをスイッチでON/OFFできるようにしてあることです。振動は何もJoy-Conだけで発生するものではないので、なんでもかんでも反応してしまわないよう、赤外線を主に使う際にはOFFできるようにしています。
で、実際に詰め込んだ結果がコチラ。
…うん、安定のスパゲッティ状態。天板面にとりつけてある各種LEDやセンサの固定には、グルーガン(ホットボンド)か両面テープのいずれかを使用しています。グルーガンは熱収集チューブの代わりになりますし、そのままダンボールへの接着にも使えますので、ダンボールを使った電子工作では相性抜群なのです。
外見は最終的にこんな感じになりました。
ピアノToy-Conパーツのダンボールの枠部分に残っていた部分を寄せ集めて貼り付けて、最後に『デコるセット』に入っていたNINTENDO LABOのロゴタイプのマスキングテープで天板面と底面を貼り付けてみました。良い感じに、純正品っぽくデコれたかなと思います。結構気に入っています。
設計上のポイントは、Joy-ConとArduino Toy-Conを並べたときに、赤外線LEDの高さが揃うように赤外線受信モジュールの位置決めをしていることです。
最後に、基板(Arduino Pro mini)にプログラムを書き込みます。今回のプログラムはとてもシンプルで短いです。
#include <string.h> #include <SoftwareSerial.h> #include <DFRobotDFPlayerMini.h> #define IR_PIN 4 #define VIB_PIN 5 #define VALID_VIB_PIN 6 #define LED_ON_PIN 7 #define IR_LED_PIN 8 #define VIB_LED_PIN 9 #define IR_SHORT_INTERVAL 200 #define IR_LONG_INTERVAL 400 SoftwareSerial mySerial(2,3); // RX, TX DFRobotDFPlayerMini myDFPlayer; uint8_t last_ir_state = HIGH; uint8_t ir_state = HIGH; uint8_t ir_short_counter = 0; uint8_t ir_long_counter = 0; unsigned long last_ir_time = 0; unsigned long ir_time = 0; uint8_t last_vib_state = HIGH; uint8_t vib_state = HIGH; void setup () { Serial.begin(115200); mySerial.begin (9600); if(!myDFPlayer.begin(mySerial)) { Serial.println(F("Unable to begin:")); Serial.println(F("1.Please recheck the connection!")); Serial.println(F("2.Please insert the SD card!")); while(true); } Serial.println(F("DFPlayer Mini online.")); myDFPlayer.setTimeOut(300); //Set serial communictaion time out 300ms myDFPlayer.volume(25); //Set volume value (0~30). pinMode(IR_PIN, INPUT_PULLUP); pinMode(VIB_PIN, INPUT_PULLUP); pinMode(VALID_VIB_PIN, INPUT_PULLUP); pinMode(LED_ON_PIN, OUTPUT); pinMode(IR_LED_PIN, OUTPUT); pinMode(VIB_LED_PIN, OUTPUT); digitalWrite(LED_ON_PIN, HIGH); } void loop () { /////////////////////////////////////////////////////////////////////////// ir_state = digitalRead(IR_PIN); if(ir_state == LOW && last_ir_state == HIGH){ ir_short_counter += 1; last_ir_time = millis(); } last_ir_state = ir_state; ir_time = millis(); if(ir_short_counter > 0){ if(ir_time - last_ir_time >= IR_SHORT_INTERVAL){ ir_long_counter += 1; ir_short_counter = 0; } } if(ir_long_counter > 0){ if(ir_time - last_ir_time >= IR_LONG_INTERVAL){ myDFPlayer.playMp3Folder(ir_long_counter); for(int i= 0;i<ir_long_counter;i++){ digitalWrite(IR_LED_PIN,HIGH); delay(100); digitalWrite(IR_LED_PIN,LOW); delay(100); } delay(1000); ir_long_counter = 0; } } /////////////////////////////////////////////////////////////////////////// if(digitalRead(VALID_VIB_PIN) == LOW){ digitalWrite(VIB_LED_PIN,HIGH); }else{ digitalWrite(VIB_LED_PIN,LOW); } vib_state = digitalRead(VIB_PIN); if(vib_state == LOW && last_vib_state == HIGH){ myDFPlayer.playMp3Folder(6); for(int i= 0;i<2;i++){ digitalWrite(VIB_LED_PIN,LOW); delay(100); digitalWrite(VIB_LED_PIN,HIGH); delay(100); } delay(3000); } last_vib_state = vib_state; /////////////////////////////////////////////////////////////////////////// delay(10); }少し気をつけなくてはいけないのは、Toy-Conガレージ上では『IRひかる』を1回実行しているだけでも、実際は目には見えない速さで(IRはそもそも見えませんが)、高速で点滅を繰り返します。そのため、「IRの点滅が落ち着いたところで1回の『IRひかる』の発光とみなす」というようなプログラムを書く必要があります。
以上で制作完了です。Toy-Conガレージ上での連携のさせ方の基本は以下のようになります。
では、このArduino Toy-Conを使った遊び方を2つほどご紹介したいとお思います。
1. RPG-AR-MIX
伝説の剣入手〜攻撃〜かいしんのいちげき〜戦闘終了までの一連の流れの臨場感を高めてみました。
視覚効果だけがAR(拡張現実)とは限らないですよね、という話です。これらの効果音を生み出した方々は本当に凄いなあと改めて思います。
上記の動画のうち、通常の斬撃音のみ、NINTENDO LABOに組み込みの音声を使っています。こちらの方が音声再生開始までのタイムラグが圧倒的に少ないので。
既に先にお見せしていますが、Toy-Conガレージ上のプログラムの全体像はこんな感じです。ポイントは以下の2つです。
- 中間ノードの『タイマー』を使うことで、赤外線LEDの点滅回数を制御し、Arduno側で再生する音声を切り替えられるようにする
- 入力ノード『Joy-Con ふり』+出力ノード『音(ソ#, こうかおん1)』を設定し、Joy-Conを振ったときの通常の斬撃音を再生。さらに、入力ノードの出力設定を『アナログ』、出力の『入力をなににつかう?』で『周波数変化』に設定し、Joy-Conを振る速さによって斬撃音を変化させる
ちなみに、動画内で私が振っている剣(『風のタクト』版マスターソード)は、本業でのアメリカ出張でのオフの時間に、ゲーム屋さんで見つけて買ってきたものです。こんなところで活用できるとは当時は全然思っていませんでした。
2. ゼルダの子守唄
特定のメロディを奏でないと謎が解けない仕組みです。『ゼルダの伝説 時のオカリナ』ではよく見るタイプの仕掛けだったのではないかと思います。
オカリナではないのが残念ですが、概ね雰囲気は再現できたかなと思います。
Toy-Conガレージ上のプログラムの全体像はこんな感じです。ポイントは以下の2つです。
- 中間ノード『カウンター』を状態保持用の変数のイメージで使用し、中間ノード『AND』を組み合わせることで、「先にこの音が鳴らされている状態でこの音を鳴らすのが正解」という縛りを作る
- 鍵盤を叩ける回数に上限を設けるため、どの鍵盤を叩いてもカウントアップするような中間ノード『タイマー』を用意。この『タイマー』の出力ノードに『画面をひからせる』を繋げ、『ひからせかた』を『のびる』に設定。光の伸びを中間ノード『スポイト』で吸い取って、失敗音(『ド#』の『こうかおん1』)の再生と全カウンタのゼロリセットを実行
『カウンター』と『画面をひからせる』と『スポイト』を組み合わせることで、一般的なプログラムで言う「if sum == 10 then X」みたいなことが表現できるのですね。おもしろいです。
ということで、ちょっと長くなってしまいましたが、Arduinoとの連携を活かしたオリジナルToy-Con『Arduino Toy-Con』のご紹介でした。
今回は簡単に『音源拡張モジュール』としてArduinoを使いましたが、Arduino側では言ってしまえばなんでもできる、モーターだって回せるし、トランジスタやリレーを使えば大電流だって扱えるし、その気になればインターネットに繋げることだってできるので、元々自由度の高いNINTENDO LABOの世界がさらに広がることになります。今回の記事が、NINTENDO LABOでモノづくりの楽しさに目覚めた方々のステップアップの一助になれば幸いです。
なお、今回の記事はArduinoとの連携方法として書きましたが、Raspberry Piとの連携方法についても、全く同様に考えることができるハズです。
ディスカッション
コメント一覧
はじめまして。
ラボでこんなことが出来るなんて。
特にゼルダの子守唄はマジですごすぎです!
引き続きまた面白いのがあったら紹介してください。
通りすがり様
コメント頂きありがとうございます◎ 大変励みになります、ありがとうございます。
Arduinoとの連携は絶対誰かやるだろうと思ったので、取り急ぎ音源を拡張するだけの簡単なものを作ってみました。でもその気になればインターネットに繋いだりもできるので、時間があればもっとダイナミックな仕掛けも作ってみたいですねー。当分時間がなくて難しそうですが。。。
初めまして、たまたま見つけたので拝見させていただきました
アイデアもそれを実現する技術も素晴らしいですね!
今後も時々見させていただきます
ななし様
ご覧いただきありがとうございます!大変励みになります、ありがとうございます。
最近ちょっと本業が忙しくてしばらく更新できそうにないので、時々見に来て頂くぐらいで丁度良いと思います。宜しくお願い致します。