空いていたので、超小ネタでいきます。
micro:bit Advent Calendar 2021の8日目の記事でI2CのSSD1306 OLEDが使えるようにssd1306モジュールを書き換えましたが、SSD1306 OLEDにはSPIインタフェースのものもあるので、これにも対応するよう書き換えます。
--- micropython/drivers/display/ssd1306.py 2021-11-27 19:36:01.000000000 +0900
+++ ssd1306.py 2021-12-10 19:59:30.000000000 +0900
@@ -114,50 +114,47 @@
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
- self.write_list = [b"\x40", None] # Co=0, D/C#=1
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
- self.i2c.writeto(self.addr, self.temp)
+ self.i2c.write(self.addr, self.temp)
def write_data(self, buf):
- self.write_list[1] = buf
- self.i2c.writevto(self.addr, self.write_list)
+ data = b'\x40' + bytes(buf)
+ self.i2c.write(self.addr, data)
class SSD1306_SPI(SSD1306):
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
- self.rate = 10 * 1024 * 1024
- dc.init(dc.OUT, value=0)
- res.init(res.OUT, value=0)
- cs.init(cs.OUT, value=1)
+ dc.write_digital(0)
+ res.write_digital(0)
+ cs.write_digital(1)
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
import time
- self.res(1)
+ self.res.write_digital(1)
time.sleep_ms(1)
- self.res(0)
+ self.res.write_digital(0)
time.sleep_ms(10)
- self.res(1)
+ self.res.write_digital(1)
+ self.spi.init()
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(0)
- self.cs(0)
+ self.cs.write_digital(1)
+ self.dc.write_digital(0)
+ self.cs.write_digital(0)
self.spi.write(bytearray([cmd]))
- self.cs(1)
+ self.cs.write_digital(1)
def write_data(self, buf):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(1)
- self.cs(0)
+ self.cs.write_digital(1)
+ self.dc.write_digital(1)
+ self.cs.write_digital(0)
self.spi.write(buf)
- self.cs(1)
+ self.cs.write_digital(1)
3Dキューブのアニメーションは SSD1306_I2C の代わりに SSD1306_SPI を使うように変えるだけです。
# 3D CUBE MicroPython version with micro:bit and ssd1306 OLED
from microbit import spi, sleep, pin8, pin9, pin16
from math import sin, cos
from ssd1306 import SSD1306_SPI
X = const(64)
Y = const(32)
oled = SSD1306_SPI(X * 2, Y * 2, spi, dc=pin8, res=pin9, cs=pin16)
f = [[0.0 for _ in range(3)] for _ in range(8)]
cube = ((-20,-20, 20), (20,-20, 20), (20,20, 20), (-20,20, 20),
(-20,-20,-20), (20,-20,-20), (20,20,-20), (-20,20,-20))
while True:
for angle in range(0, 361, 3): # 0 to 360 deg 3step
for i in range(8):
r = angle * 0.0174532 # 1 degree
x1 = cube[i][2] * sin(r) + cube[i][0] * cos(r) # rotate Y
ya = cube[i][1]
z1 = cube[i][2] * cos(r) - cube[i][0] * sin(r)
x2 = x1
y2 = ya * cos(r) - z1 * sin(r) # rotate X
z2 = ya * sin(r) + z1 * cos(r)
x3 = x2 * cos(r) - y2 * sin(r) # rotate Z
y3 = x2 * sin(r) + y2 * cos(r)
z3 = z2
x3 = x3 + X
y3 = y3 + Y
f[i][0] = x3 # store new values
f[i][1] = y3
f[i][2] = z3
oled.fill(0) # clear
oled.line(int(f[0][0]), int(f[0][1]), int(f[1][0]), int(f[1][1]), 1)
oled.line(int(f[1][0]), int(f[1][1]), int(f[2][0]), int(f[2][1]), 1)
oled.line(int(f[2][0]), int(f[2][1]), int(f[3][0]), int(f[3][1]), 1)
oled.line(int(f[3][0]), int(f[3][1]), int(f[0][0]), int(f[0][1]), 1)
oled.line(int(f[4][0]), int(f[4][1]), int(f[5][0]), int(f[5][1]), 1)
oled.line(int(f[5][0]), int(f[5][1]), int(f[6][0]), int(f[6][1]), 1)
oled.line(int(f[6][0]), int(f[6][1]), int(f[7][0]), int(f[7][1]), 1)
oled.line(int(f[7][0]), int(f[7][1]), int(f[4][0]), int(f[4][1]), 1)
oled.line(int(f[0][0]), int(f[0][1]), int(f[4][0]), int(f[4][1]), 1)
oled.line(int(f[1][0]), int(f[1][1]), int(f[5][0]), int(f[5][1]), 1)
oled.line(int(f[2][0]), int(f[2][1]), int(f[6][0]), int(f[6][1]), 1)
oled.line(int(f[3][0]), int(f[3][1]), int(f[7][0]), int(f[7][1]), 1)
oled.line(int(f[1][0]), int(f[1][1]), int(f[3][0]), int(f[3][1]), 1)
oled.line(int(f[0][0]), int(f[0][1]), int(f[2][0]), int(f[2][1]), 1)
oled.text('3D CUBE', 0, 0)
oled.show() # display
sleep(1)
I2C インタフェースの OLED と micro:bit のピンとは以下のように配線しました。
OLED | micro:bit |
---|---|
VCC | 3V |
GND | GND |
D0 | 13 (SCK) |
D1 | 15 (MOSI) |
RES | 9 |
DC | 8 |
CS | 16 |