RaspberryPizeroぬいぐるみの作り方

# ぬいぐるみが動いて話し相手になって欲しかった
## 作りたいもの
- ぬいぐるみが動いてほしい
- ぬいぐるみがしゃべって欲しい
- ぬいぐるみとおしゃべりしたい
- もふもふしたい

今回はぬいぐるみにPraspberryPizeroを入れて動いてしゃべらせる＋スマートフォンとBluetoothで通信することでしゃべる内容を送信する

## 材料
- RaspberryPizero
- Bluetoothドングル
- MiniHDMIから音声出力端子付きVGA変換ケーブル
- スピーカー
- サーボモーター
- 段ボールの切れ端
- ぬいぐるみに詰めるもの(モフモフさせるため)
- Androidスマートフォン

## 作り方
### ぬいぐるみ編(ハード)
- スピーカー
    - スピーカーはあらかじめ内臓電池を抜いてRaspberryPizeroから給電で動作するように改造
    - 音声は音声出力端子付きVGAケーブルにオーディオケーブルを接続して再生
- サーボモーター
    - RaspberryPizeroはPWMに対応しているピンが2本しかないため別途モジュールを接続しない場合はモーターは2つが限界
    - 13,18ピンにサーボモーターの信号線を接続
    - サーボモータは全身の動き用と手を動かす用に利用

![DSC_0799.JPG](https://qiita-image-store.s3.amazonaws.com/0/86283/1e742e4b-6301-3438-2afe-affd2a7739aa.jpeg)



- 組み合わせる
    - ぬいぐるみに入るようにセロテープと段ボールでまとめる

![DSC_0792.JPG](https://qiita-image-store.s3.amazonaws.com/0/86283/5c512b89-25a1-24a3-414b-b12cbdffcdfc.jpeg)
![DSC_0793.JPG](https://qiita-image-store.s3.amazonaws.com/0/86283/23c8f022-aa4b-5f06-d18f-1138340e689c.jpeg)

- ぬいぐるみに詰める
    - ぬいぐるみに適度なモフモフ感を出すために隙間に詰め物を入れる(今回は電子部品を買ったときについてきたビニール袋詰めた)

![DSC_0789.JPG](https://qiita-image-store.s3.amazonaws.com/0/86283/78c216d7-2dba-2043-23be-885ab1990600.jpeg)


### ぬいぐるみ編(ソフト)
- RaspberryPizeroの設定
- OSはRaspbian
- 以下の記事を参考にBluetoothのシリアル通信を設定
    - [RaspberryPizeroでbluetoothシリアル通信をする方法](http://qiita.com/akihiro01051/items/2f8336985f15f8d1b131)

    ``` 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;
}
```

    ``` bash
g++ <.cファイル> -o <出力ファイル> -lwiringPi
```

- 音声合成Open JTalkの制御
    - Open JTalkのインストール方法は割愛

    ``` synth.sh
TMP=/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をコメントアウト
 
    ``` bash
    sudo vim /boot/config.txt
    ```

- Bluetoothシリアル通信プログラム__rfcomm-server__を起動時実行プログラムとして登録
    - /etc/rc.localの```exit 0```の手前に実行プログラムを記述
    - Bluetoothシリアル通信からサーボモータと音声合成プログラムを実行するスクリプトを作成

``` 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ぬいぐるみがしゃべって動いたら成功
<blockquote class="twitter-video" data-lang="ja"><p lang="ja" dir="ltr">しゃべるRaspberryPiぬいぐるみ<br>その1 <a href="https://t.co/pN7W6FVVPY">pic.twitter.com/pN7W6FVVPY</a></p>&mdash; アキヒロ (@akihiro01051) <a href="https://twitter.com/akihiro01051/status/775345525218435072">2016年9月12日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

- メインのサーボモータが全体を動かす

<blockquote class="twitter-video" data-lang="ja"><p lang="ja" dir="ltr">メインのサーボで上下に動く <a href="https://t.co/QtYCKbBRWH">pic.twitter.com/QtYCKbBRWH</a></p>&mdash; アキヒロ (@akihiro01051) <a href="https://twitter.com/akihiro01051/status/777803443171758081">2016年9月19日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

- サブのサーボモータが腕を動かす

<blockquote class="twitter-video" data-lang="ja"><p lang="ja" dir="ltr">サブのサーボで手が動く <a href="https://t.co/P5B2MxSFbS">pic.twitter.com/P5B2MxSFbS</a></p>&mdash; アキヒロ (@akihiro01051) <a href="https://twitter.com/akihiro01051/status/777803751121760256">2016年9月19日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

## 今後の課題
- もろい(スピーカーが接触不良で鳴らない時がある)
- もろい(段ボールとセロテープだからすぐはがれる)
- モフモフしない(ビニール袋の感触がする)