ぬいぐるみが動いて話し相手になって欲しかった
作りたいもの
- ぬいぐるみが動いてほしい
- ぬいぐるみがしゃべって欲しい
- ぬいぐるみとおしゃべりしたい
- もふもふしたい
今回はぬいぐるみにPraspberryPizeroを入れて動いてしゃべらせる+スマートフォンとBluetoothで通信することでしゃべる内容を送信する
材料
- RaspberryPizero
- Bluetoothドングル
- MiniHDMIから音声出力端子付きVGA変換ケーブル
- スピーカー
- サーボモーター
- 段ボールの切れ端
- ぬいぐるみに詰めるもの(モフモフさせるため)
- Androidスマートフォン
作り方
ぬいぐるみ編(ハード)
- スピーカー
- スピーカーはあらかじめ内臓電池を抜いてRaspberryPizeroから給電で動作するように改造
- 音声は音声出力端子付きVGAケーブルにオーディオケーブルを接続して再生
- サーボモーター
- RaspberryPizeroはPWMに対応しているピンが2本しかないため別途モジュールを接続しない場合はモーターは2つが限界
- 13,18ピンにサーボモーターの信号線を接続
- サーボモータは全身の動き用と手を動かす用に利用
- 組み合わせる
- ぬいぐるみに入るようにセロテープと段ボールでまとめる
- ぬいぐるみに詰める
- ぬいぐるみに適度なモフモフ感を出すために隙間に詰め物を入れる(今回は電子部品を買ったときについてきたビニール袋詰めた)
ぬいぐるみ編(ソフト)
- RaspberryPizeroの設定
- OSはRaspbian
-
以下の記事を参考にBluetoothのシリアル通信を設定
rfcomm-server.c#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <bluetooth/bluetooth.h> #include <bluetooth/rfcomm.h> int main(int argc, char **argv) { char synth_buf[2048]={ 0 }; struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 }; char buf[2048] = { 0 }; int s, client, bytes_read; socklen_t opt = sizeof(rem_addr); // allocate socket s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); // bind socket to port 1 of the first available // local bluetooth adapter loc_addr.rc_family = AF_BLUETOOTH; loc_addr.rc_bdaddr = *BDADDR_ANY; loc_addr.rc_channel = (uint8_t) 1; bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr)); // put socket into listening mode listen(s, 1); // accept one connection client = accept(s, (struct sockaddr *)&rem_addr, &opt); ba2str( &rem_addr.rc_bdaddr, buf ); fprintf(stderr, "accepted connection from %s\n", buf); while(1) { memset(buf, 0, sizeof(buf)); // read data from the client bytes_read = read(client, buf, sizeof(buf)); if(strcmp(buf,"exit")==0) { sprintf(synth_buf,"sh /home/pi/Program/Control.sh ばいばーい,0"); system(synth_buf); break; } if( bytes_read > 0 ) { printf("received [%s]\n", buf); sprintf(synth_buf,"sh /home/pi/Program/Control.sh %s",buf); system(synth_buf); } } // close connection close(client); close(s); return 0; }
-
WiringPiでサーボモーターの制御
- WiringPiのインストール方法は割愛
servo.c#include <iostream> #include <stdlib.h> #include <wiringPi.h> int main(int argc,char **argv) { if (wiringPiSetupGpio() == -1) { std::cout << "cannot setup gpio." << std::endl; return 1; } pinMode(13, PWM_OUTPUT); pinMode(18, PWM_OUTPUT); pwmSetMode(PWM_MODE_MS); pwmSetClock(400); pwmSetRange(1024); int num,servo; servo = atoi((const char*)argv[1]); num = atoi((const char*)argv[2]); if(servo==0)pwmWrite(13, num); else pwmWrite(18, num); return 0; }
g++ <.cファイル> -o <出力ファイル> -lwiringPi
-
音声合成Open JTalkの制御
- Open JTalkのインストール方法は割愛
synth.shTMP=/tmp/test.wav echo "$1" | open_jtalk -m /home/pi/Program/Voice/rou.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow $TMP && \ aplay --quiet $TMP rm -f $TMP
- ディスプレイを接続していないとHDMI出力してくれない場合(音声が出力されない)
- /boot/config.txtのhdmi_driver=2をコメントアウト
sudo vim /boot/config.txt
-
Bluetoothシリアル通信プログラムrfcomm-serverを起動時実行プログラムとして登録
- /etc/rc.localの
exit 0
の手前に実行プログラムを記述 - Bluetoothシリアル通信からサーボモータと音声合成プログラムを実行するスクリプトを作成
- /etc/rc.localの
Control.sh
TEXT=`echo $1 | cut -d"," -f1`
COMMAND=`echo $1 | cut -d"," -f2`
echo "text $TEXT"
sh /home/pi/Program/Voice/synth.sh $TEXT
echo "command $COMMAND"
# 手を振る
if [ $COMMAND -eq 0 ]
then
sudo /home/pi/Program/Servo/servo 1 70
sleep 1s
sudo /home/pi/Program/Servo/servo 1 110
sleep 1s
sudo /home/pi/Program/Servo/servo 1 70
sleep 1s
sudo /home/pi/Program/Servo/servo 1 110
# お辞儀
elif [ $COMMAND -eq 1 ]
then
sudo /home/pi/Program/Servo/servo 0 110
sleep 1s
sudo /home/pi/Program/Servo/servo 0 80
sleep 2s
sudo /home/pi/Program/Servo/servo 0 110
# ノーマル
else
sudo /home/pi/Program/Servo/servo 0 110
sleep 1s
sudo /home/pi/Program/Servo/servo 1 110
fi
Androidアプリ編
- AndroidStudioを利用
- 以下の記事を参考にAndroidアプリを作成
- RaspberryPizeroでbluetoothシリアル通信をする方法
- RaspberryPizeroとペアリングしてシリアル通信を行えるようにしておく
実行
- RaspberryPizeroを起動しAndroidからBluetoothChatアプリを実行
- BluetotthでRaspberryPizeroと接続しテキストボックスにしゃべらせたい文章を入力
RaspberryPizeroぬいぐるみがしゃべって動いたら成功
しゃべるRaspberryPiぬいぐるみ
— アキヒロ (@akihiro01051) 2016年9月12日
その1 pic.twitter.com/pN7W6FVVPY
- メインのサーボモータが全体を動かす
メインのサーボで上下に動く pic.twitter.com/QtYCKbBRWH
— アキヒロ (@akihiro01051) 2016年9月19日
- サブのサーボモータが腕を動かす
サブのサーボで手が動く pic.twitter.com/P5B2MxSFbS
— アキヒロ (@akihiro01051) 2016年9月19日
今後の課題
- もろい(スピーカーが接触不良で鳴らない時がある)
- もろい(段ボールとセロテープだからすぐはがれる)
- モフモフしない(ビニール袋の感触がする)