SORACOMでラジコンを遠隔操作できるようにしてみた


ソラコムインターンの岩瀬です。
本日がSoracom Advent Calendar最終日ですね！
世間はクリスマス一色ですが、そんなことお構い無しで年末年始にRaspberry Piを使ってIoTに触れてみたい！！という方々のために、とっておきのプレゼントを用意しました！

ということで、今回はRaspberry PiとSORACOM Airを使ってリモートで操作できるラジコンバギーを作成していきます。


## 準備するもの
* Raspberry Pi B+ (OSインストール済み、SORACOM Airセットアップ済みのもの)
* SORACOM Air
* USBドングル
* [TAMIYA/バギー工作基本セット](http://www.tamiya.com/japan/products/70112buggy_car/)
* 乾電池ソケット(単3 3本用)
* モータドライバ(TA7291P)
* ブレッドボード
* スマホ用モバイル充電器(1A出力のもの)
* ジャンパー線(オスオス、オスメスをそれぞれ約5本ずつ)

TAMIYA/バギー工作基本セットはヨドバシカメラ 秋葉原店にて購入しました。SORACOM Air, USBドングルはAmazon等で購入できます。それ以外についてはすべて秋葉原にある秋月電子で購入可能です。
SORACOM Airの接続方法に関しては、

* [簡単にRaspberry PiでSORACOM Airを使う(FS01BU USBモデムを用いて自動接続)](http://qiita.com/dietposter/items/068019ee53252206a6bf)
* [Raspberry PiでSORACOM SIMを使う(ZTE MF120, MF112)](http://qiita.com/dietposter/items/068019ee53252206a6bf)

にわかりやすく書かれています。

## バギーの組み立て

1. TAMIYA/バギー工作基本セットの手順にしたがって下記の写真のように組み立ます。
※モータの配線はしないでください。
　![IMG_5131.JPG](https://qiita-image-store.s3.amazonaws.com/0/47744/a07b019a-2242-4dd0-36da-e938ab360c15.jpeg)

2. ブレッドボード上でモータとモータドライバを配線します。
配線方法は以下の図を参考にしてください。ここで配線するモータドライバを用いることで、簡単にモータの出力を変えることができるようになります。
![Untitled Sketch_ブレッドボードのコピー.jpg](https://qiita-image-store.s3.amazonaws.com/0/47744/6e191095-b323-f0c6-169d-4151b10f4676.jpeg)

3. Raspberry Piとブレッドボードをバギーの上に設置します。
ちなみにここが一番苦戦しましたorz
 ![IMG_5139.JPG](https://qiita-image-store.s3.amazonaws.com/0/47744/cd06b932-f029-6b0a-3a87-641a2a021cb8.jpeg)

これでバギーの組み立ては完了です。
次章ではRaspberry Piでモータを操作するためのセットアップを行います。

## コントローラの実装

GPIOの制御にWiringPi2-Pythonというライブラリを利用していきます。  
外部からのラジコンの操作はMQTTでメッセージを受信した際に、GPIOを制御するプログラムを動かすことで実装します。

1. WiringPiをインストール 

 ```
 $ git clone git://git.drogon.net/wiringPi
 $ cd wiringPi
 $ sudo ./build
 ```

2.WiringPi2-Pythonをソースからインストール

  ```
  $ git clone https://github.com/Gadgetoid/WiringPi2-Python.git
  $ cd WiringPi2-Python
  $ sudo python setup.py install
  ```

3.MQTTクライアントをインストール
今回はMQTTクライアントとしてpahoを利用します。

  ```
  $ sudo pip install paho-mqtt
  ```

4.以下のコマンドを入力して正しくモータが動くことを確認してください

  ```
  $ gpio -g mode 14 out
  $ gpio -g mode 15 out
  $ gpio -g mode 18 pwm
  $ gpio -g pwm 18 1023(0-1023までの任意の数字)
  # 前進する
  $ gpio -g write 14 1
  # 停止する
  $ gpio -g write 14 0
  # 後進する
  $ gpio -g write 15 1
  # 停止する
  $ gpio -g write 15 0
  ``` 

 もうすでにお気付きの方もいらっしゃると思いますが、今回はモータの制御にPWM(Pulse Width Modulation)を利用しています。PWM制御はモータの制御などによく利用される技術で、パルスの幅を変えることによってモータへの供給エネルギーを操作することができます。
Raspberry PiではGPIO18のみがPWMに対応しているので、それ以外のGPIOピンでは基本的にPWMは利用できません。(ソフトウェアでPWMを再現する方法もあります)

  `$ gpio -g pwm 18 1023(0-1023までの任意の数字)`
 上記の1023という部分を変化させてみると実際にモータの出力が変化していることがよくわかります。

5.PythonでGPIOを制御するためのテストコードを書きます

 ``` python:controller.py
 import wiringpi2 as wiringpi

 wiringpi.wiringPiSetupGpio()
 wiringpi.pinMode(14,1)
 wiringpi.digitalWrite(14,1)

 wiringpi.delay(3000)
 wiringpi.pinMode(18,2)
 wiringpi.pwmWrite(18, 600)

 wiringpi.delay(3000)
 wiringpi.pinMode(18,2)
 wiringpi.pwmWrite(18, 800)
 
 wiringpi.delay(3000)
 wiringpi.pwmWrite(18, 1024)

 wiringpi.delay(3000)
 wiringpi.digitalWrite(14,0)
 wiringpi.pwmWrite(18, 0)
```

 実際に上記のコードを試して、3秒ごとに速度が速くなっていれば成功です！

6.MQTTクライアントの実装
MQTTの通信にはSORACOM BeamとMQTTブローカサービスである[Sango](https://sango.shiguredo.jp/)を利用します。

 まずは、[Sango](https://sango.shiguredo.jp/)のHPよりSangoに登録をしてください。

 次に、SORACOMユーザコンソールを開いてグループを選択し、利用しているSIMのグループのSORACOM Beam 設定で下記のように設定をしてください。この際の「ユーザー名」と「パスワード」はSangoのダッシュボードに書かれているものを転記してください。
![スクリーンショット 2015-12-24 04.01.57.png](https://qiita-image-store.s3.amazonaws.com/0/47744/6ac0c7ff-b44c-9251-b465-2b22e8fb8882.png "スクリーンショット 2015-12-24 04.01.57.png")

 これでSORACOM BeamとSangoの設定は完了です！
 次に下記の2つのファイルを作成します。mqtt_client.pyはRaspberry Pi内に、mqtt_publisherは任意の場所に配置してください。
 

  ``` python:mqtt_client.py
  #!/usr/bin/env python
  # -*- coding: utf-8 -*-
  
  import wiringpi2 as wiringpi
  import paho.mqtt.client as mqtt

  host = 'beam.soracom.io'
  port = 1883
  topic = "%(YOUR_USER_NAME)/%(YOUR_TOPIC)"
 
  def on_connect(client, userdata, flags, respons_code):
        client.subscribe(topic)
 
  def on_message(client, userdata, msg):
      speed = int(msg.payload)
      wiringpi.wiringPiSetupGpio()
      wiringpi.pinMode(14,1)
      wiringpi.pinMode(15,1)
      wiringpi.pinMode(18,2)

      if speed <= 0:
          wiringpi.digitalWrite(14, 0)
          wiringpi.digitalWrite(15, 1)
          wiringpi.pwmWrite(18, -speed)
      else: 
          wiringpi.digitalWrite(14, 1)
          wiringpi.digitalWrite(15, 0)
          wiringpi.pwmWrite(18, speed)

  client = mqtt.Client(protocol=mqtt.MQTTv311)
  client.on_connect = on_connect
  client.on_message = on_message
  client.connect(host, port=port, keepalive=60)
  client.loop_forever()
  ```

  ```python:mqtt_publisher.py
  #!/usr/bin/env python
  # -*- coding: utf-8 -*-

  import paho.mqtt.client as mqtt

  # SORACOM Air経由のアクセスの場合はSubscriberと同じ設定を利用してください。

  MQTTHOST = "lite.mqtt.shiguredo.jp"

  def on_publish(client, userdata, mid):
      print("publish: {0}".format(mid))

  client = mqtt.Client(protocol=mqtt.MQTTv311)
  client.username_pw_set(USERNAME, PASSWORD)
  client.connect(MQTTHOST)
  client.loop_start()

  while True:
      speed = raw_input()
      client.publish("%(YOUR_USERNAME)/%(YOUR_TOPIC)", int(speed))
  ```

 以上でコントローラの実装は終了です。

 最後に、Raspberry Pi上で下記のコマンドを実行したあと、
 `$ sudo python mqtt_client.py`
 下記のコマンドを実行します。
 `$ python mqtt_publisher.py`
 すると標準入力待ちの状態になるので、-1023〜1023までの好きな数字を入力してバギーが走るのを楽しんでください！(マイナスは後ろ向き) 
  お疲れ様でした！！！！

## 補遺
 なんだ、前後にスピード変えて走らせるだけじゃん…と思った方、、たくさんいると思います。
 「サーボモータを使ってステアリングを実装したい！」、「遠隔操作するんだからカメラつけたい！」、「ラジコンをCLIじゃなくてWeb上で動かしたい！」等々いろんな考えが浮かんできたはずです。
 上記の3つに関しては僕が当初やりたかったことなのですが時間が足りずできませんでした…。本記事はそういった応用的な実装への橋渡しということで残りの部分はみなさんにお任せします!(丸投げ)
 今回このテーマを選んだのは、モータの制御がこんなに簡単にできるよ！というのを伝えたかったからです。IoTとなるとセンサーデバイスのような静的なものをイメージしがちですが、今回のラジコンを応用すれば「360度角動く監視カメラ」とか「災害派遣用のロボット」のような動的なものも作れます。なんだか、[SIM City](http://c9katayama.hatenablog.com/entry/2015/12/22/201545)(12/22のアドベントカレンダー参照)が少し近づいてきた気がしましたねw
この記事を読んで、少しでもIoTやSORACOMに興味を持っていただけると嬉しいです。

*Merry Christmas!!!そして良いお年を!!!!*
ということでSORACOM Advent Calendar最終日を閉めくらせていただきます！
長丁場になってしまいましたが、最後まで読んでいただきありがとうございました！

ところで、ソラコムサンタはどうした？と思われた方もいるかもしれません。
僕の枕元にこんなリンクが書かれた紙が落ちていました。本日(12/25)の15時にお披露目のようなのでお楽しみに！
https://blog.soracom.jp/blog/2015/12/25/soracom-santa/'

p.s 質問等あれば気軽にコメントしてください。

## 参考にさせていただいたサイト
たくさんの先人の知恵に助けていただきました。

* [How to use WiringPi2 for Python with pull-ups or pull-downs and PWM – pt 2](http://raspi.tv/2013/how-to-use-wiringpi2-for-python-with-pull-ups-or-pull-downs-and-pwm)
* [Mosquitto と paho-mqtt をつかってPythonで MQTTをさわる](https://librabuch.jp/2015/09/mosquiito_paho_python_mqtt/)
* [モータドライバの使い方](http://usicolog.nomaki.jp/engineering/avr_lineTracer/motorDriver.html)
* [Raspberry Pi 2でDCモーターを制御する](http://kaiware007.hatenablog.jp/entry/2015/07/07/024930)
* [ソフトウェアエンジニアの素人電子工作](http://elelab-net.com/hobbytec/?cat=8)