【Arduino】スピーカーを使ってロボットの鳴き声を作る!
突然ですが、私がロボットを好きになったきっかけの1つがスターウォーズのR2-D2です。
実際に喋ることはできないのに、音だけで不思議と感情が伝わりませんか?
今回はロボットの鳴き声を作ってみましょう。
自分のロボットにますます愛着がわくと思います!
- スピーカーと音の仕組み
- スピーカーの使い方
- ロボットの鳴き声の作り方
私のブログで登場するロボットはArduinoを搭載した車輪ロボット「NR-02」です。
下記記事のArduinoを始めるならこれを買えばOKの見出しで必要なパーツを紹介しています。
解説動画
今回の記事はこちらの動画をまとめたものです。
鳴き声なし/ありのかわいさ比較
実際にロボットの鳴き声を付けたものを動かしています。
(↓鳴き声のなし/ありのロボットを動かしている部分から再生されます。)
どうでしょうか?
鳴き声があると一気にロボットが可愛くなりますね。
ピロピロ鳴いて可愛い!
スピーカーの仕組みと作り方を紹介していきます!
スピーカーと音の仕組み
なんでスピーカーから音が聞こえるんだろう?
そう思ったことはありませんか。
ご存知の方もいらっしゃるとは思いますが、
1.スピーカーが高速で振動して空気が波打つ
2.空気の波が耳に伝わって音が聞こえる
という仕組みです。
スピーカーのタイプ2種類紹介
スピーカーには色々な種類があります。
今回は秋月電子通商で購入ができる2種類を紹介します。
圧電素子タイプ
中に金属が貼り合わされた薄い板が入っています。
電圧がかかることで、その板がカーブします。
電圧のON/OFFを繰り返すことで、板がカーブ/真っ直ぐを繰り返します。
それが空気中に波として伝わり、音になるという仕組みです。
音はこんな音が出ます。
(↓圧電素子タイプのスピーカー音部分から再生されます。)
メロディーを奏でるというよりは、警告音などのブザーに使われることが多いです。
Amazonや楽天でも圧電素子タイプのスピーカーの取り扱いがあります。
ダイナミック(電磁石)タイプ
中にコイルと磁石が入っています。
コイルに電流が流れることで、電流の向き・磁界の向き(磁石の力)・力の向きが決まるというフレミングの左手の法則を用いてます。
その力が振動となり、音になるという仕組みです。
音はこんな音が出ます。
(↓ダイナミックタイプのスピーカー音部分から再生されます。)
圧電素子と違いは分かりましたか?
本当は音が大きくてキレイだったダイナミックタイプのスピーカーを用いて、鳴き声を作りたいのですが、ロボットに乗せるにはサイズが大きいので、今回は圧電スピーカーをロボットに搭載します!
ダイナミックスピーカーもネットショップでの取り扱いがあります。
どんなものでもいいのですが、できれば導線が付いているもののほうがすぐに使えて楽ですよ!
スピーカーの使い方
では実際にどのように使えばいいのか、解説していきます。
スピーカーの回路
回路はシンプルです。
スピーカーから出てくる2本の線を、片方は信号が出てくる線に、もう片方はグランドに繋ぎます。
今回は12番に繋ぐことにしました。
スピーカーのプログラム
tone関数を使います。
tone以降の()内について説明します。
12:スピーカーの線をつないだピン番号
私は回路のところで説明したようにグランドではない方の線を12番に繋いでいます。
そのため今回は12と書きました。
262:周波数(音の高さ)[Hz]
どの高さの音を出すか記入しています。
数字が大きくなれば高い音に、数字が小さくなれば低い音になります。
【音 周波数】で検索すると、出したい高さの音の周波数が分かりますよ!
200:音の長さ[ms]
単位はミリ秒です。
200msの場合は、0.2秒ということになります。
つまり12番に繋いだ線に262Hzの周波数の音を200ms出す指令をする、という意味です。
delayがあることで、次の処理に進むまでに指定時間待ってくれます。
もしなければ次の動きが始まってしまうので、tone関数を続けて使ってメロディーを奏でるときはdelayが必要です。
ロボットの鳴き声を作る
- ハッピー HAPPY
- 怒り ANGER
- 起きた WAKEUP
の3種類を作ります。
ソースコード
ソースコードは以下の通りです。
1#define HAPPY 1 //ハッピー
2#define ANGER 2 //怒り
3#define WAKEUP 3 //起きる
4
5const int PIN_MOTOR_L_A = 6; //左モータA
6const int PIN_MOTOR_L_B = 9; //左モータB
7const int PIN_MOTOR_R_A = 5; //右モータA
8const int PIN_MOTOR_R_B = 3; //右モータB
9const int PIN_BUTTON = 8; //押しボタンスイッチ
10const int PIN_SPEAKER = 12; //スピーカー
11const int BEAT = 200;
12
13void sing(int emotion) {
14 if (emotion == HAPPY) {
15 tone(PIN_SPEAKER,1760,BEAT / 2) ; // ラ
16 delay(BEAT / 2) ;
17 tone(PIN_SPEAKER,1976,BEAT / 2) ; // シ
18 delay(BEAT / 2) ;
19 tone(PIN_SPEAKER,1760,BEAT / 2) ; // ラ
20 delay(BEAT / 2) ;
21 tone(PIN_SPEAKER,1976,BEAT / 2) ; // シ
22 delay(BEAT / 2) ;
23 }
24 if (emotion == ANGER) {
25 tone(PIN_SPEAKER,247,BEAT / 2) ; // シ
26 delay(BEAT / 2) ;
27 tone(PIN_SPEAKER,247,BEAT / 2) ; // シ
28 delay(BEAT / 2) ;
29 }
30 if (emotion == WAKEUP) {
31 tone(PIN_SPEAKER,1047,BEAT) ; // ド
32 delay(BEAT) ;
33 tone(PIN_SPEAKER,1319,BEAT) ; // ミ
34 delay(BEAT) ;
35 tone(PIN_SPEAKER,1175,BEAT * 2) ; // レ
36 delay(BEAT * 2) ;
37 }
38}
39
40//前進
41void moveForward(int power, int duration) {
42 analogWrite(PIN_MOTOR_L_A, power); //左A
43 analogWrite(PIN_MOTOR_L_B, 0); //左B
44 analogWrite(PIN_MOTOR_R_A, power); //右A
45 analogWrite(PIN_MOTOR_R_B, 0); //右B
46 delay(duration);
47}
48
49//後退
50void moveBackward(int power, int duration) {
51 analogWrite(PIN_MOTOR_L_A, 0); //左A
52 analogWrite(PIN_MOTOR_L_B, power); //左B
53 analogWrite(PIN_MOTOR_R_A, 0); //右A
54 analogWrite(PIN_MOTOR_R_B, power); //右B
55 delay(duration);
56}
57
58//右旋回
59void turnRight(int power, int duration) {
60 analogWrite(PIN_MOTOR_L_A, power); //左A
61 analogWrite(PIN_MOTOR_L_B, 0); //左B
62 analogWrite(PIN_MOTOR_R_A, 0); //右A
63 analogWrite(PIN_MOTOR_R_B, power); //右B
64 delay(duration);
65}
66
67//左旋回
68void turnLeft(int power, int duration) {
69 analogWrite(PIN_MOTOR_L_A, 0); //左A
70 analogWrite(PIN_MOTOR_L_B, power); //左B
71 analogWrite(PIN_MOTOR_R_A, power); //右A
72 analogWrite(PIN_MOTOR_R_B, 0); //右B
73 delay(duration);
74}
75
76//ブレーキ
77void stopBreak(int duration) {
78 digitalWrite(PIN_MOTOR_L_A, LOW); //左A
79 digitalWrite(PIN_MOTOR_L_B, LOW); //左B
80 digitalWrite(PIN_MOTOR_R_A, LOW); //右A
81 digitalWrite(PIN_MOTOR_R_B, LOW); //右B
82 delay(duration);
83}
84
85//フリー
86void stopFree(int duration) {
87 digitalWrite(PIN_MOTOR_L_A, HIGH); //左A
88 digitalWrite(PIN_MOTOR_L_B, HIGH); //左B
89 digitalWrite(PIN_MOTOR_R_A, HIGH); //右A
90 digitalWrite(PIN_MOTOR_R_B, HIGH); //右B
91 delay(duration);
92}
93
94void setup() {
95 //ピンの出力(Output)or入力(Input)設定
96 pinMode(PIN_MOTOR_L_A, OUTPUT); //左モータA
97 pinMode(PIN_MOTOR_L_B, OUTPUT); //左モータB
98 pinMode(PIN_MOTOR_R_A, OUTPUT); //右モータA
99 pinMode(PIN_MOTOR_R_B, OUTPUT); //右モータB
100 pinMode(PIN_BUTTON, INPUT); //スイッチ
101
102 sing(WAKEUP); //起動完了の鳴き声
103
104 //スタートボタンを押されるのを待つ
105 while(digitalRead(PIN_BUTTON)==0);
106 delay(1000); //1秒待つ
107}
108
109void loop() {
110 int sensor_value; //距離センサの値
111
112 sensor_value = analogRead(A0); //センサの値を読み取る
113 if (sensor_value < 270) {
114 //270より小さい場合(遠い場合)
115 moveForward(255, 10);
116 } else {
117 stopBreak(500);
118 sing(ANGER);
119 moveBackward(127, 500);
120 turnRight(127, 500);
121 stopBreak(500);
122 sing(HAPPY);
123 }
124
125}
詳しい解説
このソースコードでスピーカーに関する部分を詳しく解説します。
まずは#defineで感情を定数で定義しています。
HAPPYは1、ANGERは2、WAKEUPは3と定義しました。
const intでスピーカーのピン番号を12と定義しましょう。
また、BEATという関数をつくり、1つの音の長さを200としておきましょう。
鳴き声の関数としてsingという関数を作りました。
singの引数をemotionとし、emotionにHAPPYやANGERが入ってきます。
(このHAPPYやANGERは最初に定数で定義しているのでint型です。)
もしもemotionがHAPPYの場合は、高い音でラシラシと鳴くようにします。
ここで先ほど説明したtone関数を使います。音の長さはBEATの200msの半分にしたければ、BEAT / 2で半分の100msにできます!
鳴き声部分はぜひ自分のセンスを活かして、ロボットの気持ちを表現してみましょう!
ピンの入出力設定が終わったら、さっそくsing(WAKEUP)で鳴いてもらいましょう。
障害物があるか否かを測距センサ―で読み取り、障害物がなければ前進します。
測距センサ―についてはこちらの記事で詳しく解説しています!
障害物があった場合は停止してsing(ANGER)で鳴きます。
その後バックして方向転換したら障害物がないということでsing(HAPPY)で鳴くようにしましょう!
ロボットの動作
実際にこのプログラムでロボットを動かしてみましょう。
(↓ロボットの動作部分から再生されます。)
鳴き声があるとますます愛着がわきますね♡
まとめ
今回の記事ではロボットに鳴き声を実装させる仕組みを説明しました。
みなさんも自分のロボットにオリジナルの鳴き声を作ってあげてください!
鳴き声が完成したら、CHAに(@CHAfreeschool )見せてくださいね!
- スピーカーと音の仕組み
- スピーカーの使い方
- ロボットの鳴き声の作り方
鳴き声に合わせて気持ちをフルカラーLEDで表現してみました。
ぜひあなたのロボットにもこの機能を付け足してみてくださいね!
プログラミングをしていると出てくる「変数」や「関数」などのワード理解していますか?
こちらの記事で変数について詳しく解説しています。
理解度がまだだな…って人は一度勉強しましょう。
ものづくりって面白い!
最後まで読んでいただき、ありがとうございました!
以上、CHAでした!