はじめに
19新卒エンジニアの青木です。
先日(2019/06/07)にOPTiM Dayという創立記念日イベントがあり、今回はそこでの新卒企画を紹介します
この記事はOPTiM Day新卒企画に登場した早押しボタンと効果音について、軽く解説したいと思いますのでよろしくお願い致します。
イベントの様子、ざっくりと解説
OPTiM Dayとは
毎年恒例の創立記念日のイベントで、全スタッフが集まって、弊社の理念や行ってきた活動を称え合い、より高みを目指すための活力を生み出そうという目的で実施されます。 この日のために作成した前年1年間の振り返りムービーを見たり、夜は懇親会も開催されます。
目的 ・感謝:現在、これまでOPTiMに関わってくださった、ご支援いただいた方々への感謝の気持ちを新たにする ・達成:この1年間で我々が成したことを確認し、今日ばかりは少し自己満足気味に讃えあう ・理念:OPTiMの理念に立ち返り確認しあう ・楽しむ:ばかばかしいほど、ばかばかしく、ばかといわれるほど楽しむ
また、今年はOPTiMとご縁のある方、約20名にゲストとしてお越しいただき、一緒に楽しんでいただきました。
新卒企画について
そんなOPTiM Dayですが、新卒企画もまた毎年恒例で行われており、 企画など1から行い、発表まで行います。
今年は、早押しクイズを行いましたが、来年何が行われるか楽しみですね、
概要
今回の新卒企画では、早押しクイズを行うことになりました。
どうせなら早押しボタンも作ってしまおう、ということで、、、
今回は早押しボタンを作ります
早押しボタンを制作するに当たり、以下の課題があります。
- 早押しボタンロジック
- 早押しボタン押下時の効果音
- その他の効果音(正解・不正解など)
- 早押ししたボタンの確認方法
- ネットワーク不安定の懸念
- 応答速度、バグ時の再起動の速さ
この課題を達成すべく、システムを構築しました。
構成
構成図
さて、気になるRaspberry PiとArduinoの通信方法ですが、、 こちらの記事の技術を使用したいと思います。
使用機材リスト
機材名 | 個数 | 備考 | |
---|---|---|---|
1 | Raspberry Pi 3 Model B+ | 1 | |
2 | Raspberry Pi SenseHAT | 1 | 8x8(64個)LEDを使用 |
3 | Arduino Leonardo | 1 | |
4 | 押しボタンスイッチ(大) | 4 | 早押し用 |
5 | 押しボタンスイッチ(小) | 4 | センターコンソール用 |
6 | 抵抗 1kΩ | 8 | |
7 | ワイヤ | 200m | 適当な長さをカットして使用 |
早押しボタンの制作 ボタンロジック編(Arduino)
さて、早押しボタンの制作を行います。
今回はArduinoとRaspberry Piを分けて説明したいと思います。 ボタンロジックはArduinoで完結しており、Raspberry Piの動作が停止していてもロジックは動いている状態になります。
Arduino自身にLEDなどの情報を表示できるモジュールを導入すれば、Arduino単体で動作できるようになっています。
今回は、モジュールの購入費用やLEDを利用する際の電圧降下の計算、及び回路設計や電流値の計算などが必要になってくるため、一度OPTiM TECH BLOG でも紹介した前例がある方法で行います。
仕様
早押しボタンの仕様は以下のとおりです。
- 1番早くボタンを押した人がわかる
- 2番目以降にボタンを押しても無反応
- 指定のタイミングで早押しボタンをリセットする
- 2番目以降にボタンを押しても無反応の状態を解除するため
- 早押しボタンは計4つ
- なるべく安定させるため、有線を使用する
ということで、 リセットするためのボタンが追加で1つ必要になります。
回路図
ボタンが8個中5つを使用し、4つを早押しボタン、1つをリセットボタンとして使用します。 また、その他のボタンを効果音設定ボタン(SEボタン)とし、ボタンを押すと予め用意した音源をRaspberry Piから鳴らすことが出来ます。
Arduinoプログラムソースコード
雑なコードですが、こちらをArduinoに読み込ませると早押しボタンが実装できます。
void setup() { Serial.begin(9600); } bool resetFlag = false; int resetPush = 0; int mPush = 0; int delayTime = 15000; void loop() { if (digitalRead(6) != LOW){ if(resetPush > 0){ resetPush--; } if(resetFlag == true){ if (digitalRead(2) == LOW) { Serial.println("Blue Push!!"); resetFlag = false; } else if(digitalRead(3) == LOW) { Serial.println("Red Push!!"); resetFlag = false; } else if(digitalRead(4) == LOW) { Serial.println("Green Push!!"); resetFlag = false; } else if(digitalRead(5) == LOW){ Serial.println("White Push!!"); resetFlag = false; } } } if (digitalRead(6) == LOW && resetPush <= 0) { Serial.println("Reset"); resetPush = delayTime; resetFlag = true; } if (mPush <= 0){ if(digitalRead(7) == LOW){ Serial.println("M1"); mPush = delayTime; } if(digitalRead(8) == LOW){ Serial.println("M2"); mPush = delayTime; } if(digitalRead(9) == LOW){ Serial.println("M3"); mPush = delayTime; } } if (digitalRead(7) != LOW && digitalRead(8) != LOW && digitalRead(9) != LOW){ if (mPush > 0){ mPush--; } } }
内部的な解説をすると長くなりますのでサクッと記述します。
こちらのコードでは、ボタンを押した際に再度ボタンが押されるまでのクールタイムがあります。
ボタンを押し続けるとその分だけ連打されているようにプログラムが解釈してしまうので、連打を防ぐために使用しています。
ボタンが押されたと判断されると、シリアルコンソールに指定の文字列を表示する用になっています。 Raspberry Piではこの文字を判定し、LED操作を行う用になっています。
また、8個のボタンの内早押しに使用しないボタンは独立してもシリアルコンソールに指定の文字を表示し、 早押しボタンと切り離したロジックになっています。
早押しボタンの制作 動作確認編(Raspberry Pi)
早押しボタンのロジックは完成したので、次はどのようにして動作確認するかですが。
今回はRaspberry Piにドッキング出来る公式基盤の SenseHAT
を使用します。
仕様
Arduinoからデータが来たらその色に光らせます。
また、同時にスピーカーから音が出るようにします。
Raspberry Pi プログラムソースコード
import serial from sense_hat import SenseHat import subprocess import concurrent.futures # 音声リスト def m_1(): subprocess.call("aplay /opt/hayaosi/audio_optim/1.wav", shell=True) def m_2(): subprocess.call("aplay /opt/hayaosi/audio_optim/2.wav", shell=True) def m_3(): subprocess.call("aplay /opt/hayaosi/audio_optim/3.wav", shell=True) def m_4(): subprocess.call("aplay /opt/hayaosi/audio_optim/4.wav", shell=True) if __name__ == "__main__": executor = concurrent.futures.ProcessPoolExecutor(max_workers=5) sense = SenseHat() sense.show_letter("S") # 起動時に「S」を表示 ser = serial.Serial("/dev/ttyACM0") # シリアルコンソールに接続 while True: line = ser.readline() text = line[0:6].decode("utf-8") if "Green" in text: # Greenを受信 sense.clear(0,255,0) executor.submit(m_4) if "Red" in text: # Redを受信 sense.clear(255,0,0) executor.submit(m_4) if "Blue" in text: # Blueを受信 sense.clear(0,0,255) executor.submit(m_4) if "White" in text: # Whiteを受信 sense.clear(255,255,255) executor.submit(m_4) if "Reset" in text: # Resetを受信 sense.clear(0,0,0) if "M1" in text: # M1を受信 executor.submit(m_1) if "M2" in text: # M2を受信 executor.submit(m_2) if "M3" in text: # M3を受信 executor.submit(m_3)
音声を再生する際、プロセスが走ったままになるのでスレッド管理しています。
これで早押しボタンの制作は終了です。
課題であった効果音は上記のソースで対応し、
ネットワークなど不安定要素は有線を使用することにより排除しました。
完成しました。
- センターコンソールのボタンを押すと音が鳴り
- 早押しボタンを押すと音がなりLEDが光ります
- リセットボタンで解除します
設置
設置計画は上の画像の通りです。
実際に設置した様子です
大変だった話
今回の制作でとても苦労した点は、ボタンそのものを買ったり耐久性を高めたりすることです。
最初はスティックコーヒーが入っていた空箱を利用してボタンの台にしていましたが、、途中でボコボコにつぶれてしまいました。。
その後どうしたかというと、、100均で密閉容器を購入して穴を開けてボタンの台を作りました。(とてもアナログな作業ですね)
センターコンソールやボタン同士をつなぐ数メートルもの導線を引っ張るのもなかなかの労力でした(めっちゃ絡まります)
リハーサル時点ではショートしたりして大変でしたが、ビニルテープで補強し導線をまとめ、、物理的に頑張っていた印象です。
最後に
当初、新卒企画としてハードウェアを構築しない話で進んでいましたが、水面下で作っていたら作れちゃいました...ということで採用されました。 いろんな事に挑戦して、自分磨きもしかり、良いイベントの開催にも繋がってとても良かったと思いました!
これからもいろんな事に挑戦していきたいと思います。
以上、19新卒エンジニアの青木でした。
尚、OPTiMでは一緒に働けるエンジニアを募集しています! 今回のようにとても自由な発想で、様々な挑戦が許される現場なのでとても楽しく業務をさせていただいています!
是非、興味のある方はお問い合わせをお願いします!