LoginSignup
2
2

More than 1 year has passed since last update.

micro:bit v2 の MicroPython で OLED を使う(ssd1306モジュールをSPI版に対応させる編)

Posted at

空いていたので、超小ネタでいきます。

micro:bit Advent Calendar 20218日目の記事で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

IMG_5584.JPG

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2