iPhoneアプリからRaspberryPi3につなげたサーボモーター(SG90R)を遠隔制御する

以前RaspberryPi3をかったもののちょっとしたサーバーを動かすくらいでいまいち遊べていなかったので、せっかくだからSwiftとPHPとPythonを利用してサーボモーターを遠隔制御してみました。
ここにはプログラム以外の製作物については載せませんが、家の鍵を遠隔で開け閉めできるようにしようと思ってやりました。

そのほかの制作物（部品など）は製作中のため、[私のはてなブログ](http://crouton-camera.hatenablog.jp/entry/2017/11/15/192227)に進捗をまとめています。
#前提
RaspberryPiのセットアップが終わっており、サーボモーターの配線が完了している。
Apacheの設定ができており、PHPとPythonが利用できる。
#環境
MacBook Air
  └─Swift4

RaspberryPi3
  ┣━Python3.5.3
  └─PHP7.0.19

サーボモーター
   └─[SG90R](http://akizukidenshi.com/catalog/g/gM-08761/)
#参考サイト
[- Buffer Overruns - Raspberry Piでサーボモータ（SG90）を制御する](http://bufferoverruns.blogspot.jp/2016/08/raspberry-pisg-90.html?m=1)
ここで配線からプログラムからの制御まで紹介されてますので、まずここを済ませてからやってみてください

#大まかな手順
- RaspBerryPiでPythonを用いてGPIOを制御してサーボモーターを動かすプログラムを作成する
- RaspBerryPiでPHPを用いてPOSTによって別のPythonのプログラムを呼び出すようにする
- MacのXcodeでSwiftを用いてPOSTを送るアプリを作成

#Python編
先ほど紹介したサイトと同様の方法で制御しています。
その際にいくつか引っかかった点を・・・

####デューティ比
先ほどのサイトでは50Hzで2.5% - 12.0%で制御していましたが計算上あっていても結局サーボの個体差によって角度がずれることがあるようです。
私のサーボでは計算上180度ぴったりになるはずの信号を送っても可動域を超えた時に鳴る、「ガガガガ」という音をしばらく立ててました。
結局いろいろ実測したところ100Hzで22.9%を超えたあたりで「ガガガガ」と音がで始めてしまいました。
角度の精度が必要な場合は自分でこのパーセンテージを検証した方が確実で早いです。（今回は角度はそこまで精度を必要としていないので計算値どおりでごり押してます）
####プログラム
今回製作しているのはサーボで鍵を開けるものだったため、open.pyとclose.pyの２つの動作を別々のプログラムとして書き出しました。

```open.py
#!/usr/bin/python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

gp_out = 4
GPIO.setup(gp_out, GPIO.OUT)
servo = GPIO.PWM(gp_out, 100)

servo.start(0.0)

d = 0
cycle = 19 * (d/180) + 5
servo.ChangeDutyCycle(cycle)
time.sleep(0.5)
d = 90
cycle = 19 * (d/180) + 5
servo.ChangeDutyCycle(cycle)

GPIO.cleanup()
```

```close.py
#!/usr/bin/python
import RPi.GPIO as GPIO  
import time

GPIO.setmode(GPIO.BCM)

gp_out = 4
GPIO.setup(gp_out, GPIO.OUT)
servo = GPIO.PWM(gp_out, 100) 

servo.start(0.0)

d = 180
cycle = 19 * (d/180) + 5
servo.ChangeDutyCycle(cycle)
time.sleep(0.5)
d = 90
cycle = 19 * (d/180) + 5
servo.ChangeDutyCycle(cycle)
time.sleep(0.5)

GPIO.cleanup()
```

これでサーボが0度|180度に回転した後90度の位置に戻ります。

##PHP編
PHPではポストを受け取ってそれに従いclose.pyを実行するのか、open.pyを実行するのかを制御します。
今回はここのexec関数で5時間くらいつ躓きました・・・
実行するコマンドはちゃんとパスを書いて指定しなければならないのに注意してください。

```controller.php
<?php
  switch ($_POST['type']) {
    case 'open':
        exec('/usr/bin/python3 /***省略***/open.py');
        echo"open";
        break;
    case 'close':
        exec('/usr/bin/python3 /***省略***/close.py');
        echo"close";
         break;
    default:
        echo "デフォルト";
      break;
  }
?>
```
これでtypeにclose、またはopenを入れることで開閉を制御できるようになりました。

##Swift編
とりあえず試すだけなのでStory Boardでボタンを２つ置き、actionをそれぞれViewControllerに接続してください。

![スクリーンショット 2017-11-15 4.07.14.png](https://qiita-image-store.s3.amazonaws.com/0/204184/37eca955-6165-5707-6eef-571b4d5066d3.png)

```ViewController.swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @IBAction func OpenButton(_ sender: Any) {
        POST_Data(url: "http://***省略***/controller.php", type: "open")
    }
    
    @IBAction func CloseButton(_ sender: Any) {
        POST_Data(url: "http://***省略***/controller.php", type: "close")
    }
    
    func POST_Data(url:String,type:String){
        let postString = "type=" + type
        
        var request = URLRequest(url: URL(string: url)!)
        request.httpMethod = "POST"
        request.httpBody = postString.data(using: .utf8)
        
        let task = URLSession.shared.dataTask(with: request, completionHandler: {
            (data, response, error) in
            if error != nil {
                return
            }
        })
        task.resume()
    }
}
```

以上で完成・・・！

##動作
ちょっとここにかいたプログラムとは動きが違うけど・・・
<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/OkDTS7UNXk">pic.twitter.com/OkDTS7UNXk</a></p>&mdash; Crouton (@ryosuke_tamura) <a href="https://twitter.com/ryosuke_tamura/status/930515376986714112?ref_src=twsrc%5Etfw">2017年11月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

ちょっと書いただけでサーボが動かせるので是非・・・
あとは発注した3Dプリントした部品が届いたら鍵に装着するだけです・・・！

おわり