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 | このブログの読者になる | 更新情報をチェックする

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 | このブログの読者になる | 更新情報をチェックする

2017年11月04日

MicroPython + ST7735でのグラフィックス速度テスト

以前、以下の記事でMicroPythonからTFT LCDへの表示を行っています。

TFT LCD(ST7735R)をMicroPythonで動かしてみた: 楽しくやろう。

しかし、この記事で使っていたAdafruitのライブラリは矩形と水平線・垂直線しか描画できませんでしたので、他のライブラリを探してみたところ以下のライブラリが見つかりました。
(他にhosaka/micropython-st7735というのも見つかりましたが、こちらは描画プリミティブはAdafruit版とあまり変わらないようです)

MicroPython/ST7735.py at master ・ GuyCarver/MicroPython

このライブラリは円やテキスト表示も実装されています。
テキスト表示のフォントデータは、同じリポジトリにsysfont.py、seriffont.py、terminalfont.pyが置かれています。

ただ、このライブラリは作られた時期が2014/11/25と古く、ハードウェアもPyBoardを想定しているようです。そのため、現バージョンのmicropython-esp32で動作するように修正しました。
修正版は以下にアップロードしてあります。

boochow/MicroPython-ST7735

テストプログラムとして、Arduino用ST7735ライブラリに付属していたgraphicstestスケッチを移植してみました。
ただし三角形や角丸矩形は無いので、それぞれ線分の描画や矩形描画で代用しています。また、三角形の塗りつぶしはできないので、省略しました。

このテストプログラムも上記のリポジトリにアップロードしてあります。
動作の様子を載せておきます。

Arduinoよりも遅いですが、MicroPythonで描かれていることを考慮すればこんなものかもしれません。
ただ、少なくとも塗りつぶしはもっと高速にできるはずで、改善の余地がありそうです。
ST7735へのデータ送信は、矩形領域を設定した後、その領域に書き込むデータをSPIで連続して書き込む部分だけがネイティブコードで実行されています。
この連続書き込みの部分を高速化できればかなりの速度向上が見込めるのではないかと思います。

追記:
とりあえず、塗りつぶしの際にループで1ピクセルずつ送っていた処理を32ピクセルずつ処理するようにしてみました。
これだけでもfillrectとhline、vlineはかなりスピードアップしました。
文字表示とlineは、いずれも1ピクセルずつ描画するような実装になっており、現時点では高速化できていません。
ラベル:MicroPython
posted by boochow at 15:17| Comment(0) | ESP8266/ESP32 | このブログの読者になる | 更新情報をチェックする

2017年10月21日

MicroPythonでurequestsを使う

ESP32版のMicroPythonでは、urequestsモジュールが標準で組み込まれています(現時点では)。
これはWebサーバにリクエストを投げて、応答を得るためのライブラリで、PythonのrequestsモジュールのMicroPython版(機能はだいぶ削られていますが)です。

現時点では、GET、HEAD、PUT、POST、PATCH、DELETEの各HTTPリクエストが実装されています。
PATCHというHTTPメソッドがあるんですね。初めて知りました。
ただ、このモジュールのソースを見るとHTTPバージョン1.0でリクエストを投げるようになっているので、HTTP 1.1のメソッドであるPATCHを要求するとエラーになる可能性もあるように思います。

サーバから返された結果はResponseオブジェクトに格納されます。

このオブジェクトは、

 status_code HTTPステータスコード(正常なら200)
 reason HTTPステータスコードのReason(正常なら'OK')
 encoding 文字コード(ただし現状では'utf-8'固定の実装となっている)
 content 生の応答データ
 text contentをencodingに従ってテキストに変換したもの
 json() contentをjsonとして解釈したもの(ujsonモジュールを使用)
 
を得ることができます。

内部的には、HTTPヘッダを読み終えた時点でソケットオブジェクトがResponseオブジェクトに渡されます。
ソケットオブジェクトはrawプロパティにセットされ、contentが初めて参照されたときにそのソケットからデータを読んでオブジェクト内にキャッシュするようになっています。
ソケットをcloseするには、close()を呼びます。

何度か例題に取り上げた、現在の為替レートを得るWebサービスにアクセスするには、以下のようになります。



WiFiに接続する部分は上記には入っていませんが、それでも短いですね。

ただし、現時点ではこのコードはESP32/ESP8266のMicroPythonでないと動かないと思います。
urequestsは内部でsocket.readline()を使用していますが、CC3100やWIZnet5Kなど、上記以外のNICではreadline()が実装されていないからです。

そのため、WIZnet5Kに関してはTCP/IP実装はlwIPを使用し、WIZnet5Kは単なるイーサネットインタフェースとして使用するようなMicroPython側のドライバ実装が現在テスト中のようです。

stm32: Incorporate lwip stack and use Wiznet in MACRAW mode by dpgeorge ・ Pull Request #3379 ・ micropython/micropython

ただ、TCP/IPをメインCPUで処理するため、WIZnet5Kのソケット機能を使う場合よりも速度は低下するようです。
ラベル:MicroPython
posted by boochow at 18:28| Comment(0) | ESP8266/ESP32 | このブログの読者になる | 更新情報をチェックする

2017年10月07日

TFT LCD(ST7735R)をMicroPythonで動かしてみた

st7735r-micropython.jpg

ESP32+MicroPythonで、SPIでOLED表示ができたので、同じくSPI接続のTFT LCDも動かしてみました。
使用したLCDはこちらの記事で使用したもので、128×160ピクセル、コントローラはST7735系です。
MicroPythonでのドライバは、おなじみのAdafruitのものがありました。

adafruit/micropython-adafruit-rgb-display: MicroPython library for RGB pixel displays.

結線は基本的には前回使用したOLEDと同様に
LCD  ESP32
VLED 3V3
RST IO17
A0 IO16(DC)
SDA IO13(MOSI)
SCK IO14(CLK)
VCC 3V3
CS IO5
GND GND
と接続してみました。

esp32-st7735r.png


ソフトウェアですが、上記のAdafruitで公開されているファイルのうち、
rgb.py
st7735.py
の2つが必要です。

まずrgb.py、次にst7735.pyを転送もしくはREPLでコピペします。
やり方は以前と同じです。

使い方の例です。冒頭の写真の表示を出力します。
from machine import Pin, SPI
spi = SPI(1, baudrate=30000000, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
lcd = ST7735R(spi, dc=Pin(16), cs=Pin(18), rst=Pin(17))
lcd.fill(0)
for x in range(128):
for y in range(160):
lcd.pixel(x,y,color565(x*2, y*3//2, 255-x-y*3//4))

st7735.pyではST7735とST7735Rの二つのクラスが定義されていますが、私のLCDモジュールはST7735Rのほうで動作しました。
SPIのビットレートを早くしすぎるとディスプレイのほうが追いつかない(ドットが1つ飛ばしになる)ので、もしうまく動作しない場合はbaudrateの値を小さくしてみてください。

全部Micropythonで書かれているので、さすがに実行速度はあまり早くありません。
しかし、インタープリタで実行できる有難味は捨てがたいですね。
ラベル:MicroPython
posted by boochow at 19:36| Comment(0) | ESP8266/ESP32 | このブログの読者になる | 更新情報をチェックする
人気記事