年末年始こそ工作! 家族で遊べるオリジナル◯×ゲームを作ろうd

いよいよ大晦日ですね。家族や友人と自宅で冬休みを過ごす方も多いのではないかと思います。そんな方向けに、インタラクションのある○×ゲームを考えてみました。プログラムの環境構築やライブラリも不要なので、初心者の方でも作りやすいと思います。お子さんと一緒に作っても楽しいですよ。
まずは、どのようなゲームか動画で確認しましょう。

光るコマの仕組み
このゲームは、画面上に出題されるクイズを○/×で答えるものです。コマを○/×に近づけ、正解ならコマが光ります。このコマがどのような仕組みになっているか、分かったでしょうか。
中身はワイヤレスLED給電ユニットです。ワイヤレスLED給電ユニットとは、電力共有用のアダプターなどを接続しなくても、ワイヤレスLEDを近づけることで給電できる機能を持ったユニットです。
通電したままの状態でワイヤレスLEDを近づけたり、遠ざけたりすることでON/OFFさせるのですが、今回作成するガジェットは直接、ワイヤレスLED給電ユニット自体をON/OFFすることで、正解/不正解を表現しました。

当初、M5Stackのディスプレイに質問を出し、ワイヤレスLED給電ユニットのON/OFFで正解の判定を行う想定でいましたが、配線して試してみたところ......光りませんでした。
ワイヤレスLED給電ユニットの配線をLEDに変更してみたところ発光したので、電力不足という事は明確でした。


ESP32のGPIOは出力が3.3V
M5Stackの基本的なGPIOの出力は、3.3Vです。M5Stackには5V出力のPINも用意はされていますが、ON/OFFの制御ができるのは3.3Vだけでした。
ワイヤレスLED給電ユニットの動作電力は5V~9Vなので、ワイヤレスLED給電ユニットに5V以上で電気を給電する方法を考える必要が出てきました。
余談ですが、通電がされているかどうかを確認するために、砲弾型LEDを使います。ESPやArduinoなどは、3.3V~5Vが多いため、砲弾型LEDのみ接続してもLEDが壊れてしまうことはありません。
大きな電力のものを動かせるリレー
M5Stackで動かない高い電圧の製品を使いたい時は、「リレー」を使います。リレーとは、外部から信号を受け取り電気回路のON/OFFを行う装置です。
今回は、M5StackでON/OFFの信号をリレーに送り、リレーに接続された高い電力(ワイヤレスLED給電ユニット)を動かします。
リレーを覚えると、M5Stackの3.3Vでは動かないモーターなども動かせるようになります。

M5Stackに質問を表示する
M5Stackのディスプレイには簡単にテキストを表示できますが、日本語フォントは標準で表示できません。日本語ライブラリをArduino IDEにインストールすれば表示が可能ですが、Arduino IDEをM5で使うにはライブラリの追加やさまざまな設定変更など、初心者にはハードルが高いので要注意です。また、オンライン版のArduino Web Editorではそういった設定は省けますが、日本語が使用できません。
そこで今回は、日本語フォントを使用するのではなく、画像を読み込み表示させようと思います。
オープニング画像1枚/質問4枚/答え4枚で計9枚の画像を用意しましょう。もし用意ができない場合は、ページ下部よりダウンロードして画像を利用してください。



用意した画像をマイクロSDカードに保存
用意したオープニング画像と、質問画像4枚/答え画像4枚をSDカードに保存します。
ご自身で画像を作成した場合は、同じ名称で保存していただくか、プログラムに記載してある画像名を変更してください。

その後、画像を保存したSDカードをM5Stackに差し込んでください。
回路とプログラム
回路は非常にシンプルですが、配線が細かく難しいので、回路図を参考にして配線してください。


ワイヤレスLED給電ユニットには、リレーを挟んで5Vを供給します。
GroveコネクターからGPIOの21、22を使用し、ON/OFFを制御することでリレーに接続した機器のON/OFFを行っています。
使用するプログラミング環境は、Arduino Web Editorです。アカウントを登録し、左メニューExamplesから、M5STACK > Display > JpegDrawを選択します。このプログラムを変更していきます。

プログラムの詳細は割愛しますが、下記プログラムをM5Stackに書き込めば完成です。
#include <M5Stack.h>
int btnCnt = 0;
void step1();
void step2();
void step3();
void step4();
void step5();
#define RELAY_PIN1 22 //◯
#define RELAY_PIN2 21 //×
void setup(void) {
M5.begin();
M5.Power.begin();
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(4);
M5.Lcd.setBrightness(200);
M5.Lcd.drawJpgFile(SD, "/opening.jpg");//オープニング画像表示
pinMode(RELAY_PIN1, OUTPUT);
pinMode(RELAY_PIN2, OUTPUT);
digitalWrite(RELAY_PIN1, LOW);
digitalWrite(RELAY_PIN2, LOW);
}
void loop() {
if(M5.BtnA.wasPressed()) {
digitalWrite(RELAY_PIN1, LOW);
digitalWrite(RELAY_PIN2, LOW);
btnCnt++;
M5.Lcd.clear(); // 画面全体を消去
//M5.Lcd.drawString("CNT=" + String(btnCnt), 0, 40); //ボタンAを押した時の動作
if(btnCnt == 1) {
step1();
} else if(btnCnt == 2) {
step2();
} else if(btnCnt == 3) {
step3();
} else if(btnCnt == 4) {
step4();
} else if(btnCnt == 5) {
step5();
}
}
M5.update();//状態の更新
return;
}
void step1(){
M5.Lcd.setBrightness(200);
M5.Lcd.drawJpgFile(SD, "/question1.jpg", 0, 0, 320, 240);
delay(10000);
int countDown;
for(countDown=5; countDown>=1; countDown--){
M5.Lcd.fillScreen(BLACK);
M5.Lcd.drawString(String(countDown), 150, 110);
delay(1000);
}
M5.Lcd.drawJpgFile(SD, "/answer1.jpg", 0, 0, 320, 240);
digitalWrite(RELAY_PIN1, HIGH);
return;
}
void step2(){//質問2
M5.Lcd.setBrightness(200);
M5.Lcd.drawJpgFile(SD, "/question2.jpg", 0, 0, 320, 240);
delay(10000);
int countDown;
for(countDown=5; countDown>=1; countDown--){
M5.Lcd.fillScreen(BLACK);
M5.Lcd.drawString(String(countDown), 150, 110);
delay(1000);
}
M5.Lcd.drawJpgFile(SD, "/answer2.jpg", 0, 0, 320, 240);
digitalWrite(RELAY_PIN2, HIGH);
return;
}
void step3(){
M5.Lcd.setBrightness(200);
M5.Lcd.drawJpgFile(SD, "/question3.jpg", 0, 0, 320, 240);
delay(10000);
int countDown;
for(countDown=5; countDown>=1; countDown--){
M5.Lcd.fillScreen(BLACK);
M5.Lcd.drawString(String(countDown), 150, 110);
delay(1000);
}
M5.Lcd.drawJpgFile(SD, "/answer3.jpg", 0, 0, 320, 240);
digitalWrite(RELAY_PIN2, HIGH);
return;
}
void step4(){
M5.Lcd.setBrightness(200);
M5.Lcd.drawJpgFile(SD, "/question4.jpg", 0, 0, 320, 240);
delay(10000);
int countDown;
for(countDown=5; countDown>=1; countDown--){
M5.Lcd.fillScreen(BLACK);
M5.Lcd.drawString(String(countDown), 150, 110);
delay(1000);
}
M5.Lcd.drawJpgFile(SD, "/answer4.jpg", 0, 0, 320, 240);
digitalWrite(RELAY_PIN1, HIGH);
return;
}
void step5(){
digitalWrite(RELAY_PIN1, LOW);
digitalWrite(RELAY_PIN2, LOW);
M5.Power.reset();
return;
}
最後にコマを装飾する
コマにワイヤレスLEDを使用しますが、とても小さく、なくしてしまう危険性があります。そこでプラスチック粘土を使ってワイヤレスLEDを装飾し、なくさないようにします。プラスチック粘土は光を透過するので、LEDが点灯した時も綺麗に見えます。星形や月形など、コマを作るところから、みんなで始めても楽しいと思います。

実際に○×ゲームを行ってみたところ、正解するとLEDが点灯する事で正解した感触が伝わり、画面だけの○×ゲームよりも面白いようです。

画面に表示する質問と答えは、ご自身で作成可能です。アニメや植物に関するクイズなど、自分たちが得意なクイズを用意するとさらに盛り上がると思います。ぜひ試してみてください。
また次回も、電子工作を楽しみましょう!
準備する用具
M5Stack Basic V2.6:6545円
ワイヤレスLED給電ユニット OSWPTS1208D 2個:計800円
ワイヤレスLED 赤:220円
ワイヤレスLED 青:220円
M5Stack用2チャンネルSPSTリレーユニット(1回路1接点):1056円
ブレッドボード BB-801:220円
ブレッドボード・ジャンパーワイヤ(オス-オス)10cmセット:180円
ヒノデワシ プラスチックねんど おゆまる1000 OO-1000:579円
※各製品の価格は記事初出時点での価格です。