0.96インチのI2C接続OLED(128×64ドット)に表示するデモです。
Arduino環境では、Adafruit作成のものがあるようですが、micropythonだとデモが存在しないため、自作してみました。
表示する図形によって表示速度が遅かったり一瞬静止したりする理由は、SPI接続、MicroPython、またはコード上の問題なのか。
RP2040の性能限界ではないと思いますが、よく分かりません。
苦労した点は、random.sampleがないため、自作で関数定義したのと、あとは星のscroll部分を、再帰で処理したことです。
現状の力量はこの程度しかありませんが、コード上の問題点や改良点など教えて頂ければ励みになります。
よろしくお願いします。
追記:
同じコードをCircuitPythonで走らせてみましたが、描画はとても遅くて体感的には1/10程度。このあたりは、情報どおりでした。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import machine
import ssd1306
import time
import random
import math
import string
sda = machine.Pin(0)
scl = machine.Pin(1)
i2c = machine.I2C(0,sda=sda, scl=scl, freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
#中心
xc = 64
yc = 32
ycp = 36
yct = 42
#左上
x1 = 0
y1 = 0
#右上
x2 = 128
y2 = 0
#右下
x3 = 128
y3 = 64
#左下
x4 = 0
y4 = 64
#対角線の長さ
r = 142.3
r2 = 71
r3= 48
#pentagram、star用変数
a1 = 0- math.pi/10
a2 = 2*math.pi/5- math.pi/10
a3 = 4*math.pi/5- math.pi/10
a4 = 6*math.pi/5- math.pi/10
a5 = 8*math.pi/5- math.pi/10
ra2 = round(a2, 1)
ra3 = round(a3, 1)
ra4 = round(a4, 1)
ra5 = round(a5, 1)
s1x = math.cos(a1)
s1y = math.sin(a1)
s2x = math.cos(ra2)
s2y = math.sin(ra2)
s3x = math.cos(ra3)
s3y = math.sin(ra3)
s4x = math.cos(ra4)
s4y = math.sin(ra4)
s5x = math.cos(ra5)
s5y = math.sin(ra5)
LETTERS = string.ascii_letters
def draw_lines1():
for i in range(90, 27, -1):
xi = r*math.cos(math.radians(i))
yi = r*math.sin(math.radians(i))
rxi = round(xi, 1)
ryi = round(yi, 1)
x11 = x1 + rxi
y11 = y1 + ryi
oled.line(x1, y1, int(x11), int(y11), 1)
oled.show()
for j in range(0, 63, 1):
xj = r*math.cos(math.radians(j))
yj = r*math.sin(math.radians(j))
rxj = round(xj, 1)
ryj = round(yj, 1)
x12 = x1 + rxj
y12 = y1 + ryj
oled.line(x1, y1, int(x12), int(y12), 1)
oled.show()
oled.fill(0)
oled.show()
def draw_lines2():
for i in range(90, 153, 1):
xi = r*math.cos(math.radians(i))
yi = r*math.sin(math.radians(i))
rxi = round(xi, 1)
ryi = round(yi, 1)
x21 = x2 + rxi
y21 = y2 + ryi
oled.line(x2, y2, int(x21), int(y21), 1)
oled.show()
for j in range(180, 153, -1):
xj = r*math.cos(math.radians(j))
yj = r*math.sin(math.radians(j))
rxj = round(xj, 1)
ryj = round(yj, 1)
x22 = x2 + rxj
y22 = y2 + ryj
oled.line(x2, y2, int(x22), int(y22), 1)
oled.show()
oled.fill(0)
oled.show()
def draw_lines3():
for i in range(180, 207, 1):
xi = r*math.cos(math.radians(i))
yi = r*math.sin(math.radians(i))
rxi = round(xi, 1)
ryi = round(yi, 1)
x31 = x3 + rxi
y31 = y3 + ryi
oled.line(x3, y3, int(x31), int(y31), 1)
oled.show()
for j in range(270, 207, -1):
xj = r*math.cos(math.radians(j))
yj = r*math.sin(math.radians(j))
rxj = round(xj, 1)
ryj = round(yj, 1)
x32 = x3 + rxj
y32 = y3 + ryj
oled.line(x3, y3, int(x32), int(y32), 1)
oled.show()
oled.fill(0)
oled.show()
def draw_lines4():
for i in range(360, 333, -1):
xi = r*math.cos(math.radians(i))
yi = r*math.sin(math.radians(i))
rxi = round(xi, 1)
ryi = round(yi, 1)
x41 = x4 + rxi
y41 = y4 + ryi
oled.line(x4, y4, int(x41), int(y41), 1)
oled.show()
for j in range(270, 333, 1):
xj = r*math.cos(math.radians(j))
yj = r*math.sin(math.radians(j))
rxj = round(xj, 1)
ryj = round(yj, 1)
x42 = x4 + rxj
y42 = y4 + ryj
oled.line(x4, y4, int(x42), int(y42), 1)
oled.show()
oled.fill(0)
oled.show()
def draw_linesC():
for i in range(0, 90, 1):
xi1 = r2*math.cos(math.radians(i))
yi1 = r2*math.sin(math.radians(i))
xi2 = r2*math.cos(math.radians(i+90))
yi2 = r2*math.sin(math.radians(i+90))
xi3 = r2*math.cos(math.radians(i+180))
yi3 = r2*math.sin(math.radians(i+180))
xi4 = r2*math.cos(math.radians(i+270))
yi4 = r2*math.sin(math.radians(i+270))
rxi1 = round(xi1, 1)
ryi1 = round(yi1, 1)
rxi2 = round(xi2, 1)
ryi2 = round(yi2, 1)
rxi3 = round(xi3, 1)
ryi3 = round(yi3, 1)
rxi4 = round(xi4, 1)
ryi4 = round(yi4, 1)
xc1 = xc + rxi1
yc1 = yc + ryi1
xc2 = xc + rxi2
yc2 = yc + ryi2
xc3 = xc + rxi3
yc3 = yc + ryi3
xc4 = xc + rxi4
yc4 = yc + ryi4
oled.line(xc, yc, int(xc1), int(yc1), 1)
oled.line(xc, yc, int(xc2), int(yc2), 1)
oled.line(xc, yc, int(xc3), int(yc3), 1)
oled.line(xc, yc, int(xc4), int(yc4), 1)
oled.show()
def draw_rect():
for i in range(32):
oled.rect(0+i,0+i, 128-2*i, 64-2*i, 0)
oled.show()
def draw_rect2():
for i in range(0,31, 6):
for j in range(3):
oled.rect(i+j, i+j, 128-2*(i+j), 64-2*(i+j), 1)
oled.show()
time.sleep_ms(10)
oled.invert(1)
oled.show()
time.sleep_ms(10)
oled.invert(0)
oled.show()
time.sleep_ms(10)
oled.fill(0)
oled.show()
def draw_circle():
for k in range(0, 45, 3):
for j in range(1, 4):
for i in range(360):
xi = (k+j)*math.cos(math.radians(i))
yi = (k+j)*math.sin(math.radians(i))
rx = round(xi, 1)
ry = round(yi, 1)
x = xc + rx
y = yc + ry
oled.pixel(int(x), int(y), 1)
oled.show()
def draw_circle2():
for k in range(45, -4, -6):
for j in range(1, 4):
for i in range(360):
xi = (k+j)*math.cos(math.radians(i))
yi = (k+j)*math.sin(math.radians(i))
rx = round(xi, 1)
ry = round(yi, 1)
x = xc + rx
y = yc + ry
oled.pixel(int(x), int(y), 0)
oled.show()
time.sleep_ms(10)
oled.invert(1)
oled.show()
time.sleep_ms(10)
oled.invert(0)
oled.show()
time.sleep_ms(10)
oled.fill(0)
oled.show()
def draw_triangle():
for ri in range(0,37, 9):
for j in range(3):
x30 = (ri+j)*math.cos(math.radians(30))
y30 = (ri+j)*math.sin(math.radians(30))
x150 = (ri+j)*math.cos(math.radians(150))
y150 = (ri+j)*math.sin(math.radians(150))
x270 = (ri+j)*math.cos(math.radians(270))
y270 = (ri+j)*math.sin(math.radians(270))
rx30 = int(x30)
ry30 = int(y30)
rx150 = int(x150)
ry150 = int(y150)
rx270 = int(x270)
ry270 = int(y270)
oled.line(xc+rx30, yct+ry30, xc+rx150, yct+ry150, 1)
oled.line(xc+rx150, yct+ry150, xc+rx270, yct+ry270, 1)
oled.line(xc+rx270, yct+ry270, xc+rx30, yct+ry30, 1)
oled.invert(1)
oled.show()
time.sleep_ms(50)
oled.invert(0)
oled.show()
time.sleep_ms(50)
oled.fill(0)
oled.show()
def draw_pentagram():
for i in range(0, 37, 6):
for j in range(3):
oled.line(xc+int(s1x*(i+j)), ycp+int(s1y*(i+j)), xc+int(s2x*(i+j)), ycp+int(s2y*(i+j)), 1)
oled.line(xc+int(s2x*(i+j)), ycp+int(s2y*(i+j)), xc+int(s3x*(i+j)), ycp+int(s3y*(i+j)), 1)
oled.line(xc+int(s3x*(i+j)), ycp+int(s3y*(i+j)), xc+int(s4x*(i+j)), ycp+int(s4y*(i+j)), 1)
oled.line(xc+int(s4x*(i+j)), ycp+int(s4y*(i+j)), xc+int(s5x*(i+j)), ycp+int(s5y*(i+j)), 1)
oled.line(xc+int(s5x*(i+j)), ycp+int(s5y*(i+j)), xc+int(s1x*(i+j)), ycp+int(s1y*(i+j)), 1)
oled.invert(1)
oled.show()
time.sleep_ms(50)
oled.invert(0)
oled.show()
time.sleep_ms(50)
oled.fill(0)
oled.show()
##星demo
xx_lst = [i for i in range(10, 130, 10)]
yy_lst = [i for i in range(5, 10)]
def draw_star():
for i in range(0, 37, 12):
for j in range(3):
oled.line(xc+int(s1x*(i+j)), ycp+int(s1y*(i+j)), xc+int(s3x*(i+j)), ycp+int(s3y*(i+j)), 1)
oled.line(xc+int(s3x*(i+j)), ycp+int(s3y*(i+j)), xc+int(s5x*(i+j)), ycp+int(s5y*(i+j)), 1)
oled.line(xc+int(s5x*(i+j)), ycp+int(s5y*(i+j)), xc+int(s2x*(i+j)), ycp+int(s2y*(i+j)), 1)
oled.line(xc+int(s2x*(i+j)), ycp+int(s2y*(i+j)), xc+int(s4x*(i+j)), ycp+int(s4y*(i+j)), 1)
oled.line(xc+int(s4x*(i+j)), ycp+int(s4y*(i+j)), xc+int(s1x*(i+j)), ycp+int(s1y*(i+j)), 1)
oled.invert(1)
oled.show()
time.sleep_ms(50)
oled.invert(0)
oled.show()
time.sleep_ms(50)
oled.fill(0)
oled.show()
def draw_mstars(xi, yi):
for j in range(0, 10, 1):
oled.line(xi+int(s1x*j), yi+int(s1y*j), xi+int(s3x*j), yi+int(s3y*j), 1)
oled.line(xi+int(s3x*j), yi+int(s3y*j), xi+int(s5x*j), yi+int(s5y*j), 1)
oled.line(xi+int(s5x*j), yi+int(s5y*j), xi+int(s2x*j), yi+int(s2y*j), 1)
oled.line(xi+int(s2x*j), yi+int(s2y*j), xi+int(s4x*j), yi+int(s4y*j), 1)
oled.line(xi+int(s4x*j), yi+int(s4y*j), xi+int(s1x*j), yi+int(s1y*j), 1)
oled.show()
def make_star5():
n = random.choice([j for j in range(1,6)])
for i in range(n):
xx = random.choice(xx_lst)
yy = random.choice(yy_lst)
draw_mstars(xx, yy)
oled.show()
def fall_stars():
make_star5()
for i in range(18):
oled.scroll(0, 1)
oled.show()
time.sleep_ms(10)
oled.fill_rect(0,0, 128, i, 0)
oled.show()
##テキストdemo
def get_random_string(num):
rcletters_lst = []
for i in range(num):
rc = random.choice(LETTERS)
rcletters_lst.append(rc)
random_string = ''.join(rcletters_lst)
return random_string
#ディスプレイに表示するランダム文字列
str_0 = get_random_string(16)
str_1 = get_random_string(16)
str_2 = get_random_string(16)
str_3 = get_random_string(16)
str_4 = get_random_string(16)
str_5 = get_random_string(16)
#Lt16は、0-15の数字順リスト。ここからダブりなく数字を取り出す。文字列の位置指定となる。
Lt16_0 = [i for i in range(16)]
Lt16_1 = [i for i in range(16)]
Lt16_2 = [i for i in range(16)]
Lt16_3 = [i for i in range(16)]
Lt16_4 = [i for i in range(16)]
Lt16_5 = [i for i in range(16)]
ln0, ln1, ln2, ln3, ln4, ln5 = 16, 16, 16, 16, 16, 16
def text_display():
for i in range(16):
oled.text(str_0[i], 8*i, 0)
oled.text(str_1[i], 8*i, 10)
oled.text(str_2[i], 8*i, 20)
oled.text(str_3[i], 8*i, 30)
oled.text(str_4[i], 8*i, 40)
oled.text(str_5[i], 8*i, 50)
oled.show()
time.sleep_ms(50)
def text_eraseall():
global str_0, str_1, str_2, str_3, str_4, str_5
global Lt16_0, Lt16_1, Lt16_2, Lt16_3, Lt16_4, Lt16_5
global ln0, ln1, ln2, ln3, ln4, ln5
#取り出した数字を要素の番号にして、文字列からその部分を空白にする
for j in range(16):
oled.fill(0)
#rrが、Lt16の位置をランダムで指定
rr0 = random.randint(0, ln0-1)
rr1 = random.randint(0, ln1-1)
rr2 = random.randint(0, ln2-1)
rr3 = random.randint(0, ln3-1)
rr4 = random.randint(0, ln4-1)
rr5 = random.randint(0, ln5-1)
#numは、Lt16のrrに位置する数字
num0 = Lt16_0[rr0]
num1 = Lt16_1[rr1]
num2 = Lt16_2[rr2]
num3 = Lt16_3[rr3]
num4 = Lt16_4[rr4]
num5 = Lt16_5[rr5]
#Lt16からnumが削除される
Lt16_0.remove(num0)
Lt16_1.remove(num1)
Lt16_2.remove(num2)
Lt16_3.remove(num3)
Lt16_4.remove(num4)
Lt16_5.remove(num5)
ln0 = len(Lt16_0)
ln1 = len(Lt16_1)
ln2 = len(Lt16_2)
ln3 = len(Lt16_3)
ln4 = len(Lt16_4)
ln5 = len(Lt16_5)
#ランダム文字列においてnumに位置する文字を空白にして、穴あきの文字列を作って上書き
str_0 = str_0[:num0]+str(" ")+str_0[num0+1:]
str_1 = str_1[:num1]+str(" ")+str_1[num1+1:]
str_2 = str_2[:num2]+str(" ")+str_2[num2+1:]
str_3 = str_3[:num3]+str(" ")+str_3[num3+1:]
str_4 = str_4[:num4]+str(" ")+str_4[num4+1:]
str_5 = str_5[:num5]+str(" ")+str_5[num5+1:]
#再描画する
oled.text(str_0, 0, 0, 1)
oled.text(str_1, 0, 10, 1)
oled.text(str_2, 0, 20, 1)
oled.text(str_3, 0, 30, 1)
oled.text(str_4, 0, 40, 1)
oled.text(str_5, 0, 50, 1)
oled.show()
time.sleep_ms(300)
if __name__ == '__main__':
draw_lines1()
draw_lines2()
draw_lines3()
draw_lines4()
draw_linesC()
draw_rect()
draw_rect2()
draw_circle()
draw_circle2()
draw_triangle()
draw_pentagram()
draw_star()
text_display()
text_eraseall()
while True:
fall_stars()