前編:加速度センサとMP3プレイヤーで作るおしゃべりサイコロ
はじめに
こんにちは。平原です。この記事では、旅の目的地や会話の話題をしゃべって決めてくれるサイコロを作ります。前回はブレッドボードでの仮組み、ライブラリのインストール、サンプルファイルの実行を行いました。今回の後編では、MDFで外装の作製、ユニバーサル基板のはんだ付け、プログラムの実装を行います。
それでは今回もよろしくお願いします!
【目次】
1.基板と筐体の作製
筐体の設計
サイコロなので全体の形は立方体です。中央に渡した板にArduino UNOなどの部品類を固定し、上面にスイッチ、側面にスピーカを取り付けます。3DCADソフトのFusion360を使って設計しました。部品を入れて窮屈でないように内寸150mm x 150mm x 150mm としています。上面と前面はあとから取り外しできるようにL字アングルを3Dプリンタで作り、ネジ止めします。素材はMDF(5.5mm厚)です。
レーザー加工
Fusion360でそれぞれのパーツの平面図をPDFとして書き出します。配布ファイルの「CutData.ai」を使用してください。赤い線が切断する箇所です。お使いのレーザー加工機に合わせてAdobe Illustratorなどでデータを作製してください。
ユニバーサル基板の作製
筐体を組み立てる前に、DFPlayer miniを乗せる専用のシールドを作ります。専用のシールドと言っても、ArduinoUNOのソケットの位置にピンを取り付けたユニバーサル基板です。
使用する部品は、Arduino用ユニバーサルシールドキット、DFPlayer mini、スピーカ、スイッチ、抵抗器です。キットに付属するソケットは今回使用しません。
表面にDFPlayer mini、抵抗器、スピーカとスイッチからの配線を配置し、裏面にピンの配置と配線をします。
はじめに、スイッチのナットを一旦外して、MDFで切り出したスイッチ受けを取り付け、再びナットで固定してください。スイッチをユニバーサル基板にはんだ付けしてしまうと、後から取り付けられないので、順番に注意してください。
Arduino用ユニバーサルシールドキットに付属するピンを6ピン 2つ、8ピン 2つに切断します。ニッパーで勢いよく切ると割れてしまうことがあるので、少しずつ力をかけてください。
裏面からピンを指し込み、表面ではんだ付けします。複数のピンがある部品を基板に密着させるには、まず一番端のピンを仮にはんだ付けし、部品を基板に押し付けながら、仮はんだした部分をもう一度溶かします。
同じ要領で、すべての部品を基板にはんだ付けします。
最後に、ピンとピンの間を配線します。ジャンパワイヤを使ってもいいですし、下の写真のように銅箔の上に盛ったハンダを連結しても結構です。完成したらテスターを使って、ピンと部品の間が接続されているか、不要な箇所がショートしていないかを確認してください。
筐体の組み立て
中板にArduino UNOと電池ホルダーを固定します。Arduino UNOはナベネジ(M2 20mm)で4箇所、透明のケースはナベネジ(M3 15mm)で2箇所、電池ホルダーはナベネジ(M3 15mm)で3箇所を固定します。 2.1mm DCプラグ付バッテリースナップを電池に取り付けてください。2.1mmDCプラグをお持ちの場合は、電池ホルダーに付属するスナップに取り付けて使用しても結構です。
左、右、下、後と中板を木工用ボンドで接着します。
Arduino UNOにシールドを乗せます。下から、Arduino UNO、ロームセンサ評価キットシールド、自作ユニバーサル基板シールドです。
スピーカーホルダーを使ってスピーカーを後の板に固定します。次にスイッチを取り付けた板と上の板をナベネジ(M3 25mm)で固定します。その際、ワッシャーなどで6mm程度のスペースをとってください。
左右の板に3DプリントしたL字のパーツをナベネジ(M3 15mm)で取り付けます。配布ファイルの3Dプリントフォルダの中から「L-angle.stl」を出力して使ってください。上と前の板は、プログラムを書き込んだあとでネジ止めして閉じます。
2.音声ファイルの準備
出目に応じた6つのセリフとタイトルコールで1セットとなります。配布ファイルにサンプルとして、3セット21ファイルを用意しました。内容は次の一覧のとおりです。ご自身で録音したファイルを使用しても結構です。
ファイル一覧
番号 | ファイル名 | セリフ |
---|---|---|
1 | 1-1.mp3 | カレーライス |
2 | 1-2.mp3 | ハンバーグ |
3 | 1-3.mp3 | とんかつ |
4 | 1-4.mp3 | すき焼き |
5 | 1-5.mp3 | 焼き肉 |
6 | 1-6.mp3 | 寿司 |
7 | 1-title.mp3 | 今日のメニューは! |
8 | 2-1.mp3 | 鹿児島 |
9 | 2-2.mp3 | 松山 |
10 | 2-3.mp3 | 大阪 |
11 | 2-4.mp3 | 釜山 |
12 | 2-5.mp3 | 札幌 |
13 | 2-6.mp3 | 博多 |
14 | 2-title.mp3 | 旅の行き先は! |
15 | 3-1.mp3 | 恥ずかしい話 |
16 | 3-2.mp3 | 初めて〇〇した話 |
17 | 3-3.mp3 | ここだけの話 |
18 | 3-4.mp3 | 怖い話 |
19 | 3-5.mp3 | 情けない話 |
20 | 3-6.mp3 | 驚いた話 |
21 | 3-title.mp3 | トークテーマは! |
マイクロSDカードへコピーする
DFPlayer miniは、ファイルがコピーされた順で再生するファイルを指定します。ファイル名順ではないことに注意してください。そのため、SDカードにコピーする際は、リストの順番どおりにコピーをおこなうといいでしょう。また、ファイルを更新した場合も、1ファイルだけコピーすると順番が変わってしまうので、すべてのファイルを消去したあとで、コピーするようにしてください。
ファイルを書き込んだマイクロSDカードをDFPlayer miniに差し込んでください。
3.Arduinoのプログラム
プログラムの全体は、配布ファイルのTalkingDiceフォルダの中にある「TalkingDice.ino」を参照してください。ここでは、重要なポイントについて説明します。
加速度センサモジュールの使い方
ライブラリのインストール方法は、前編の「3.動作確認」を参照してください。
宣言部でライブラリのインポートとインスタンスの生成を行います。
#include <KXTJ3.h> //加速度センサモジュールのライブラリをインポート
KXTJ3 kxtj3(KXTJ3_ADDR_LOW); //加速度センサモジュールのインスタンス
setup部では加速度センサモジュールの初期化をして、通信がうまくいけば起動させます。
///加速度センサモジュールのセットアップ
int32_t result;
float32 version;
Wire.begin();//I2C通信の準備
result = kxtj3.init();//加速度センサモジュールの初期化
if (result == KXTJ3_COMM_OK) {//通信が成功したら
(void)kxtj3.start();//加速度センサモジュールを起動
} else {
error_func(result);//通信に失敗していたらエラーメッセージを表示
}
loop部で、kxtj3.get_val()関数を呼び出すことで値を取得します。値は引数として渡した配列に、[x,y,z]の順で格納されます。
int32_t result;
float32 acc[KXTJ3_AXIS_SIZE]; //
result = kxtj3.get_val(acc); //加速度センサの値を取得
DFPlayer miniの使い方
こちらもライブラリのインストール方法は、前編の「3.動作確認」を参照してください。
宣言部で、ライブラリのインポートとインスタンスの生成を行います。DFPlayer miniはシリアル通信で命令を受け取るのですが、通常のシリアル通信はPCとArduinoの間で使用されるために、出力ピンを使うソフトウェアシリアル通信を利用します。
#include <SoftwareSerial.h> //ソフトウェアシリアルライブラリのインポート
SoftwareSerial mySoftwareSerial(10, 11); //10, 11ピンをソフトウェアシリアルで使用する
#include <DFRobotDFPlayerMini.h> //DFPlayer miniのライブラリをインポート
DFRobotDFPlayerMini myDFPlayer; //DFPlayer miniのインスタンス
setup部では、ソフトウェアシリアル通信の開始、DFPlayerとの通信開始、通信に失敗した場合のエラー表示、音量の設定をおこなっています。
//DFPlayer miniのセットアップ
mySoftwareSerial.begin(9600);
if (!myDFPlayer.begin(mySoftwareSerial)) { //DFPlayerとの通信開始
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) {
delay(0);
}
}
Serial.println(F("DFPlayer Mini online."));
myDFPlayer.volume(20); //音量( 0~30 )
音声を再生するには、play()関数を使います。引数として渡すのは、「ファイルが書き込まれた順番」です。ファイル名順ではないので注意が必要です。
myDFPlayer.play(0);//指定した書き込み順のファイルを再生する
サイコロの目を判定する
サイコロの動きが止まった時に、出目の判定をします。
加速度をバッファに保存し、バッファの平均と現在の差が一定の値を(stopTolerance)を下回ったら揺れが収まったと判断します。
//インデックスを増やし、上限を超えたら0にする
bufferIndex++;
if (bufferIndex >= bufferIndexMax) bufferIndex = 0;
//加速度をバッファに入れる
accBuffer[0][bufferIndex] = acc[0];
accBuffer[1][bufferIndex] = acc[1];
accBuffer[2][bufferIndex] = acc[2];
//差を平均する
for (int i = 0; i < bufferIndexMax; i++) {
accAve[0] += accBuffer[0][i] / bufferIndexMax;
accAve[1] += accBuffer[1][i] / bufferIndexMax;
accAve[2] += accBuffer[2][i] / bufferIndexMax;
}
//平均と現在の差
accDiff[0] = abs(accAve[0] - acc[0]);
accDiff[1] = abs(accAve[1] - acc[1]);
accDiff[2] = abs(accAve[2] - acc[2]);
//平均との差が小さくなる、つまり揺れが収まったら
if (accDiff[0] < stopTolerance && accDiff[1] < stopTolerance && accDiff[2] < stopTolerance) {
...
}
どの面が上を向いているかは、加速度センサモジュールの値を読み取り、X,Y,Zの値を場合分けで判断します。幅を持たせる事で、斜めになっていても判断することが可能です。例えば、-0.5<X<0.5、-0.5<Y<0.5、0.5<Z<1.5 の場合上を向いていることとします。
if ((-tolerance < acc[0] && acc[0] < tolerance) && (-tolerance < acc[1] && acc[1] < tolerance) && (1 - tolerance < acc[2] && acc[2] < 1 + tolerance)) {
myDFPlayer.play(1 + mode * 7);
}
配布ファイルの「TalkingDice.ino」をArduino UNOに書き込んでください。スイッチを押すとセットが切り替わり、タイトルが読み上げられます。筐体を傾けて一定時間静止すると、出目が確定し対応した音声ファイルが読み上げられるはずです。
さいごに
MDFのままでも機能しますが、筐体を緩衝材で包み、フェルトで作ったカバーを被せてみました。カラフルになり楽しい雰囲気がでましたね。
今回は、ロームセンサ評価キットの加速度センサモジュールとDFPlayer miniを使って、出目に応じて音声を再生するおしゃべりサイコロを作りました。好きな音楽をランダム再生したり、自分で音声を録音してテーマを作ってみてはいかがでしょうか。
それではサイコロまかせの気ままな日常を楽しみましょう!
今回の連載の流れ
前編:加速度センサとMP3プレイヤーで作るおしゃべりサイコロ
後編:加速度センサとMP3プレイヤーで作るおしゃべりサイコロ(今回)