うーん。
タイトルやここで行っていることは、どういう表現が適切なんでしょうねえ。
MicroPythonの標準的なOLEDディスプレイドライバssd1306では、文字列の出力はtext()メソッドを使用して、座標を指定して出力するようになっています。
コンピュータの文字出力用のコンソールあるいは端末では、ただ文字列を出力すると、文字が左から右に、上から下に、下の端に行きついたら外面が上にスクロールして表示されますよね。
あのある意味普通で御気楽な文字列出力機能が欲しいので、そのドライバを作りました。
OLEDCSドライバ
TFTディスプレイ用などOLEDディスプレイだけではない幅広い拡張性を考えると、ssd1306ドライバの基礎になるFrameBufferを拡張すべきなのですが、そうすると、それを継承する標準のssd1306を書き換える必要が出てきます。特にESP8266では、ssd1306がファームウェアに組み込まれているので、ファームウェアの再構築などをしてssd1306ドライバを置き換えるのは面倒です。
ということで、ssd1306ドライバ(のSSD1306_I2C)を拡張する形で実装したドライバ例を示します。ssd1306ドライバがスーパークラスですが拡張機能の一部として、1.3インチのOLEDディスプレイに多用されているSSH1106も利用できるようにしております。
"""
OLEDCS_I2C OLED Display Driver (ssd1306, ssh1106)
for MicroPython
Version 1.0
Copyright 2023 K.Kakizaki
OLEDCSライブラリ: OLEDディスプレイのコンソール的利用 (MicroPython)
"""
import ssd1306
from micropython import const
class OLEDCS_I2C(ssd1306.SSD1306_I2C):
SSD1306 = const(0)
SSH1106 = const(1)
SET_LOW_COL = const(0x00)
SET_HIGH_COL = const(0x10)
SET_PAGE_ADDR = const(0xb0)
def __init__(self, width, height, i2c, chip=SSD1306, addr=0x3C, external_vcc=False):
self._cx = 0
self._cy = 0
self._chip = chip
super().__init__(width, height, i2c, addr, external_vcc)
def print(self, text):
txt = str(text)
while (txt.find('\n') > 0):
idx = txt.index('\n')
ctxt = txt[0:idx]
txt = txt[idx+1:]
self.println(ctxt)
l = len(txt)
while (l + self._cx > self.width // 8):
cl = self.width // 8 - self._cx
l = l - cl
ctxt = txt[0:cl]
txt = txt[cl:]
self.text(ctxt, self._cx*8, self._cy*8,1)
self._scroll_check()
self.text(txt, self._cx*8, self._cy*8,1)
self._cx += l
self.show()
def println(self, text=''):
self.print(text)
self._scroll_check()
self.show()
def _scroll_check(self):
self._cx = 0
self._cy += 1
if (self._cy * 8 >= self.height):
self._cy -= 1
self.scroll(0, -8)
self.fill_rect(0, self.height-8, self.width-1, self.height-1, 0)
def setCursor(self, x, y):
self._cx = x
self._cy = y
def getCursor(self):
return (self._cx, self._cy)
def clear(self):
self.fill(0)
self.setCursor(0,0)
self.show()
def show(self):
if self._chip == SSD1306:
super().show()
else:
for page in range(0, self.pages):
self.write_cmd(SET_PAGE_ADDR | page)
self.write_cmd(SET_LOW_COL | 2)
self.write_cmd(SET_HIGH_COL | 0)
self.write_data(self.buffer[page * 128:(page + 1) * 128])
OLEDCSの機能概要
oledcsの追加メソッドを紹介します。oledcsはssd1306を継承して作成しているので、従来のssd1306の機能はグラフィックスを含めて同様に使用できます。
- print(obj) 文字列だけでなく、数値、オブジェクトなどstr()関数で文字列化可能なものは一通り出力できます。文字列の中に改行文字'\n'があればそこで改行します。
- println(obj) print(obj)の最後に改行機能を加えたものです。引数が指定されていなければ改行のみを行います。
- setCursor(x,y) 文字カーソルを指定した位置に移動させます。xは横、yは縦軸です
- getCursor() 文字カーソルの現在位置を返します。
- clear() 画面を消去し文字カーソルを(0, 0)に設定します。
なお、上記のメソッドでは、画面の変更を表示に反映させるためのshow()メソッドを使用する必要はありません。
OLEDCSの利用例
oledcsの利用例を示します。従来は、ssd1306をインポートしSSD1306_I2Cをインスタンス化していましたが、そこをoledcsとOLEDCS_I2Cに置き換えると、これまでのプログラムと同様に動きます。
従来と同じ機能だけだと価値がありませんが、いちいち表示位置を指定せずにprint(), println()が使えるところが強みですね。
長い文字列でも行の右端で改行して出力されること、改行文字があればそこで改行されること、最下行の出力では、必要に応じて画面がスクロールすることなどが確認できます。
from machine import Pin, I2C
from oledcs import OLEDCS_I2C
import time
i2c = I2C(0) # STM32 は3
# i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=400000) # ESP32-S3, ESP32-C3
# i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000) # ESP32
# i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) # ESP8266
# i2c = I2C(0, scl=Pin(13), sda=Pin(12), freq=400000) # RP2040
oled = OLEDCS_I2C(128, 64, i2c)
oled.println('123456789012345678901234567890')
time.sleep(3)
for i in range(1,20):
oled.print('OLED-')
oled.println('{:.3f}'.format(1/i))
time.sleep(3)
oled.println('OLEDCS Driver for MicroPython Version 1.0\nCopyright 2023 K.Kakizaki')
SSH1106への対応
インスタンスの生成時にコントローラチップを特に指定しない場合には、SSD1306を使用した0.96インチのOLEDディスプレイを想定して処理を行いますが、以下の例のように、コントローラチップとしてSSH1106を指定すると、1.3インチディスプレイを操作することができます。
# oled = OLEDCS_I2C(128, 64, i2c)
# コントローラチップとしてSSH1106を指定
oled = OLEDCS_I2C(128, 64, i2c, chip=OLEDCS_I2C.SSH1106)