2017年11月14日

Raspberry PiベアメタルでMicroPythonの調査

Raspberry PiをOSを介さずに直接プログラミングすることを「ベアメタル・プログラミング」と呼ぶそうです。
マイコンだと、プログラミングといったらベアメタルが標準だと思いますが、Linuxを使っているとハードウェアは隠蔽されているので、プログラミングといったらカーネルを叩くことがせいぜいで、ハードウェアを直接触るプログラミングには別の名前をつけた、ということでしょうか。

Raspberry Piは、手元に1、2、W Zeroの3台があるのですが、現状ではほぼ積みボードになっていることもあり、MicroPythonをベアメタル・プログラミングでRaspberry Piの上で動かせないのかな? と思って少し現状を調べてみました。

まず、試みている人はいて、おそらく現状で一番進んでいるのはこちらです。

Porting Micropython to the Raspberry Pi – Part 2 – Stefan Naumann

言語のコア部分の動作は確認できていて、移植に際してアンアラインド・アクセスの設定が必要だった等の苦労話も書かれています。
同じ方の、MicroPythonフォーラムでの投稿です。

Raspberry Pi Port - MicroPython Forum

Wrong label-calculation for JUMP-Bytecode on Raspberry Pi, due to unaligned access ・ Issue #3201 ・ micropython/micropython

現状としては、main()から文字列をMicroPythonインタープリタに与えてLチカさせるところまではできているようです。


その先ですが、同じくRaspberry Piベアメタルプログラミングで動かしているIchigoJamのように、HDMIとUSBキーボードでMicroPythonのREPLが使えるようにするには入出力デバイス周りの実装が必要になります。

画面表示については、Raspberry PiのGPUを叩けばいいわけで、こちらにいろいろ先人の事例が紹介されています。

RaspberryPiのVideoCore IV(GPU)を使ってOS無し(ベアメタル)からポリゴン出して遊ぶ - Qiita


一方USBキーボードについては、USBプロトコルスタックを実装しなければならないわけで、これは「経験のある人でも半年かかる仕事」だそうです。

USB peripherals in bare metal? - Raspberry Pi Forums

とはいえ、先人の作ったものが使えればそんな苦労はないわけで、上記のリンクにも3つほどそういったものが紹介されています。
もっとも、マイコンと同様にUARTを使うのであれば、そのような苦労はしなくて済みます。
おそらくステップとしてはまずUARTからREPLを叩けるようにし、そのあと画面出力、次にUSBへと進んでいくべきでしょう。


さらにその先はどうでしょう? EthernetやBluetoothが使えるようになれば、ESP32版MicroPythonを凌駕したと言えそうです。
しかし、Raspberry PiではEthernetは内部的にUSB接続になっているので、まずUSB Host機能、さらにUSB Ethernetドライバが必要になると思われます。
そこまで実現しているプロジェクトとして、上記のリンクでも紹介されているultibo coreがあります。

Ultibo core a bare metal environment for Raspberry Pi - Raspberry Pi Forums

こちらはしかし、なんと全てPascalで書かれているそうです。別の意味ですごいです。

また、同じく上記のリンクで紹介されているcircleもUSBやEthernetのサポートがあります。こちらのほうは、C++です。

rsta2/circle: A C++ bare metal environment for Raspberry Pi with USB

MicroPythonをベアメタルで、かつキーボード、画面、ネットワークが使えるようにしようとすると、circleの上で動かせると良さそうではあります。
ただ、なかなか大きなシステムになってしまいそうです。
ちょっとcircleをダウンロードして見てみましたが、libだけで33000行、includeが1万行くらいです。
また、ライセンスがGPL3.0なので、MicroPythonのライセンスとは合わない感じです。


既存のコードを使わないとすると、自前で最低限のI/Oを実装しなければなりませんが、そういった点で参考になりそうなのは、上にも挙げたQiitaの記事を初めとしたネット上の記事と、以下の書籍です。

BareMetalで遊ぶ Raspberry Pi - 達人出版会

2017年2月号目次|Interface

両方とも購入してみましたが、上の書籍ではベアメタルで開発したバイナリをU-bootを使ってネットワークブートする手法が書かれているのが面白いと思いました。
下のほうはInterface誌ですので丁寧ですし、開発環境をインストールしたVMが入ったDVDが付属しています。

ただ、どちらもUSB Hostの実装まではたどりついていません。HIDデバイスだけなら、Arduino用のライブラリとかを見ながらやれば何とかなるのかもしれませんが・・・。

felis/USB_Host_Shield_2.0: Revision 2.0 of USB Host Library for Arduino.

というわけで、今のところ「USBキーボードとUSB経由のイーサネットをどうするか」が一番の課題のような気がします。
ラベル:MicroPython
posted by boochow at 21:14| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2017年11月12日

1.5インチのOLEDモジュール

oled1-5.jpg

OLEDモジュールは0.96インチと1.3インチのものを持っていたのですが、Aliexpressで1.5インチのものを見かけて買ってみました。
1.3インチはArduboyで使われていたサイズです。
1.5インチは、たった0.2インチの差ですが結構大きく感じます。
また、面積が大きいせいか、ピクセルが明るく感じられます。
ただ、このサイズになるとピクセルがはっきり見えてしまって、128×64よりも高い解像度が欲しいような気がしました。
QRコードなどを表示させるなら、このサイズのほうが良いかもしれませんが。

コントローラはSSD1309というものらしいですが、ドライバはSSD1306のもので問題なく動作しました。
posted by boochow at 17:48| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2017年11月11日

MicroPythonのNeoPixelライブラリを使ってみた

neopixel.jpg

ESP32用MicroPythonでは、電子工作で近年人気の「NeoPixel」を制御するライブラリがデフォルトでインストールされています。
NeoPixelはRGB LEDとコントローラ用ICを一体化したものです。
1本の信号線で制御し、数珠つなぎにすることができます。

コントローラ用ICは「WS2812B」という型番で、この型番で検索すると製品がいろいろ見つかります。
それほど安いものでもないので(8LEDのモジュールが秋月電子で600円)、これまで入手せずにいたのですが、最近Aliexpressで買えば安く入手できることに気づき、別の買い物のついでに1つ購入してみました。ちなみに8LEDのモジュールで$1程度でした。安いところを探せば、$0.6くらいで見つかります。
8×8のモジュールでも$6以下で入手できます。(送料はかかりますが)

neopixel2.jpg


裏面に電極がありますので、ブレッドボードでの実験用にL字型のピンヘッダを取り付けました。
DOUTに別のモジュールのDINを接続すれば、カスケード接続ができるようです。

neopixel3.jpg

ESP32との接続は、GND、3.3V、任意のI/Oピン(私はIO25で実験しました)をそれぞれモジュールのGND、VDC、DINにつなぎます。
モジュールには、電源電圧は4V〜7Vとありますので、3.3Vは微妙に規格外なのですが、問題なく動作しました。
neopixel4.jpg


MicroPythonでのライブラリの使用方法は、以下のページに解説があります。

11. Controlling NeoPixels − MicroPython 1.8.2 documentation

インスタンス生成の際のパラメータは、信号用のPinおよび連結したNeoPixelの個数です。
生成されたオブジェクトは配列の形をしており、1つの要素が1つのNeoPixelにあたります。
要素に対して、(R,G,B)形式のタプルで色を設定し、write()でデータをLEDに転送します。
0番から7番までのピクセルを順に光らせるサンプルはこんな感じです。



このWS2812Bの制御ですが、データシートはAdafruit等からダウンロードできます。

Downloads | Adafruit NeoPixel Überguide | Adafruit Learning System

1bitのデータを1つのパルスで送信し、0か1かの判別はパルスのHの時間(TH)に対する閾値で行なわれます。
1bitは TH+TL=1.25μs±600nsで送り、0を送る場合はTH = 0.4μs±150ns、1を送る場合はTH = 0.8μs±150nsでなければなりません。
データは1ピクセルあたり24ビット、GRBの順で上位ビットから送信です。
また、50μs以上長いLはリセットと見なされます。
カスケード接続する場合は、自分が使った分のデータの次のデータから、後方のNeoPixelへ送られます。
シンプルですが、数珠繋ぎの個数が増えてくると、個数×24bit分のデータの転送に乱れが生じてはいけないのが若干厳しいところですね。
少し詳しい解析記事が以下のリンクにありました。

秋月でWS2812B買ってしまったので動かないかも知れないけれど作ってみた

WS2812B + LPC810

ESP32版MicroPythonでは、このデータ転送の部分はCで記述されています(port/esp32/espneopixel.c)。
割り込みを禁止して一気にデータを送信しています。
ラベル:MicroPython
posted by boochow at 20:27| Comment(0) | ESP8266/ESP32 | このブログの読者になる | 更新情報をチェックする

MicroPython on Web Browser

MicroPythonをブラウザ上で動かしているデモを見つけたので、リンクを貼っておきます。
MicroPython用ハードウェアであるPyBoardと、それに接続されたLEDやサーボモータもエミュレートされています。
手軽に雰囲気を楽しめて良いと思います。

MicroPython on Unicorn

これはMicroPythonの作者によるもので、こちらに解説があります。

MicroPython running "bare metal" in the browser via unicorn.js - MicroPython Forum

QEMUベースのマルチプラットフォームのエミュレータであるUnicornを、EmscriptenでJavaScriptに変換したUnicorn.jsをブラウザ上で動作させ、その上でARM用のMicroPythonを動かしているそうです。
上の記事にもありますが、コードが以下に置かれています。

micropython/micropython-unicorn: MicroPython on Unicorn

さすがに、速度はESP32の上で動かすMicroPythonにはだいぶ劣ります。
サンプルの中にマンデルブロ集合をテキストで出力する例が入っていましたが、同じものをESP32で動かしたら一瞬で終了してしまいます。

オマケとして、このマンデルブロ集合のコードをESP32+ST7735の上でビットマップ出力するように修正してみましたので、以下に載せておきます。



動作の様子です。この動画では1ピクセルずつ描画していますが、上のコードは1ライン分をまとめて描画するように変更しており、もう少し速くなっています。
ラベル:MicroPython
posted by boochow at 15:07| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2017年11月05日

MicroPython + ST7735でのbitmap画像表示

前回、ArduinoのサンプルにあるgraphicstestをMicroPythonに移植したので、ついでに同じくAdafruitのビットマップファイルの表示のサンプルも移植してみました。

ST7735で画像を表示するには、表示させたい矩形領域を指定した後、その領域のピクセルをまとめて転送します。矩形領域の指定と1ピクセルの転送は、ST7735のドライバに_setwindowlocと_pushcolorというメソッドが定義されていますので、これを使います。
1ピクセルは16ビットで、24ビットカラーからの変換関数は同じくドライバ内に用意されています。

画像ファイルが「RGBRGB...」というデータの羅列だとすると、このファイルを読み出してLCDに表示するコードは以下のような感じになります。
ここでは画像ファイルが128×160ピクセルであると仮定しています。

bitmap形式のファイルは、画像サイズや圧縮形式などを記述したヘッダが付きますが、非圧縮のbitmapファイルであればファイルの中身は上記と大差ありません。(ピクセルの並びはBGRBGR...となります)
上のコードにヘッダ部分の処理を追加して、bitmap形式のファイルを表示するサンプル「tftbmp.py」も下記のリポジトリに追加しました。

boochow/MicroPython-ST7735

LCDとESP32との結線は以前と同じですが、再掲します。
なお、ここで使っている1.8インチTFT LCDモジュールのFritzing用データはこちらに置きました。
esp32-st7735r-breadboard.png

このサンプルを動作させるには、ビットマップファイルをMicroPythonのファイルシステムに書き込む必要があります。
uPyCraftはバイナリファイルの転送には向かないので、Adafuit製のツール「ampy」を使いました。
このツールはPythonスクリプトなので、LinuxなどPythonが動作する環境が前提となります。
ツールの解説は以下にあります。

Overview | MicroPython Basics: Load Files & Run Code | Adafruit Learning System

このツールはファイルの転送コマンド「get」「put」があります。
ホスト側からMicroPython側へファイルを転送するには、
$ ampy -p /dev/ttyUSB0 put test128x160.bmp

のようにします。
なお、ファイルの転送には結構時間がかかりますので、気長に待つ必要があります。
Windowsで使えるアップロードツールとしては、MicroPython File Uploaderというのもあるようです。

最後に、動作している様子の動画を載せておきます。
ラベル:MicroPython
posted by boochow at 17:42| Comment(0) | ESP8266/ESP32 | このブログの読者になる | 更新情報をチェックする
人気記事