画面表示(温度、湿度、気圧、電源電圧、MQTT送信間隔)
全UIFlowグラフィカルプログラム(Pythonコードはリアルタイムで自動生成される)
はじめに
「M5StickC」と「M5StickC ENV Hat(DHT12/BMP280/BMM150搭載)」で、温度、湿度、気圧を測定し、MQTT送信をしてみました。
開発環境は、UIFlow V1.4.0-Beta です。(UIFlow V1.3.2 では、ENV Hat に未対応のようです。)
グラフィカルプログラムから、Pythonコードがリアルタイムで生成され、良い感じです。
M5StickC は小さく良いです。
48(W)×24(D)×14(H)mm 18.1 g
3個のスイッチ(1つは電源ボタン)、LED、LCDカラーディスプレイ等で、ユーザインターフェースを作れます。
リアルタイムクロック用のボタン電池も内蔵しています。
ENV Hat は、M5StickC本体発熱の影響を受けて、温度が高めにでます。
そのままでは使えない感じです。発熱を抑える工夫が必要です。
UIFlow IDEのBlockly画面ではグラフィカルにプログラムでき楽しい。
- UIFlow IDE上部にある「Blockly」と「>Python」で、グラフィカル画面とPythonコード画面の間を行き来できます。
- グラフィカルプログラムは、Pythonコードに反映されますが、逆はできません。
- グラフィカル画面のメニューは、ハードウェアAPIのマニュアル代わりになり便利です。
- グラフィカル画面内にPythonコードを書きたい時は、「高度なブロック」「実行」ブロックを使用します。
UIFlow V1.4.0-Beta では、つぎの不具合がありました。
- 文字列に'%'を入力すると、python側では'%'になってしまう
- LCDの画面レイアウト作成時に設定したプロパティが、時々反映されない。
LCD画面レイアウトとハードウェアアクセスをグラフィカル環境で行い、その後グラフィカル環境を捨てて、Pythonコードのみでの開発もできそうです。
ハードウェア
M5StickC 本体
https://docs.m5stack.com/#/ja/core/m5stickc より
M5StickC 電源管理
https://lang-ship.com/reference/unofficial/M5StickC/Tips/AXP192/ より
M5StickC ENV Hat(DHT12/BMP280/BMM150搭載)
https://www.switch-science.com/catalog/5755/ より
プログラム仕様
LCD画面表示情報
- 温度、湿度、気圧
- 電源電圧
- MQTT送信間隔
LED点灯
- ハートビート
- MQTT送信
MQTT送信データ(PC側でのグラフ作成とデータ表示)
グラフィカルプログラム(Blockly画面)
初期化(MQTT、画面、タイマー)とメインループ(LEDハートビート、センサー読込ループ、中央値計算、LCD表示)
ボタンAとBの処理
- ボタンA(上面、M5マーク) LCDオン/オフ、長押しでMQTT送信
- ボタンB(側面) MQTT送信タイマー選択(1/3/30分)、長押しで背景色変更(青/赤)
スクリーンセーバタイマー1
MQTT送信タイマー2
Python プログラム(自動生成されたプログラム)
グラフィカルプログラムから自動生成されたプログラムを次に示します。
自動生成後の、コード追加と修正は行っていません。
from m5stack import *
from m5ui import *
from uiflow import *
from m5mqtt import M5mqtt
import hat
setScreenColor(0x111111)
hat_env0 = hat.get(hat.ENV)
m5mqtt = M5mqtt('M5StickC', '192.168.11.2', 1883, '', '', 300)
label0 = M5TextBox(74, 5, "Text", lcd.FONT_DejaVu18,0xFFFFFF, rotate=90)
label1 = M5TextBox(50, 5, "Text", lcd.FONT_DejaVu18,0xFFFFFF, rotate=90)
label2 = M5TextBox(25, 5, "Text", lcd.FONT_DejaVu18,0xFFFFFF, rotate=90)
label4 = M5TextBox(50, 97, "Text", lcd.FONT_DejaVu18,0xFFFFFF, rotate=90)
label3 = M5TextBox(74, 97, "Text", lcd.FONT_DejaVu18,0xFFFFFF, rotate=90)
from numbers import Number
x = None
LcdOn = None
mqttIntervalMinIndex = None
blueOn = None
ID = None
LcdOffMin = None
mqttIntervalMin = None
mqttIntervalMinList = None
msg = None
tempList = None
humiList = None
presList = None
battList = None
temp = None
humi = None
pres = None
batt = None
def math_median(myList):
localList = sorted([e for e in myList if isinstance(e, Number)])
if not localList: return
if len(localList) % 2 == 0:
return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0
else:
return localList[(len(localList) - 1) // 2]
def setLcdTimer():
global x, LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
LcdOffMin = 3
timerSch.stop('timer1')
timerSch.run('timer1', (LcdOffMin * (1000 * 60)), 0x00)
def setMqttTimer(x):
global LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
timerSch.stop('timer2')
if x:
timerSch.run('timer2', (mqttIntervalMin * (1000 * 60)), 0x00)
def buttonA_wasReleased():
global LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, x, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
LcdOn = not LcdOn
if LcdOn:
axp.setLDO2Vol(3)
else:
axp.setLDO2Vol(0)
setLcdTimer()
pass
btnA.wasReleased(buttonA_wasReleased)
def buttonA_pressFor():
global LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, x, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
setMqttTimer(False)
ttimer2()
wait(3)
setMqttTimer(True)
setLcdTimer()
pass
btnA.pressFor(0.8, buttonA_pressFor)
def buttonB_wasReleased():
global LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, x, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
mqttIntervalMinIndex = 1 + mqttIntervalMinIndex
if mqttIntervalMinIndex >= 4:
mqttIntervalMinIndex = mqttIntervalMinIndex - 3
mqttIntervalMin = mqttIntervalMinList[int(mqttIntervalMinIndex - 1)]
label4.setText(str((str(mqttIntervalMin) + 'min')))
setMqttTimer(True)
setLcdTimer()
pass
btnB.wasReleased(buttonB_wasReleased)
def buttonB_pressFor():
global LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, x, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
blueOn = not blueOn
if blueOn:
setScreenColor(0x3366ff)
else:
setScreenColor(0xff0000)
axp.setLDO2Vol(3)
label0.setText('')
label1.setText('')
label2.setText('')
label3.setText('')
label4.setText('')
setLcdTimer()
pass
btnB.pressFor(0.8, buttonB_pressFor)
@timerSch.event('timer1')
def ttimer1():
global LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, x, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
axp.setLDO2Vol(0)
LcdOn = False
pass
@timerSch.event('timer2')
def ttimer2():
global LcdOn, mqttIntervalMinIndex, blueOn, ID, LcdOffMin, mqttIntervalMin, x, mqttIntervalMinList, msg, tempList, humiList, presList, battList, temp, humi, pres, batt
M5Led.on()
msg = temp + ' ,' + humi + ',' + pres + ',' + batt
m5mqtt.publish(str('M5StickC'),str(((ID + ((',' + msg))))))
wait(0.001)
M5Led.off()
pass
ID = 'I5001'
m5mqtt.start()
LcdOn = True
axp.setLDO2Vol(3)
blueOn = True
setScreenColor(0x3366ff)
setLcdTimer()
mqttIntervalMinIndex = 3
mqttIntervalMinList = [1, 3, 30]
mqttIntervalMin = mqttIntervalMinList[int(mqttIntervalMinIndex - 1)]
setMqttTimer(True)
while True:
M5Led.on()
wait(0.0007)
M5Led.off()
tempList = []
humiList = []
presList = []
battList = []
for count in range(5):
tempList.append(int(((hat_env0.temperature) * 100)))
humiList.append(int(((hat_env0.humidity) * 100)))
presList.append(int(((hat_env0.pressure) * 100)))
battList.append(int(((axp.getBatVolt()) * 100)))
wait(0.2)
temp = (("%.2f"%((math_median(tempList) / 100))) + 'C')
humi = (("%.2f"%((math_median(humiList) / 100))) + 'pct')
pres = (("%.2f"%((math_median(presList) / 100))) + 'hPa')
batt = (("%.2f"%((math_median(battList) / 100))) + 'V')
label0.setText(str(temp))
label1.setText(str(humi))
label2.setText(str(pres))
label3.setText(str(batt))
label4.setText(str((str(mqttIntervalMin) + 'min')))
wait_ms(2)
関連情報
M5StickC クイックスタート - UIFlow
https://docs.m5stack.com/#/ja/quick_start/m5stickc/m5stickc_quick_start_with_uiflow
M5StickC (M5Stack Docs)
https://docs.m5stack.com/#/ja/core/m5stickc
https://docs.m5stack.com/#/en/uiflow/hardware
m5stack/M5StickC
https://github.com/m5stack/M5StickC
屋根裏実験室 M5Stackを使ってみる
http://itoi.jp/M5Stack.html
M5StickC非公式日本語リファレンス AXP192の調査
https://lang-ship.com/reference/unofficial/M5StickC/Tips/AXP192/
M5StickC 0.0.7のAXP192追加関数を調べてみた
https://lang-ship.com/blog/?p=696#_LightSleep
M5Stick C とりあえず分解してみた
https://twitter.com/Ghz2000/status/1125058416014176263
BeetleC が 届いた
http://gijin77.blog.jp/archives/20843205.html
パソコン上のM5Stackの3Dモデルを、M5Stackの動きに合わせて動かす
http://pages.switch-science.com/letsiot/rotateM5Stack/
【これは】世界のメイカーズが注目するM5Stack本社に行ってきた!【勝てない】
https://wirelesswire.jp/2019/08/71960/
Adafruit M5Stick-C Pico Mini IoT Development Board
https://www.adafruit.com/product/4290