Raspberry Piに360度回転するサーボモーターを取り付けて移動できるようにする

## 趣旨 : ラズパイを移動できるようにしよう!
Raspberry Piを移動できるようにすると、作れるモノが増えて楽しいです。移動できるようにするためには、ロボットキットなどを購入する方法もありますが、部品をいくつか購入して、自作することもできます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/41825/57cbf09a-1608-5178-d0e1-9b2d10e95d12.jpeg" width="320">

## 作業手順
1. Raspberry Piの初期設定 (他にたくさん記事があるので、ここでは書きません)
2. 必要な部品をそろえる
3. ボディの作成
4. GPIOの制御
5. おまけ (Flaskでウェブから操作できるようにする)

## 2. 必要な部品をそろえる
**必要な部品**
- Raspberry Pi
- MicroSDカード
- [Raspberry Pi用ケース](https://jp.rs-online.com/web/p/products/9084212/?grossPrice=Y&cm_mmc=JP-PLA-DS3A-_-google-_-PLA_JP_JP_Enclosures_Storage_And_Material_Handling-_-%E3%82%A8%E3%83%B3%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3-_-PRODUCT_GROUP&matchtype=&aud-386392066544:pla-331391750075&gclid=Cj0KCQiAg_HhBRDNARIsAGHLV52p5dY5BwVbA6_VYhFuz1ZvanNnzOvbMmu9D2YKDW__Oj4cvSRPuXQaAs0QEALw_wcB&gclsrc=aw.ds)
- [バッテリー(Anker PowerCore 10000)](https://www.amazon.co.jp/gp/product/B019GNUT0C/ref=ppx_yo_dt_b_asin_title_o00__o00_s00?ie=UTF8&psc=1)
- MicroUSBケーブル
- MDF4mm
- [タイヤ付き360度サーボモーター(FS90R)](https://www.amazon.co.jp/dp/B077JFCPCX/ref=asc_df_B077JFCPCX2567967/?tag=jpgo-22&creative=9339&creativeASIN=B077JFCPCX&linkCode=df0&hvadid=220251940262&hvpos=1o2&hvnetw=g&hvrand=17990446782124703963&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009331&hvtargid=pla-486861865084)
- M3-10mmトラスネジ x 4
- M3ナット x 4
- M2-10小ネジ x 4
- M2ナット x 4

Raspberry Piを持っていれば、追加で購入するのは、Raspberry Pi用のケース、モバイルバッテリー、360度サーボモーター、ネジ類です。

## 3. ボディの作成
[Githubのページ](https://github.com/miokato/PiBot)にボディのデータを置いているのでお使いください。ボディのデータはpdfになっているので、このデータをレーザー加工業者に渡すか、レーザー加工サービスが利用できる場所で加工します。素材は厚さが4mmであれば何でもよいです。上の写真はMDFを利用しています。**デザインデータは上の部品表に載せているバッテリーとRaspberry Pi用のケースを利用してつくるように設計しています。他のケースやバッテリーを使うとサイズが合わないのでご注意ください**

レーザー加工ができるサービスの例
- [グラフィック](https://www.graphic.jp/lineup/graphiclaser/)
- [FabCafe](https://fabcafe.com/tokyo/)
- MakerSpace / HackerSpace
 

## 4. GPIOの制御
Raspberry PiのGPIOをPythonで制御するようにしました。PythonでGPIOを制御するためのライブラリはいくつかあるようで、最初Rpi.GPIOライブラリを利用しましたが、360度サーボの正転、逆転が指定した方向と逆に動くことがありました。そのためpigpioというライブラリを利用します。pigpioのインストール手順は以下の通り。

```shell
sudo apt install pigpio
sudo pip3 install pigpio
# デーモンを動かす
sudo pigpiod
```
pigpioはデーモンを動かす必要があるので、`sudo pygpiod`を実行して、デーモンを動かした状態でPythonから利用します。

以下のようなスクリプトを書いてテストします。Python3を使ってます。2秒間正転、2秒間逆転して、止まります。

```Python
import pigpio
import time

# サーボモーターをGPIOの18につないで使います
servo = 18

pi = pigpio.pi()

# ピンを出力に設定
pi.set_mode(servo, pigpio.OUTPUT)

# 2秒間正転 (FS90Rは1msのパルスで正転)
pi.set_servo_pulsewidth(servo, 1000)

time.sleep(2)

# 2秒間逆転 (FS90Rは2msのパルスで逆転)
pi.set_servo_pulsewidth(servo, 2000)

time.sleep(2)

# 停止 (FS90Rは1.5msのパルスで停止)
pi.set_servo_pulsewidth(servo, 1500)

# 終了
pi.stop()
```

サーボモーターの仕様はAdafruitのページに載ってます。
https://www.adafruit.com/product/2442

## 5. おまけ (Flaskでウェブから操作できるようにする)
```Python
import pigpio
import time

from flask import Flask, redirect, render_template, url_for

app = Flask(__name__)


@app.route('/')
def home():
    return render_template('index.html')


@app.route('/forward')
def forward():
    pi.set_servo_pulsewidth(left_out, 1000)
    pi.set_servo_pulsewidth(right_out, 2000)
    time.sleep(2)
    pi.set_servo_pulsewidth(left_out, 1480)
    pi.set_servo_pulsewidth(right_out, 1480)
    return redirect(url_for('home'))


@app.route('/backward')
def backward():
    pi.set_servo_pulsewidth(left_out, 2000)
    pi.set_servo_pulsewidth(right_out, 1000)
    time.sleep(2)
    pi.set_servo_pulsewidth(left_out, 1480)
    pi.set_servo_pulsewidth(right_out, 1480)
    return redirect(url_for('home'))


@app.route('/right')
def right():
    pi.set_servo_pulsewidth(left_out, 2000)
    pi.set_servo_pulsewidth(right_out, 2000)
    time.sleep(0.3)
    pi.set_servo_pulsewidth(left_out, 1480)
    pi.set_servo_pulsewidth(right_out, 1480)
    return redirect(url_for('home'))


@app.route('/left')
def left():
    pi.set_servo_pulsewidth(left_out, 1000)
    pi.set_servo_pulsewidth(right_out, 1000)
    time.sleep(0.3)
    pi.set_servo_pulsewidth(left_out, 1480)
    pi.set_servo_pulsewidth(right_out, 1480)
    return redirect(url_for('home'))


if __name__ == '__main__':
    pi = pigpio.pi()

    left_out = 18
    right_out = 19

    pi.set_mode(left_out, pigpio.OUTPUT)
    pi.set_mode(right_out, pigpio.OUTPUT)

    app.run(host='0.0.0.0', port=80)
```

## 終わりに

[Github](https://github.com/miokato/PiBot)にデータとスクリプトを置いてます。