MQTTとサーボでプラモのLEDを簡単リモートコントロール


ここ最近趣味として凝っているのがプラモデル、特に電飾の演出をつけたり、電飾がついているものを組んだりすることでして、1年ほど買うか悩んだ挙句、買ってしまいました。PG 1/60 RX-0 ユニコーンガンダム + PG 1/60 RX-0 ユニコーンガンダム用 LEDユニット!!
こいつのパーツ数が凄まじく組むのにすごく時間がかかってしまったわけですが、組んでLED点灯させて感動。

さて、この感動を継続的に感じたいがために、すでにMQTTでiTunesとコレクションケースのHueを連携してみるで仕込んでいたセンサー類と組み合わせて、自分の振る舞いに合わせてサイコフレームが発光するように仕込みたくなりました。
センサーとこういったおもちゃを組み合わせる方法には色々なやり方が考えられますが、今回は、いかに手間をかけずに、ハードウェアとソフトウェアを構成するかに着目してやってみました。

ハードウェア: ソフトウェアからLEDをどう制御する?

PGユニコーンガンダムの台座部分にはバッテリーユニットがあり、そこに電飾制御用の押しボタンがあります。このボタンを、1回押す→カメラアイ点灯, 2回押す→カメラアイ+全身サイコフレーム点灯, 3回押す→サイコフレームが消灯しカメラアイが数秒後に消灯 といった形で演出が変化します。サイコフレームの発光は徐々に光量が上がるような演出でして、ここは殺したくないところです。

また、既存のLEDの制御回路をリバースエンジニアリングするという時間もちょっと取れないかなということで、今回はボタン押しをサーボに代行させることにしました。力技ですが、とりあえずまずは動けばよい。ということで以下使用パーツ。

  • 制御系: Raspberry Pi Zero W ... プラモを飾るケース内外でなるべくケーブルを這わせたくなかったので、コンパクトさ重視
  • サーボ: ASV-15MG ... 手元にあったので。位置制御を考えると、もうちょっと良い奴に置き換えるべきかも・・・

工作としては以下のようにバッテリーユニットのカバー部分にサーボ固定用のパーツをアルミ板で作り両面テープで固定。雑めな工作。動作確認中にアルミ板の折り曲げ部が断裂してセロテープ補修する程度の雑さ。

サーボをネジ止めすると以下のような感じ。サーボモーターに取り付けたサーボホーンで、ボタンを押し込むような構造にしています。

このサーボをRaspberry Pi Zero WのGPIOに接続しています。制御はRaspberry Pi Zero WにインストールしたPythonスクリプトで実装しました。GPIO経由でのサーボ制御コード例は色々と記事を書かれている人がいるので、それらの記事を参考にしつつで。回転角は実際に動かしながら調整という雑作業でしたが、20行程度のPythonコードで実装できました。

ソフトウェア: Raspberry Pi Zero Wを別デバイスとどう連携する?

ここまででサイコフレーム発光を制御するハードウェアが構築できました。今回は、すでに自分の机に置いてあるRaspberry Pi 1 Model Bに接続された超音波センサーの値変化を検出し、何かが席についているかどうかで電飾制御をキックしてみることにします。

ネットワーク越しのメッセージのやり取りは、これまでMQTTベースのおうち制御システムをAmazon Echo対応した話なんかでも書いた通り、MQTTベースのソフトウェアを用いてPub/Subネットワークを構成するのが柔軟性が高いと感じています。ですので、今回もRaspberry Pi Zero WをMQTTベースで制御できるようにします。

ソフトウェアのインストール

MQTTブローカにはEclipse Mosquittoを使ってみます。mosquittoは今回特にコマンドラインツールをベースに使ってみようと思いますので、以下のようにapt-getを用いてソフトウェアをインストールします。Raspberry Pi Zero WにはRASPBIAN STRETCH LITEをインストールしてある想定です。

$ sudo apt-get install mosquitto mosquitto-clients

余談ですが、Raspberry Piの多様化と低価格化もあり、複数のRaspberry Piを持つ羽目になって若干管理しずらくなっているという状態に陥っています。仕事でやっているJupyter+Ansibleを使ったインフラ運用のはじめかたのテクニックを使って、把握しやすくしたいところですねえ・・・

スクリプトの構成

MQTTブローカに対してメッセージの購読を行い、メッセージに応じてLED制御を実施するようなことはこれまでも何度か書いてきました。MQTTライブラリをPythonスクリプトから呼び出しても良いのですが、実際にやりたい処理(メッセージが来たらサーボ制御を行う)以外に初期化やハンドラの登録などにも注意を向けねばならず面倒です。
そこで、MQTTのメッセージ購読ができるユーティリティコマンド mosquitto_sub を活用してみることにします。このコマンドが受信したメッセージを標準出力に出力することを利用して、Unixのパイプを用いたコマンド連携を試してみました。以下のような形式で記述できます。

$ mosquitto_sub  -h mqtt.beebotte.com -p 1883 -u XXXX -t TOPIC/NAME | python /home/xxxx/controller.py

TOPIC/NAME トピックにメッセージを受信したら、その内容をそのままパイプで後続のコマンドに引き渡すような構造です。
controller.py には、以下のようなコードを記述します。fileinput.input 関数を利用してmosquitto_sub が出力したメッセージ(今回はJSONでシリアライズされている)を取得し、解析しています。

controller.py
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import fileinput
import json
from datetime import datetime

GPIO.setmode(GPIO.BCM)
try:
  for line in fileinput.input():
      msg = json.loads(line)
      to_state = msg['on']
      print(datetime.now(), msg)

      # to_stateの値を使ってサーボ制御
finally:
  GPIO.cleanup()

controller.py を見るとわかる通り、制御スクリプト内をMQTTのことを気にすることなく記述できました。動作確認したい場合は、mosquitto_sub の代わりにechoでテスト用メッセージを食わせてもよいですし、Mosquittoをインストールした別の環境から、mosquitto_pubコマンドを実行すればメッセージを送ってもよいです。

$ mosquitto_pub -h mqtt.beebotte.com -p 1883 -u XXXX -t TOPIC/NAME -m '{"on": true}'

ちなみに、MQTTブローカーサービスには、Beebotteのようなインターネット越しに利用可能なサービスを用いることで、家庭内のLANだけでなくインターネット越しに制御することもできるようになります。外からプラモの電飾を制御する必要があるのかという話は置いておいて。

まとめ

そんなわけで、だいたい半日程度の作業で、作業机に座るとPGユニコーンガンダムのサイコフレームが輝くように仕込むことができました。本体の組み立てに正味5日程度かかっているので、組み立てに比べてずっと楽に実現できてほどほど成功かなと。以下、動作の様子。

PG ユニコーンガンダムのLED制御をRaspberry Piで

ついでに、背後のMGジェスタにもLEDユニットを仕込んでカメラアイが光るように改造したりして遊んでいます。
趣味の工作が休日の心の休息になっているわけですが、工数かけてしまうと仕事と変わらなくなってしまうので、少ない工数で実現したい物を作るというのが工夫のしどころかなと。

今後の課題としては、サーボの動作音が若干うるさい(嫁からいきなりサーボ音が聞こえてびっくりすると苦情をいただいている)のをどうするかなーというところ。