マイコンボード収集癖で溜まったボードにmicropython を入れて遊んでみました。
目的の半分は、python を使おうと思っているけど、具体的にやることがないと手が動かないからなかなか覚えられない。じゃあ、micropython でプログラムを実際に書くようなことをやればいいんじゃないかな?と思いました。
PCと装置の間をシリアル通信でやり取りして装置の状態をPCの画面でリアルタイムで表示するプログラム(よくあるやつ)を作ろう、と思ったんですが、休日の勉強を兼ねて、PCの方で動かすプログラムはpython + matplotlib + pySerialで作ろう。あー、でもpython 書けないなあ、それに装置のシミュレーターもないとシリアル通信の相手もないなあ、じゃあ、手元のマイコンボードでシリアル通信する装置のシミュレーターを作ろう。micropython をマイコンに入れてそれでシミュレーター作ったら簡単じゃね?
という、簡単なんだか回りくどいんだかわからないことを(休日なので)してみました。
いくつかハマったことなどもあるので、下記に書いておきます。
マイコンボードは引き出しで眠っていた、STMのNUCREO f446re とSTM32F429Iのdiscoveryボードを試しました。 最終的にはどちらも動きましたが、discoveryボードの方はbuild オプションを間違えていてしばらく悩んだ。

まずこちらのいうとおりに、手元のUbuntu linux にgit でmicropython の内容をclone しました。
micropython ディレクトリのREADMEにある通り、まず、mpy-cross をmake しておく必要、その他コンパイラーなどを入れておく必要、がありますが、そのうえで、ports/stm32/で
make BOARD=STM32F429DISC
(BOARD=のオプションはboardsの下にたくさんディレクトリがあるのでそれから選ぶ)
とかすると、firmware.hex などがbuild-STM32F429DISC の下にできますから、それをマイコンボードに書き込めばOK.私は、USBでマイコンボードをPCにつないでwindowsのst-link utility でさくっと書き込みました。
micropython が動作するとteraterm などでPCから接続してプログラミングするわけですが、ボーレートがすぐわかるところに書いていなくて難渋。115200 bps でした。
MicroPython v1.11-72-g9cebead on 2019-06-29; F429I-DISCO with STM32F429
Type "help()" for more information.
>>>
てな感じで、プロンプトが出ますが、ここでpython のプログラミングができるのは面白い。いろいろなやり方があると思いますが、PCのエディタでコードを書いておいて、micropython のターミナルでCtrl-Eでペーストモードに入り、書いたコードをpasteし、そのあとCtrll-Dで実行、やめるときはCtrl-Cというのが一番楽なやり方かな、と思います。プログラムの実行をCtrl-Cでいつでも止められるし、そのあと変数をREPLで書き出したりできるのもデバッガ内蔵という感じで非常にプログラミング学習が楽しいです。
micropython は、ドキュメントを読むと書いてありますが、最初にflash ディスクのboot.py を実行して、そのあとmain.py を実行するようになっているので、プログラムができたらboot.py, main.py の形で書き込んでおくのが良いのだと思いますが、基本的にはこういうので試すのはせいぜい100行程度のちいさなプログラムなので、paste and run の形が最も簡単にいろいろ試せて楽かなと思います。
boot.py, main.py に書き込むのは、ampy とかをpcにインストールしてコマンドプロンプトでやるのもよし、私は、試したなかでは、uPyCraft のようなwindows でのIDE環境がpythonのエディタとterminalが一緒になっていて、ペーストモードでの操作がスムーズなので、割とやりやすかった。main.py をエディタで書いていくんですが、マイコンのmain.py にダウンロードはせず、ターミナルからペーストしてコードを試す方法。
肝心のpython の方は、いつもCとかでダラダラ書く癖が抜けず、苦労しましたが、こんな感じで、PCからコマンドを受けては返すのを書いてみた。正直、これは、input文とprint文をただループさせればいいんですが、input待ちの間に処理をすることができるように、わざわざnon block serial input を書いてみたけど、もっとスマートなやり方があると思う。webでmicropythonの実践的な実装例を探したけど、見つからないんだよな・・・
from math import sin
led=pyb.LED(1)
buf=''
uart=pyb.repl_uart()
def input_nonblock(uart) :
global buf
s1=None
if uart.any():
s=uart.read()
for c in s:
if c==0x0d :
#print(str(buf))
led.toggle()
s1=str(buf)
buf=''
elif c==0x0a:
pass
else:
buf=buf+chr(c)
return s1
def update_vars():
global lason, vlaser,itec,vtec, rtact,iphd,ain1,ain2,freq
phase=((pyb.millis()/1000.)*freq*6.28)%6.28
rtact=10000+sin(phase)*300
def init_vars():
global lason, vlaser,itec,vtec, rtact,iphd,ain1,ain2,freq
freq=1.5
lason=0
vlaser=0
itec=0
vtec=0
rtact=10000
iphd=0
ain1=0
ain2=0
def show_prompt():
print('>>',end='')
init_vars()
while True:
s=input_nonblock(uart)
if (s!=None):
args = s.split(' ')
if (args[0]=='status'):
update_vars()
print()
print(lason,vlaser,itec,vtec,rtact,iphd,ain1,ain2,sep=',')
elif args[0]=='lason' :
if (len(args)>=2):
lason=args[1]
else:
print()
print (str(s))
show_prompt()
pyb.delay(10)
こんなのを書いただけだけど、一応手が動くようにはなったので、休日のpythonの勉強としてはとてもよかった。