mqtt
Pythonista
Pythonista3
M5stack
M5Bala

iPhoneを使ってM5BALAを操作する(Pythonista-MQTT編)


概要

前の投稿やった iPhoneを使ってM5BALAを操作する(JavaScript-MQTT編) の Pythonista版です。


  • iPhone の傾きを Pythonista で検知する

  • Pythonista から MQTT 経由で制御コマンドを送信する

  • 受信した制御コマンドに従ってM5BALA+M5GOが動く

Pythonista は iPhone や iPad 上で Python が実行できる開発環境。以前 Pythonista を知った時は、興味は持ったものの、有料(1200円)であることや、iPhone や iPad 上でコーティングなんて外付キーボードを使っても無理、と思って使わずでしたが、今は iCloud Drive で連携できるので、Mac で iCloud Drive 上のファイルを編集し、iPhone側で iCloud Drive 上のファイルをそのまま実行できるのでとっても楽です。BLEが使えるので、M5Stack と BLE で連携というのも、そのうち試したいことです。


環境


  • M5BALA+M5GO

  • M5UI.Flow (Firmware 0.7.2/0.8.0 で確認)

  • iMac (macOS Mojave)

  • MQTT Broker (mosquitto version 1.4.15)

  • MQTT Client (paho-mqtt 1.4.0)

  • Pythonista3 v3.2

  • iPhone6 iOS 12.0.1


実行例

iPhoneを前後左右に傾けることで、M5BALAが前進・後進・右回転・左回転します。

IMG_1792.jpeg


Pythonista3プログラム

iPhoneの前後左右の傾きに応じて、左右の車輪を動かすための指示をMQTT経由で送信する仕組みです。

MQTTクライアントが必要なので StaSh - Shell Like an Expert in Pythonista をインストール。(Pythonista のコンソールで以下を実行)

import requests as r; exec(r.get('http://bit.ly/get-stash').text)

StaSh を実行し pip で paho-mqtt をインストール。

pip install paho-mqtt


m5bala_controller.py

import motion

import time
import paho.mqtt.client as mqtt
import math
import ui

MQTT_BROKER = 'MQTTBroker' # MQTTBroker のアドレスを設定
MQTT_TOPIC = 'M5BALA'

def end_controller(sender):
global action_loop
sender.superview.close()
send_action('I')
action_loop = False

def send_action(action):
global last_action
client.publish(MQTT_TOPIC, action)
view['action'].text = action
last_action = action

view = ui.load_view()
view.present('sheet')

client = mqtt.Client('iPhonePythonista3', protocol=mqtt.MQTTv311)
client.connect(MQTT_BROKER, keepalive=60)

motion.start_updates()

# 'I' : Init Params
send_action('I')

action_loop = True
while action_loop:
roll, pitch, yaw = motion.get_attitude()
yaw = math.degrees(yaw)
pitch = math.degrees(pitch)
roll = math.degrees(roll)

view['yaw'].text = '{:.2f}'.format(yaw)
view['pitch'].text = '{:.2f}'.format(pitch)
view['roll'].text = '{:.2f}'.format(roll)

move = max(-60, min(60, pitch)) * 4
turn = max(-60, min(60, roll)) * 1
action = 'L={:.2f},R={:.2f}'.format(move + turn / 2, move - turn / 2)
if action != last_action:
send_action(action)
time.sleep(0.5)



Pythonista3 UI


m5bala_controller.pyui

[

{
"nodes" : [
{
"nodes" : [

],
"frame" : "{{17, 197}, {337, 45}}",
"class" : "Label",
"attributes" : {
"name" : "action",
"frame" : "{{45, 104}, {150, 32}}",
"uuid" : "95E5B18C-90A9-4784-BA75-4B1016070924",
"class" : "Label",
"alignment" : "center",
"text" : "Action",
"font_size" : 36,
"font_name" : "<System>"
},
"selected" : false
},
{
"nodes" : [

],
"frame" : "{{96, 27}, {60, 32}}",
"class" : "Label",
"attributes" : {
"name" : "label2",
"frame" : "{{82, 125}, {150, 32}}",
"uuid" : "5144134F-E68A-4023-A81E-A67824AF01CA",
"class" : "Label",
"alignment" : "right",
"text" : "方角",
"font_size" : 24,
"font_name" : "<System>"
},
"selected" : false
},
{
"nodes" : [

],
"frame" : "{{96, 67}, {60, 32}}",
"class" : "Label",
"attributes" : {
"name" : "label3",
"frame" : "{{82, 125}, {150, 32}}",
"uuid" : "01A7842C-1680-4655-9F09-F3B52A0721B6",
"class" : "Label",
"alignment" : "right",
"text" : "前後",
"font_size" : 24,
"font_name" : "<System>"
},
"selected" : false
},
{
"nodes" : [

],
"frame" : "{{96, 107}, {60, 32}}",
"class" : "Label",
"attributes" : {
"name" : "label4",
"frame" : "{{82, 125}, {150, 32}}",
"uuid" : "A5EF17D2-3351-4AA3-B918-A82382B2DF4D",
"class" : "Label",
"alignment" : "right",
"text" : "左右",
"font_size" : 24,
"font_name" : "<System>"
},
"selected" : false
},
{
"nodes" : [

],
"frame" : "{{164, 27}, {103, 32}}",
"class" : "Label",
"attributes" : {
"name" : "yaw",
"frame" : "{{82, 125}, {150, 32}}",
"uuid" : "F6954500-8FAB-4E42-B4A6-29A7865C50F9",
"class" : "Label",
"alignment" : "right",
"text" : "",
"font_size" : 24,
"font_name" : "<System>"
},
"selected" : false
},
{
"nodes" : [

],
"frame" : "{{164, 67}, {103, 32}}",
"class" : "Label",
"attributes" : {
"name" : "pitch",
"frame" : "{{82, 125}, {150, 32}}",
"uuid" : "A73FDD85-DBEE-4857-9B9E-39B13FEEA553",
"class" : "Label",
"alignment" : "right",
"text" : "",
"font_size" : 24,
"font_name" : "<System>"
},
"selected" : false
},
{
"nodes" : [

],
"frame" : "{{164, 107}, {103, 32}}",
"class" : "Label",
"attributes" : {
"name" : "roll",
"frame" : "{{82, 125}, {150, 32}}",
"uuid" : "7744E0CF-F2CD-4985-AAD3-A68158E7F67D",
"class" : "Label",
"alignment" : "right",
"text" : "",
"font_size" : 24,
"font_name" : "<System>"
},
"selected" : false
},
{
"nodes" : [

],
"frame" : "{{136, 266}, {87, 39}}",
"class" : "Button",
"attributes" : {
"action" : "end_controller",
"border_width" : 1,
"frame" : "{{146, 149}, {80, 32}}",
"title" : "終了",
"uuid" : "0EC4234B-2C78-4812-89A4-236FB5384680",
"class" : "Button",
"corner_radius" : 8,
"font_bold" : true,
"name" : "button1",
"font_size" : 24
},
"selected" : false
}
],
"frame" : "{{0, 0}, {372, 330}}",
"class" : "View",
"attributes" : {
"name" : "M5BALA Controller",
"enabled" : true,
"border_color" : "RGBA(0.000000,0.000000,0.000000,1.000000)",
"background_color" : "RGBA(1.000000,1.000000,1.000000,1.000000)",
"tint_color" : "RGBA(0.000000,0.478000,1.000000,1.000000)",
"flex" : ""
},
"selected" : false
}
]