Grove-OLED-i2cにFramebufferモジュールを使ってイメージを表示する
2020/4/25+
MCP2221A adafruit_blinka Framebuffer Image
MCP2221A adafruit_blinka Framebuffer Image
概要
MCP2221Aボードで以下のGrove-OLED-i2cにFramebufferモジュールを使ってイメージを表示する. 本記事は「Grove-OLED-i2cをFramebufferモジュールで機能拡張する」の続きになる。
本ボードは、ボードのバージョンによって、解像度が96x96または128x128であり、それぞれでコントローラも異なる。 入手したボードは、v1.1で解像度は128x128でコントローラはSH1107Gであった。(Vdd:3.3V/5V両用対応)
接続
MCP2221Aボードのi2cに本件のOLEDを接続する。(Vdd=3.3V)
該当モジュールのインストール
cd ~/mcp2221a_ws
# 仮想環境に切り替える
source blinka/bin/activate
# sh1107g_cpy.pyをダウンロードする
wget https://beta-notes.way-nifty.com/blog/files/sh1107g_cpy.py
# adafruit_framebufをインストールする
pip3 install adafruit-circuitpython-framebuf
# framebufで使用するフォントをダウンロードする
wget https://github.com/adafruit/Adafruit_CircuitPython_framebuf/blob/master/examples/font5x8.bin
# python3のimageライブラリーをインストールする
pip3 install Pillow
# adafruit_imageloadモジュールをダウンロードする(CircuitPython用)
git clone https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git
cp -r Adafruit_CircuitPython_ImageLoad/adafruit_imageload .
# テスト用画像をダウンロードする(これは任意の画像で良い)
wget https://upload.wikimedia.org/wikipedia/en/5/58/Blinka.png
テスト用画像をビットマップ画像に変換する
以下のスクリプトを実行してテスト用ビットマップ画像を作る:
mk_b1image.py
#!/usr/bin/python3
from PIL import Image
im = Image.open('Blinka.png')
resized_im = im.resize((128,128))
gray_im = resized_im.convert("L")
# 以下の「x < 90」の「90」の画像によって調整すること
tmp_im = gray_im.point(lambda x: 0 if x < 90 else 255)
b1_im = tmp_im.convert('1')
b1_im.save('blinka_b1.bmp')
# inverted image
# 以下の「x < 90」の「90」の画像によって調整すること
tmp_im = gray_im.point(lambda x: 255 if x < 90 else 0)
inv_b1_im = tmp_im.convert('1')
inv_b1_im.save('blinka_inv_b1.bmp')
これにより以下の2つのファイルが作られる。
blinka_b1.bmp
blinka_inv_b1.bmp
デモ・スクリプト(python3/circuitpython兼用)
test_fb1_sh1107g.py
#CIRCUITPY = True
CIRCUITPY = False
# import image related module
if CIRCUITPY:
import displayio
import adafruit_imageload
else:
from PIL import Image
# for CircuitPython/blinka
import time
import busio
import board
i2c = busio.I2C(board.SCL, board.SDA)
i2c.try_lock()
from sh1107g_cpy import SH1107G
oled = SH1107G(i2c)
oled.clear()
#-----------------------------
# framebuffer related
import adafruit_framebuf
# pixel size for display
WIDTH = 128
HEIGHT = 128
fbuf = bytearray(round(WIDTH * HEIGHT / 8))
fb = adafruit_framebuf.FrameBuffer(fbuf, WIDTH, HEIGHT,
buf_format=adafruit_framebuf.MVLSB)
#------------------------------
# write image into framebuffer
def fb_image(fb,img):
# Iterate through the pixels
for x in range(img.width):
for y in range(img.height):
if img.getpixel((x, y)):
fb.pixel(x, y, 1)
else:
fb.pixel(x, y, 0)
# for circuitpython
def fb_image_cpy(fb,img):
# Iterate through the pixels
for x in range(img.width):
for y in range(img.height):
if img[x, y]:
fb.pixel(x, y, 1)
else:
fb.pixel(x, y, 0)
# (for debug) Ascii printer for very small framebufs!
def print_buffer(the_fb):
print("." * (the_fb.width+2))
for y in range(the_fb.height):
print(".", end='')
for x in range(the_fb.width):
if fb.pixel(x, y):
print("*", end='')
else:
print(" ", end='')
print(".")
print("." * (the_fb.width+2))
# clear framebuffer
def clear_fbuf():
for i, _ in enumerate(fbuf):
fbuf[i] = 0
#----------------------------------
print("image test1: ")
clear_fbuf()
if CIRCUITPY:
im, pal = adafruit_imageload.load(
"blinka_b1.bmp",
bitmap=displayio.Bitmap, palette=displayio.Palette)
fb_image_cpy(fb, im)
else:
im = Image.open('blinka_b1.bmp')
im.show()
fb_image(fb, im)
# show display
oled.draw(fbuf, len(fbuf))
time.sleep(4)
print("image test2: ")
clear_fbuf()
if CIRCUITPY:
im, pal = adafruit_imageload.load(
"blinka_inv_b1.bmp",
bitmap=displayio.Bitmap, palette=displayio.Palette)
fb_image_cpy(fb, im)
else:
im = Image.open('blinka_inv_b1.bmp')
im.show()
fb_image(fb, im)
# show display
oled.draw(fbuf, len(fbuf))
time.sleep(4)
変数CIRCUITPYのTrue/Falseでcircuitpython/python3用を切り換えている。
実行
PC(python3)の場合
# 仮想環境を有効化する
source blinka/bin/activate
# 実行する
export BLINKA_MCP2221=1
python3 test_fb1_sh1107g.py
注意:変数CIRCUITPYをFalseにすること。
CircuitPythonの場合
REPL:
import test_fb1_sh1107g
注意:変数CIRCUITPYをTrueにすること。
なお、CircuitPythonで実行する場合、 以下のファイル/ディレクトリをCIRCUITPYにコピーする:
(1)sh1107g_cpy.py
(2)blinka/lib/python3.6/site-packages/adafruit_framebuf.py
# 「python3.6」の部分は、ホストPCの状況に合わせる
(3)test_fb1_sh1107g.py
(4)blinka_b1.bmp
(5)blinka_inv_b1.bmp
(6)adafruit_imageload(デレクトリ)
これは、CIRCUITPY/lib以下にコピーする
動作実績
(1)MCP2221Aボード
正常に動作した(Vdd=3.3V)
(2)CircutPython Teensy4.0
正常に動作した(Vdd=3.3V)
(3)FT232Hボード
i2c.scan()でデバイス・アドレスが返ってこない。(動作せず)(Vdd=5V)
デバイスの仕様としては、5V/3.3V両用対応になっているが本ボードでは動作しないようだ。
参照情報
Framebuffer API
Famebuffer docs (MicroPython-based)
Python library for Seeedstudio Grove devices
Arduino Library for this Grove - OLED Display 1.12inch
download datasheet SH1107_v2.1.pdf
USB-I2CブリッジボードV2(GROVE対応ボード)【MR-GROVE-B】
USB-I2CブリッジボードV2(GROVE対応ブレッドボード版)【MR-GROVE-BB】
MCP2221 Blinka Pinout
CircuitPython Libraries on any Computer with MCP2221
CircuitPython on Linux and Raspberry Pi
CircuitPython 5.0.x - I2C
PCのpython3でCircuitPythonのAPIを使用する(FT232H版)
PCのpython3でCircuitPythonのAPIを使用する(MCP2221A版)
以上