Arduinoのソースコード(mugbot_arduino)の解説です。
このソースコードはArduino専用の言語で書かれており、拡張子は「ino」になっています。
server(mugbot_server)から送られてきたコマンドを読み取って、そのコマンドを実行します。LEDやサーボが動くのはこのソースコードの働きです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <Servo.h> //Mugbot Project Tokyo City University Koike Lab. 2014 //Mugbot System ver. 1.0.0. Servo eye_servo; Servo head_servo; static int pos = 0; //Arduinoのサーボの回転角度 static int g = 0; //Webのスライダーの位置 char ch=0; int l_mouse=7; //口LED左部(正面から見て) int m_mouse=8; //口中央LED(正面から見て) int r_mouse=9; //口LED右部(正面から見て) int l_eye=11; //左目(正面から見て) int r_eye=13; //右目(正面から見て) int eye_default = 90; //目の正面位置を設定 int eye_min = 75; //目の最小位置を設定 int eye_max = 105; //目の最大位置を設定 int head_default = 90; //首の正面位置を設定 int head_min = 0; //首の最小角度を設定 int head_max = 180; //首の最大角度を設定 int eye_light_default = 50; //目の明るさの通常値を設定 |
それぞれのLEDとサーボの初期設定をしています。
例えば、「int l_mouse=7;」は「l_mouse」を「7」と設定するということです。ソースコード上で「l_mouse」と入力されているところは7という値を代入することを定義しています。
また、同じように「int eye_default=90;」は目のサーボの正面位置を90に設定し、ソースコード上で「eye_default」と入力されているところは90という値を代入することを定義しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void setup() { Serial.begin(9600); eye_servo.attach(2); //サーボ 目の上下 head_servo.attach(4); //サーボ 首の左右 //目、首、目の明るさの初期設定 pinMode(l_eye, OUTPUT); pinMode(r_eye, OUTPUT); pinMode(l_mouse, OUTPUT); pinMode(m_mouse, OUTPUT); pinMode(r_mouse, OUTPUT); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); digitalWrite(l_mouse, LOW); digitalWrite(m_mouse, LOW); digitalWrite(r_mouse, LOW); eye_servo.write(eye_default); head_servo.write(head_default ); } |
setup( )はスケッチがスタートしたときに1度だけ呼び出される部分で、ピンモードやライブラリの初期化などを行っています。
「attach」というのは、「サーボ名.attach(ピン番号)」でサーボを割り当てるピンを設定しています。
(例 eye_servo.attach(2)というのは、eye_servoは2番ピンに接続されているということです。)
「pinMode」というのは、「pinMode(ピン番号, 入力もしくは出力)」で、そのピンが入力ピンなのか出力ピンなのかを設定しています。
(例 pinMode(l_eye, OUTPUT)というのは、l_eye(上で定義したように11)ピンはOUTPUT(出力)に設定するということです。)
「analogWrite」というのは、「analogWrite(ピン番号,値)」で、そのピンに接続されているLEDをどのくらいの明るさにするのかを設定しています。
(例 analogWrite(l_eye,eye_light_default)というのは、l_eye(上で定義したように11)ピンをeye_light_default(上で定義したように50)の明るさに設定するということです。)
「digitalWrite」というのは、「digitalWrite(ピン番号,HIGHまたはLOW)」で、そのピンに接続されているLEDを5Vにするのか0Vにするのかを設定しています。
(例 digitalWrite(l_mouse, LOW)というのは、l_mouse(上で定義したように7)ピンをLOW(0V=光らせない)に設定するということです。)
「write」というのは、「サーボ名.write(角度)」で、サーボをどの角度にするのか設定しています。
(例 eye_servo.write(eye_default)というのは、eye_servoをeye_default(上で定義したように90)に向けるということです。)
1 2 3 4 5 6 7 8 9 10 11 |
void loop(){ if(Serial.available()>0){ ch = Serial.read(); switch(ch) { case '0'...'9': g = g * 10 + ch - '0'; //例えば100Xの文字がRaspberry Piから来ると1文字ずつ読み込む //1、0、0を順に読み込んで数字の100にして変数に格納する。 break; |
loop( )には実行したいプログラムを書きます。その名のとおり、この部分に書かれた内容は繰り返し実行されます。
「if(serial.available( )>0)」というのは、もしも受信データがあるならば以下の内容を実行するという意味です。
「ch = serial.read();」で受信したデータを読み込み、その値を「ch」に代入します。
「switch文」で「ch」の値がそれぞれの「caseの値」だった場合、その「case」の内容を実行します。(例 「ch」の中身が0〜9の数字だった場合、その数字を順番に読み込んで、「1・0・0」というぶつ切りの数字ではなく、「100」のようにひとつの数字に変換して「g」に代入する。)breakまでいくとswitch文を抜けて、ループに戻ります。
1 2 3 4 5 6 7 |
case 'x': //Rasberry Piからxを受け取ると首を左右に運動。 head_servo.write( g ); //次にxを読み込むと変数gに入った100でサーボの角度を変える。 delay( 15 ); g=0; //gを0にして初期化 break; |
もしも「x」を受け取った場合は、サーボを 「g」の値の角度に向け、少し待った後に「g」を0に初期化してループに戻ります。
「delay」というのはその時間の分だけ待つということです。
1 2 3 4 5 |
case 'y': //Rasberry Piからyを受け取ると目を上下に運動。 eye_servo.write( g ); delay( 15 ); g=0; break; |
もしも「y」を受け取った場合は、サーボを 「g」の値の角度に向け、少し待った後に「g」を0に初期化してループに戻ります。
1 2 3 4 5 6 |
case 'z': //Rasberry Piからzを受け取ると目の明るさを変調。 analogWrite(l_eye,g); analogWrite(r_eye,g); delay( 15 ); g=0; break; |
もしも「z」を受け取った場合は、LEDの明かりを 「g」の値にし、少し待った後に「g」を0に初期化してループに戻ります。
「発話」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
case 't': //Rasberry Piからtを受け取ると口が点滅し、発話時の動作を行う。 delay( 2000 ); digitalWrite(l_mouse, HIGH); digitalWrite(m_mouse, HIGH); digitalWrite(r_mouse, HIGH); for ( pos = eye_default; pos < 110; pos += 1 ) { eye_servo.write( pos ); delay( 15 ); } ; for ( pos = 110; pos > 80; pos -= 1 ) { eye_servo.write( pos ); delay( 15 ); } ; for ( pos = 80; pos < eye_default; pos += 1 ) { eye_servo.write( pos ); delay( 15 ); } ; break; |
もしも「t」を受け取った場合は、口のLEDを点灯させ、目を上下に動かします。
「for ( pos = eye_default; pos < 110; pos += 1)」というのは初期値がeye_default(90)で、その90に数字を1ずつ足していき、posの値が110を超えるまで{ }の中の内容を実行するということなので、posが110になるまで、eye_servoの角度をposの値にするということです。
他のfor文も値は違いますが同じことをしています。
ただし、pos -= 1の場合は数字を1ずつ足していくのではなく、減らしていきます。
「初期値に戻る」の動作
1 2 3 4 5 6 7 8 9 10 |
case 'n': //Rasberry Piからnを受け取ると首、目の標準位置に戻す。 analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); digitalWrite(r_mouse, LOW); digitalWrite(l_mouse, LOW); digitalWrite(m_mouse, LOW); eye_servo.write(eye_default); head_servo.write(head_default); break; |
もしも「n」を受け取った場合は、全ての値を初期設定値に戻します。
「笑う」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
case 'l': //Rasberry Piからlを受け取ると「笑う」のアクションを行う。 analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); digitalWrite(l_mouse, HIGH); digitalWrite(m_mouse, HIGH); digitalWrite(r_mouse, HIGH); eye_servo.write( 120 ); delay(100 ); eye_servo.write( 100 ); delay(100 ); eye_servo.write( 120 ); delay(100 ); eye_servo.write( 100 ); delay(100 ); eye_servo.write( 120 ); delay(100 ); eye_servo.write( 100 ); delay(100 ); eye_servo.write( 120 ); delay(100 ); eye_servo.write( 100 ); delay(100 ); eye_servo.write( 120 ); delay(100 ); eye_servo.write( 100 ); delay(100 ); eye_servo.write( 120 ); delay(100 ); eye_servo.write( 100 ); delay(100 ); eye_servo.write( 120 ); delay(100 ); eye_servo.write( 100 ); delay(100 ); eye_servo.write( 120 ); delay(100 ); eye_servo.write( eye_default ); delay(100 ); digitalWrite(r_mouse, LOW); digitalWrite(l_mouse, LOW); digitalWrite(m_mouse, LOW); break; |
もしも「l」を受け取った場合は、口を点灯させ、目を上下運動させます。上下運動が終わったら、口の点灯を止めます。
「悲しい」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
case 's': //Rasberry Piからsを受け取ると「悲しい」のアクションを行う。 for ( pos = eye_default; pos > 70; pos -= 1 ) { eye_servo.write( pos ); delay( 15 ); } ; for ( pos = eye_light_default; pos > 20; pos -= 1 ) { analogWrite(l_eye, pos); analogWrite(r_eye, pos); delay( 10); } ; eye_servo.write(eye_default); head_servo.write(head_default); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); digitalWrite(r_mouse, LOW); digitalWrite(l_mouse, LOW); digitalWrite(m_mouse, LOW); break; |
もしも「s」を受け取った場合は、目を下げ、目の明るさを小さくしていきます。終わると元の状態に戻ります。
「はい」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
case 'h': //Rasberry Piからhを受け取ると「はい」のアクションを行う。 analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); for ( pos = eye_default; pos > 70; pos -= 1 ) { eye_servo.write( pos ); delay( 15 ); } ; for ( pos = 70; pos < eye_default; pos += 1 ) { eye_servo.write( pos ); delay( 15 ); eye_servo.write( pos ); delay( 15 ); } ; for ( pos =eye_default; pos > 70; pos -= 1 ) { eye_servo.write( pos ); delay( 15 ); } ; for ( pos = 70; pos < eye_default; pos += 1 ) { eye_servo.write( pos ); delay( 15 ); eye_servo.write( pos ); delay( 15 ); } ; break; |
もしも「h」を受け取った場合は、目を上下に動かします。
「いいえ」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
case 'f': //Rasberry Piからfを受け取ると「いいえ」のアクションを行う。 analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); for ( pos = 85; pos < 135; pos += 1 ) { head_servo.write( pos ); delay( 15 ); } ; for ( pos = 135; pos > 55; pos -= 1 ) { head_servo.write( pos ); delay( 15 ); } ; for ( pos = 55; pos < 85; pos += 1 ) { head_servo.write( pos ); delay( 15 ); } ; break; |
もしも「f」を受け取った場合は、首を左右に動かします。
「ウィンク」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 |
case 'w': //Rasberry Piからwを受け取ると「ウインク」 のアクションを行う。 analogWrite(l_eye, eye_light_default); digitalWrite(r_eye, LOW); delay( 500 ); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); delay( 500 ); digitalWrite(l_eye,LOW); analogWrite(r_eye, eye_light_default); delay( 500 ); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); break; |
もしも「w」を受け取った場合は、目を交互に点灯させます。
「びっくり」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
case 'b': //Rasberry Piからwを受け取ると「びっくり」のアクションを行う。 for ( pos = eye_default; pos < 105; pos += 1 ) { eye_servo.write( pos ); delay( 15 ); } ; analogWrite(l_eye, 250); analogWrite(r_eye, 250); delay( 350 ); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); delay( 100 ); eye_servo.write(eye_default); delay( 100 ); break; |
もしも「b」を受け取った場合は、目を上げ、目の光を大きくします。終わると元の状態に戻ります。
「ハイテンション」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
case 'e': //Rasberry Piからeを受け取ると「ハイテンション」のアクションを行う。 for ( ch = 0; ch <5; ch += 1 ) { digitalWrite(l_mouse, HIGH); digitalWrite(m_mouse, HIGH); digitalWrite(r_mouse, HIGH); analogWrite(l_eye, eye_light_default); digitalWrite(r_eye, LOW); delay( 100 ); digitalWrite(l_eye, LOW); analogWrite(r_eye, eye_light_default); delay( 100 ); eye_servo.write(random(eye_default,110) ); head_servo.write(random(25,135) ); delay( 100 ); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); delay( 100 ); digitalWrite(l_mouse, LOW); digitalWrite(m_mouse, LOW); digitalWrite(r_mouse, LOW); delay( 100 ); } eye_servo.write(eye_default); head_servo.write(head_default); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); digitalWrite(r_mouse, LOW); digitalWrite(l_mouse, LOW); digitalWrite(m_mouse, LOW); break; |
もしも「e」を受け取った場合は、口を点灯させ、目を交互に点灯させ、首を上下左右に動かします。終わると元の状態に戻ります。
「上記以外のコマンドが入力された時」の動作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
default: eye_servo.write(eye_default); head_servo.write(head_default); analogWrite(l_eye, eye_light_default); analogWrite(r_eye, eye_light_default); digitalWrite(r_mouse, LOW); digitalWrite(l_mouse, LOW); digitalWrite(m_mouse, LOW); break; } } } |
上記以外を受け取った場合は、初期設定値のままにします。
以上でArduinoのソースコード(mugbot_arduino)の解説を終了します。