【v1】micro:bit (MicroPython)で温度・明るさのシリアル通信・本体ログ

0. はじめに

micro:bit v1用の記事です。micro:bit v2でも下記方法は可能ですが、便利なlog moduleを利用する方法がありますので、そちらもお試しください。

前回

micro:bit事始め。前回はMakeCode Editorのブロックを使い、シリアル通信による温度変化のグラフ表示を試しました。

vivitelaeti.hatenablog.com

今回

今回は、前回の予告通り、単に等価のコードをMicroPythonで書いてみようかと思っていましたが、MakeCode Editorのブロックから移植するだけでなく、内容も発展させて、測定対象と出力形式を加えてみます。

  • 測定対象:温度に加えて明るさも測定する。
  • 出力形式:グラフ表示やPCへのデータ保存に加えて、MakeCode Editorではできないmicro:bit本体へのログ保存も行う。

MicroPython

MicroPythonとは、マイクロコントローラなど制限のある環境で動作するPython3と基本的な互換性のあるプログラミング言語です(MicroPython公式)。通常のPython(CPython)との差異は、同サイト上のドキュメントの通りです。

micro:bitのためのMicroPythonについては、このMicroPythonのサイトとは別に次に公式ドキュメントがあります。

公式ドキュメントは、チュートリアルAPIリファレンス、開発者ガイドの3部構成ですが、最初のチュートリアルは遊び心が散りばめられていて読んでいて楽しい。これに沿ってコーディングしていくと主な機能を試すことができます。

micro:bitでのMicroPythonの利用を紹介した日本語のウェブサイトで初心者向けのものとしてはこちらが見つかりました。他に、日本語でも、高度な使い方を紹介しているブログがありますが、やはり全体に英語のリソースが多いです。

Make CodeのPython(参考)

なお、2020/6/12のMake Code 2020へのアップデートにより、Make Code EditorでもPythonへの切り替えがサポートされましたが、これはMicroPythonとは別物です。

Python language support
In addition to being able to view your code in Javascript. You can now switch to a Python view in the editor.
This is a MakeCode flavour of Python and not the same as MicroPython available in the Python Editor and other third party editors, so you won't be able to use MakeCode Python in another editor
MakeCode 2020 update : Help & Support

1. エディタ

micro:bit専用、又はmicro:bitを主な対象とするMicroPython用のエディタ2種類を紹介します。
その他にも、PyChamでのPlugin利用やEduBlocksのようなコードブロックエディタなど多数の選択肢があります(GitHub - carlosperate/awesome-microbit: A curated list of BBC micro:bit resources.)。

Python Editor (Online)

まずは、micro:bit公式のLet's code > Pythonで紹介されているオンラインのPython Editorです。

Makecode Editorと同じく、PCからブラウザでPython Editorにアクセスすれば直ちに使える手軽さ、機能や設定項目もシンプルで、第一候補となりそうです。ただし、グラフ化の機能はなく、micro:bit本体のファイルシステムへのアクセスもできないようです。

Mu (Offline)

次に、micro:bit公式のLet's code > Other editorsで紹介されているMu(ミュー)です。
micro:bitのためのMicroPython公式ドキュメントではMuが推奨されており、こちらを先に紹介すべきなのかもしれません。

機能的にはPlotterでグラフ化できるほか、micro:bit本体のファイルシステムへのアクセスも可能です。

教育用途を意識したシンプルなデザインであり、本格的なIDEに比肩するものではありませんが、簡単な補完機能など基本的な機能も揃っています。ただし、 Mu Editorは独自環境下のPython3を実行するため、必要なライブラリをインストールした既存環境がある場合にそれを使うことができないという不便さがありそうです(Facilitate installation of 3rd party packages for use with Mu · Issue #675 · mu-editor/mu · GitHub)。

Muのコンセプト

Muのコンセプトについては、公式サイトのAboutにて、アラン・ケイさんの言葉を引用して次のように説明しています。

Alan Kay's quote about learning to program summarizes Mu's outlook. Mu aspires to be "the real thing" as a development environment for beginner programmers taking their first steps with Python.

より詳しいことは開発者向けドキュメントにありますが、同ドキュメントで紹介されている主な開発者であるNicholas H.Tollerveyさんのプレゼンテーションも興味深いです。

youtu.be

プレゼンの17:00〜のScratch/BlockyとMu/Pythonのanalogyに関して、そこまではっきりしたものであるか(Scratchも十二分に右のイメージのようになるのではないか)は素人的には疑問もありますが、Muの意義をどのように考えているかが伝わってきます。

なお、プレゼンのこのあたりで、Scratch/BlockyとMu/Pythonのイメージの間に、EduBlocksを位置付けておくべきだったとの説明があります。EduBlocksは聴き慣れませんでしたが、micro:bit公式のLet's code > Other editorsで紹介されています。開発者のJoshua Loweさんが12歳のときから開発を続けているものです(Joshua Lowe - EduBlocks - Tech4Good Awards)。

ざっと触ってみた限り、EduBlocksは、コードが書かれたブロックを組み立てる形式であり、ビジュアルプログラミングからテキストプログラミングへの橋渡しにうってつけのように感じます(小さなMakerたちの作品が集合! プログラミング好きな小中学生の交流を促すイベント「Kids Maker Festival」レポート - Watch Headline)。EduBlocksにはmicro:bitモードもあり、今回は使用しませんでしたが別の機会に試してみたいです。

Muのインストール方法

Muは、基本的にこちらのDownloadからOS毎のインストーラーをダウンロードしてインストールする必要があり、オンラインのPython Editorと比べれば一手間かかりますが、複雑な設定は必要ありません。
ただし、環境によってはトラブルが生じることもあります。手元のWindows 10 version 1909では問題ないのですが、Mac OS 10.13 High Sierraでは(PortaMuではなくインストールする方の)安定版が起動せず、Alpha版のみ起動する状況です。Alpha版はPython3のREPLが正常に動作しないなど問題もあります。

上記がDownloadページです。

なお、Windows/Mac OSについてはインストールせずに利用可能なPortaMuも準備されていますので、制約のある環境や試しに使って見たいという場合はこれが良さそうです。

micro:bit以外(参考)

Muは、元々micro:bit専用のエディタとして開発されたようですが、現在ではModeの切り替えにより、Alpha版も含めると以下のプログラミングが可能です。ここでは、後の応用編とでPython3モードを試しています。

  • micro:bit
  • CircuitPython
  • ESP8266/ESP32(Alpha版のみ)
  • Pygame Zero
  • Python 3
  • FlaskによるWebサイト(Alpha版のみ)

Modeのアイコンをクリックすると次のようにモードを選ぶことができますので、ここでちゃんとmicro:bitが選択されていることを確認してからコーディングに進みます。

←  安定版             Alpha版  →

2. シリアル通信

コード

10秒毎に温度と明るさを測定しprintするコードです。

from microbit import *

# 初期表示
display.scroll("temp/lt")
sleep(500)

# 10秒毎の測定・printループ
while True:
    # 温度測定
    temp = temperature() 
    # 明るさ測定
    lt = display.read_light_level() 
    # REPL/Plotterでの表示
    print((temp, lt)) 
    # 10秒待つ
    sleep(10000) 

温度測定

公式ドキュメントでは「Microbitモジュール」の箇所に記載があります。

microbit.temperature()
micro:bit の温度を摂氏で返します。
Microbit モジュール — BBC micro:bit MicroPython 1.0.1 ドキュメント

プロセッサ上にセンサーがあるため、周囲の温度より高めに出ます。

温度センサーの値は、このプロセッサーの温度になるので、マイクロビットが置かれている部屋の室温とは異なります。
【micro:bit(マイクロビット)でプログラミング】内蔵された温度センサーによる温度計 | micro:bit Lab.【マイクロビット】

MakeCodeでも温度センサを使ったプロジェクトが紹介されています(Features in depth | micro:bitのTemperature sensor)。
プロジェクトページではMakeCode Editorのブロックが先に出てきますが、PythonをクリックするとMicroPythonのコードに切り替わります。

明るさ測定

公式ドキュメントでは「ディスプレイ」の箇所に記載があります。

microbit.display.read_light_level()
ディスプレイの LED を逆バイアスモードで利用して、ディスプレイのまわりの光量を検出します。戻り値は明度を表す 0 から 255 までの整数値で、値が大きいほど強い明度を意味します。
ディスプレイ — BBC micro:bit MicroPython 1.0.1 ドキュメント

MakeCodeでも明るさセンサを使ったコードが紹介されています(Features in depth | micro:bit のLight sensor)。
プロジェクトページではMakeCode Editorのブロックが先に出てきますが、PythonをクリックするとMicroPythonのコードに切り替わる点は同様です。

REPL/Plotterでの表示

REPLでの表示だけであればタプルにする必要がないですが、MuのPlotterでのグラフ表示をする場合、タプルをprintする必要があります(Plotting Data with Mu)。誤ってprint(temp)print(lt)とするとグラフ表示されない。

今回は、 tempとltの2要素あるため、print((temp, lt))ですが、仮に温度測定のみでtempの一要素だけであっても、print((temp, ))とタプルにしなければなりません。 1要素だけでも、タプル内にカンマが必要です。

個々の要素を表現する式をカンマで区切って構成します。単一の要素からなるタプル (単集合 'singleton') を作るには、要素を表現する式の直後にカンマをつけます
3. Data model — Python 3.10.8 documentation

MakeCode Editorのブロック(参考)

なお、MakeCode Editorのブロックでは次のようなコードとなります。

実行方法・結果

Python Editor (Online)

Python Editorを開きコードを入力。

コードをmicro:bitに書き込む手順は、MakeCode Editorと似ています。

  1. micro:bitとPCのUSBコネクタを繋ぐ
  2. Connectのアイコンをクリック
  3. WebUSB設定画面が表示されたら接続をクリック2
  4. Flashのアイコンをクリック("Flashing micro:bit"とポップアップ表示され、進捗はプログレスバーと完了時のチェックマークで確認可能)

Flash後に再起動したmicro:bitで測定できた温度と明るさは、Open Serial (REPL) をクリックすると次の通りに数字で表示され更新されていきます。

Mu (Offline)

Muでのコードの書き込みは、さらにシンプルです。

  1. micro:bitとPCのUSBコネクタを繋ぐ(最下部のステータスバーにDetected New BBC micro:bit deviceと表示される)
  2. Flashのアイコンをクリック(少し間が空いて、最下部のステータスバーにFinished Flashingと表示される)

Python Editorと違って、Flashプログレスバーの表示がないので、書き込みに時間がかかる場合はトラブルが起きていないか少々不安になりますがじっと待つ。

REPLとPlotterのアイコンをクリックすると、次の通り測定値が数値とグラフで表示されますね。

MuのREPLについての一般的な説明はWhat is a REPL?を参照。Python3モードのREPLで一行ずつコードを打ち込んで実行結果を確認する説明があります。最後の方に、micro:bitモードの記載も少しあります。

MuのPlotterについてはPlotting Data with Muです。データ形式をタプルにしてprintすれば、グラフを表示できるという機能です。

Plotterに表示されたデータは、自動的には mu_codeディレクトリ直下のdata_captureディレクトリに.csv形式のファイルで保存されていますので、micro:bitをPCに繋いだまま温度と明るさを測定する場合、後からデータをこの自動保存されたファイルで後からデータを確認することもできますね。

次のセクションでわざわざ本体でログを取るのは、PCを離れて温度や明るさ測定をするためです。

ターミナル等(参考)

ちなみに、ターミナル等からシリアル通信しても良いです(REPL へのアクセス — BBC micro:bit MicroPython 1.0.1 ドキュメント)。mac OSの場合、ターミナルからscreen /dev/cu.usbmodemXXXX 115200でこのようになります(XXXXは ls /dev/cu.*で調べたポートの情報に置き換える)。

シリアル通信の終了はCtrl-A の後に Ctrl-¥(バックスラッシュ)で質問にYesと回答。

3. 本体ログ

いよいよ本体でログを取ります。micro:bitを屋外に設置してみるため、雨風を防ごうと100均のアクリルケース(外寸W60 * H77 * D 42)に入れてみました。温度をとる観点からは密閉すべきでないのかもしれません。

コード

1時間毎に温度と明るさを測定して結果を本体のファイルに書き込むコードです(printも残しています)。
先程とは違い、本体をPCと繋いでいない状態でも測定・記録できるので、電池をつないで屋外に放置しておき、後でPCと繋いで1日の測定結果を確認するという使い方もできます。

from microbit import *
import time

# 初期化・初期表示
log_count = 0 # ログ回数の初期値。時刻の代わりとする
log_file = "log.csv" # 本体ログファイル名。フラットファイルシステムのためディレクトリは指定不可。
log_data = "time,temp,lt\n" # ログデータの初期値(表の最初の列)
display.scroll("temp/lt") # 本体LEDでプログラム名を表示

# Aボタンが押されるまで待つ
while not button_a.was_pressed():
    sleep(1000)

# Aボタンが押された直後の表示
display.show(Image.SNAKE) # 正常動作確認用
sleep(1000)
display.clear()

# ログ初期化
with open(log_file, "w") as f:
    f.write(log_data)

# 1時間毎の測定・記録ループ
while True:
    # 開始後の初カウントを1、その後1ずつ増加させる。
    log_count += 1
    temp = temperature()
    lt = display.read_light_level()
    print((temp, lt))
    # ログの読み込みと出力
    with open(log_file, "r") as f:
        log_data = f.read()
    with open(log_file, "w") as f:
        f.write(log_data + str(log_count) + "," + str(temp) + "," + str(lt) + "\n")
    # 1時間待つ
    time.sleep(3600)

ファイルシステム

公式ドキュメントに説明がありますが、約30KBのフラットファイルシステムディレクトリ構造なし)です。

ファイルシステムへのアクセスは、後述のMuのFilesを使う方法が簡単ですが、microFSというツールも用意されています(GitHub - ntoll/microfs: A simple command line tool and module for interacting with the simple filesystem on the BBC micro:bit.)。

ファイルI/O

ファイルについては、仕様上、追加的書込み(append)ができないので、一度ログファイル全体を読み込んでから、追加のデータを加えて、書き込んでいます。

注釈
ファイルを開いて書き込むとき、ファイルがすでに存在する場合はファイルの内容を上書きします。
ファイルにデータを追加するには、最初にそれを読み出し、読み出した内容をどこかに保持し、ファイルを閉じ、読み込んだ内容にデータを追加して、再度ファイルを開いて、改訂した内容を書き直す必要があります。
これは MicroPython の場合ですが、 "通常の" Python では "append" モードで書き込むファイルを開くことができます。micro:bit でこれを行うことができないのは、ファイルシステムの実装を簡略化したためです。 ストレージ — BBC micro:bit MicroPython 1.0.1 ドキュメント

今回のように1時間毎で1日分測定・記録するのであれば問題ないですが、高頻度や長時間で測定・記録すると、上記の通り一度ログファイル全体を読み込む関係で、ストレージの上限である約30KBに達する前に、RAMの上限である16KB(Hardware)に達することが原因で020エラー(micro:bit 020 error : Help & Support )が起きます。

なお、本来は次のコードのようにファイルI/Oのエラー処理をすべきですが、端折っています。 Max-min temperature logger | micro:bit

time.sleep()

1時間おきの計測のために、sleepのミリ秒単位を使っても良いのですが、秒単位の方が分かりやすいので最初にtimeをimportしてtime.sleepを使っています。

実行方法・結果

電池を繋いだmicro:bitを持って屋外に行き、Aボタンで測定開始。

1日放置したmicro:bitを回収してPCに繋ぎます。そこから、Muを起動して、でmicro:bit本体のファイルシステムにアクセスするのですが、その方法も至ってシンプル。

Filesアイコンをクリックして、左側のfiles on your micro:bitから、右側のfiles on your computerへとドラッグ&ドロップするだけです(操作のアニメーションはMu and micro:bitのページ中段あたり)。

そのまま、右側のfiles on your computerに移されたファイルを右クリックしてopenすると関連付けられたアプリケーションで開くことができます。
ファイル本体は mu_codeディレクトリにあります。

これをExcelで開き、timeの列を調整(午前6時に測定開始したため、timeにそれぞれ5を加える)。

そして、そのままExcelで、温度と明るさに左右2軸を充ててグラフ化。Plotterのグラフより分かりやすいです。

午前7時頃の明るさがおかしいですが何かの照り返しかもしれません。それ以外は午後1時、2時をピークとする日中の温度や明るさの変化が分かります。
上記の通り、プロセッサ上にあるセンサーを使うため、温度は実際より高めに出るので、予め、他の温度計を使って実際の外気温との差を図っておき、後で補正する対応が必要ですね。明るさも相対値なので、自由研究などで使う場合は、いずれの数値も説明が必要となりそうです。

4. 応用編

応用編として、Pythonによるグラフ描画、そして、測定項目の追加(温度だけでなく湿度や気圧など他の気象観測)もできればと思い、調べてみました。

Pythonによるグラフ描画

このグラフは、Python3の下記コードの通り、pandasを利用してログを読み込み、matplotlib.pyplotで表示しています。細かい調整はしていませんが、Excelのグラフと比べると測定された最低温度がY軸の下限となっており、温度変化が分かり易いです。

どう実行するかですが、本記事で紹介しているMu EditorのPython3モードで次のコードを保存し、単にRunアイコンをクリックすると、ライブラリの不足についてエラーが出ます。実行環境にAnacondaをインストールしているなどpandasとmatplotlibのいずれのライブラリもターミナルからの実行では問題なく利用できる場合にも。

これは、Mu Editorから実行されるPython3は/Applications/mu-editor.app/Contents/Resources/以下にある独自環境のもので、ターミナルからの実行環境とは異なるためのようです。

そこで、pip install XXX --target /Applications/mu-editor.app/Contents/Resources/app_packagesなどとしてpipの--targetオプションでMu Editorの実行環境のapp_packagesに必要なライブラリ(今回はpandasとmatplotlib)をあらかじめインストールしておく必要があります。これをしておけば、エラーは出てしまいますが、Mu Editorからでもこのグラフ描画はできました。

import pandas as pd
from matplotlib import pyplot as plt

# ログ読み込み
log = pd.read_csv("log.csv", index_col=0)

# 温度と明るさ毎にグラフ関連付け
s = log.index
fig, ax1 = plt.subplots()
ax1.plot(s, log['temp'], color="r", label="temp")
ax2 = ax1.twinx()
ax2.plot(s, log["lt"], color="b", label="lt")

# タイトルや軸ラベル
ax1.set_title("temp/lt")
ax1.set_ylabel("temp")
ax2.set_ylabel("lt")

# 凡例
ax1.legend(loc="upper left")
ax2.legend(loc="upper right")

# 表示
plt.show()

拡張ボード+Make Code Editorによる測定項目の追加

weather:bitやTFW-EN1といった拡張ボードを利用する方法がメジャーのようです。この場合、製造元が提供されている拡張ブロックをMake Code Editorで読み込んで使うことになり、MicroPythonを利用した方法の説明はないようです。

Grove拡張ボードとBME280を組み合わせた例でも、TFW-EN1の拡張ブロックが使えたとの報告がありますので、この方法ならば選択肢は色々あります。

I2C通信+MicroPythonによる測定項目の追加

他方、MicroPythonにこだわる場合、MicroPythonを使ってI2C通信もできるので、micro:bitをI2Cの機器と直接つないでやるのが良さそうですね。Make Code Editorでも出来そうです。大人の夏休みの自由研究…としては、自分の技量を考えるとハードルが高いですが、またいつか。


  1. Alpha版はQtを利用しているところ、その対象プラットフォームが限定的なので安定版より動作環境が限定されているようです。もっとも、Qtは現時点ではmacOS 10.13以上のサポートのようであり(Supported Platforms | Qt 5.15)やはり良くわかりません。

  2. WebUSBの利用には、micro:bitファームウェア0243以上であること、ブラウザが対応していることが必要となる。WebUSB Troubleshooting : Help & Supportを参照。