背景:MicroPythonに接続したセンサーデータを手軽にグラフ化したい
取り組み:MQTTを介してMicroPythonのデータをPCに転送する。PC側ではNode-REDのNodeを組み合わせてMQTT Subscribeして得られた値をグラフ化する
結論:追従できる速度に課題があるが*1、仕組みとしては実現できた。以下は構成図

詳細:
ESP32版のMicroPythonなら最初からMQTT Clientが入っているのだが、RP2040用のMicroPythonにはMQTT Clientが入っていない様である。umqtt.simpleパッケージが提供されているので、パッケージで入れてみる。
CPythonだとpipコマンドでパッケージインストールできるが、MicroPythonの場合、ホスト側からmpremoteコマンドを使って、ターゲット(RP2040)のFlashにパッケージをインストールすることができる。
自分の場合、諸般の事情により、mpremoteコマンドはUbuntu(WSL)上に入っているので、まずはUSBを透過する必要がある。
PS C:\Windows\system32> usbipd list Connected: BUSID VID:PID DEVICE STATE 2-1 2e8a:0005 USB シリアル デバイス (COM20) Not shared 2-3 046d:c058 USB 入力デバイス Not shared 2-5 1199:90b1 Sierra Wireless EM7431 Qualcomm® Snapdragon™ X16 LTE-A, S... Not shared 2-7 5986:118f USB FHD Camera, IR Camera, Camera DFU Device Not shared 2-8 06cb:00c6 Synaptics UWP WBDI Not shared 2-10 8087:0033 インテル(R) ワイヤレス Bluetooth(R) Not shared Persisted: GUID DEVICE 2a4f2781-19c5-4922-a1dd-e96106844633 USB シリアル デバイス (COM14), USB JTAG debug unit 6b9e6ec4-1707-401f-8d5d-8ac0b21d899c USB シリアル デバイス (COM18), USB JTAG/serial debug unit 820033e8-df76-408a-b5b9-8807c63590eb USB-Enhanced-SERIAL CH9102 (COM19) b24984ee-275b-44bd-905e-387f22edb9c5 USB シリアル デバイス (COM17), USB JTAG/serial debug unit c8df5152-439b-47bc-b8b6-de2c8a0e55f2 USB シリアル デバイス (COM13), USB JTAG/serial debug unit PS C:\Windows\system32> usbipd bind --busid 2-1 PS C:\Windows\system32> usbipd attach --wsl --busid=2-1 usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions. usbipd: info: Using IP address 172.17.96.1 to reach the host.
上記操作によりUbuntu(WSL)からPC上のCOMポートが参照可能になった。
$ ls /dev/ttyACM0 /dev/ttyACM0
mpremoteコマンドを使って、umqtt.simpleパッケージをインストールする
$ mpremote mip install umqtt.simple Install umqtt.simple Installing umqtt.simple (latest) from https://micropython.org/pi/v2 to /lib Installing: /lib/umqtt/simple.mpy Done
Windows環境からTereTermでMicroPythonコンソールに接続したいので、一旦透過を戻す
> usbipd detach --busid 2-1
MicroPythonコンソールから、umqttが入ったことを確認。確認の方法がイマイチだが、一応パッケージが入ったようである。
>>> import umqtt >>> dir(umqtt) ['__class__', '__name__', '__dict__', '__file__', '__path__']
MQTT Clientのセットアップ等は省略しますが、、以下の内容で50msec周期でpublish(テストなのでセンサーデータはRandom値)
import random
import json
while True:
value = int(100*random.random())
msg = {"data" : value}
print(f'send message {msg} on topic: {TOPIC}')
client.publish(TOPIC, json.dumps(msg), qos=0)
time.sleep_ms(50)Node-REDにより、MQTTでSubscribeしてグラフに描画するプログラムは以下

描画されたグラフは以下(欠損なく50msec周期で描けているのかは未確認)

欠損状態が分かりやすいように、センサデータとして、周期1秒のSin波を描いてみる
50msec周期でsin波をpublishするサンプル。1波20publish(sin波の周期は1秒)として実装
import random
import json
import math
while True:
for nth in range(20):
value = 100 * math.sin(2 * math.pi * nth / 20)
msg = {"data" : value}
print(f'send message {msg} on topic: {TOPIC}')
client.publish(TOPIC, json.dumps(msg), qos=0)
time.sleep_ms(50)Node-REDによって描画される波は以下

50msec周期だと大幅な乱れもなく描画できている。さらにPublishの周期を短くして、10msec 周期にしてみた。
ソースコードは以下
import random
import json
import math
while True:
for nth in range(100):
value = 100 * math.sin(2 * math.pi * nth / 100)
msg = {"data" : value}
print(f'send message {msg} on topic: {TOPIC}')
client.publish(TOPIC, json.dumps(msg), qos=0)
time.sleep_ms(10)ここまで周期が短くなるとさすがに描画も苦しくなって以下のように波形もひずんでいる。

■追記
やはりNode-RED/dashboard/MQTT Clientの組み合わせだと、性能的にちょっと心配な所がある(しかもデータ集計はPythonで行う予定なので、どうにかしてPythonと接続必要)。そんな中、WSLではGUIアプリが動かせると知りまして、だったら、PC上のUbuntu(WSL)でPython + tkinterの組み合わせで自作グラフ描画させたらいいのではと思った。 UbuntuでPython3用 tkinterパッケージのインストールは以下
$ sudo apt-get install python3-tk
パッケージを入れた状態で、以下tkinterモジュールを指定してPythonを起動すると、WSLの環境からTkのWindowが表示できた。
$ python3 -m tkinter
Node-RED環境ではなく、Python3 + MQTT Client + tkinterの組み合わせでグラフ描画させる取り組みを行う。Python環境でデータが取り込めたら、データ解析も同時に行えるので効率が良い。
■追記
RP2040にセンサを取り付けMicroPythonからMQTTでPublishしてUbuntu(WSL)上のNode-REDでSubscribeしてdashboardでグラフ化した例

■参考URL
Tkinterでグラフを表示したい! #Python - Qiita
(tkinterでグラフをリアルタイムに描画する方法が紹介されている)
python - Using MQTT to update Tkinter GUI? - Stack Overflow
tkinterとMQTTを組み合わせる実装例
*1:50msec周期でpublishされるデータは遅延なく描画可能