基于esp32通过micropython控制ws2812实现像素时钟(初版)

一、前言

基于esp32和ws2812的彩色像素时钟,目前网上有许多类似作品,但大多使用的为esp32原生的编程语言,鉴于Python的简洁易懂,我打算使用本文记录一次使用micropython编程的像素时钟过程。


micropython

首先确保你的esp32已经刷了micropython,如果你还没有,请查阅其他相关资料教程,这里不再赘述,我使用的编程软件是thonny,可以很方便的对esp32进行程序调试

thonny官网:Thonny, Python IDE for beginners

如果你无法打开github,可以使用镜像站下载(该链接为我写文章时thonny最新版本,如果thonny有更新的版本,可以将下载链接的“github.com”替换为“hub.nuaa.cf”)https://hub.nuaa.cf/thonny/thonny/releases/download/v4.1.4/thonny-4.1.4.exe

二、硬件连接

1.ws2812

接线如下图(此处散热片是我之前做别的东西时装的,已经拆不下来了):

2.DS1302

接线如下图:

3.ESP32


三、编程

1.初始化数据

首先是需要初始化的一些东西

from machine import Pin
from ds1302 import DS1302
from machine import RTC
import machine, neopixel, time, network, ntptime
wlan = network.WLAN(network.STA_IF)
n = 32*8
p = 13
printtime = [10,10,10,10,10,10]
ds  = DS1302(clk = Pin(25), dio = Pin(26), cs = Pin(27))
np = neopixel.NeoPixel(machine.Pin(p), n)

2.ds1302模块驱动

从网上找到了ds1302的驱动程序

保存为ds1302.py

from machine import Pin
 
DS1302_REG_SECOND = (0x80)
DS1302_REG_MINUTE = (0x82)
DS1302_REG_HOUR   = (0x84)
DS1302_REG_DAY    = (0x86)
DS1302_REG_MONTH  = (0x88)
DS1302_REG_WEEKDAY= (0x8A)
DS1302_REG_YEAR   = (0x8C)
DS1302_REG_WP     = (0x8E)
DS1302_REG_CTRL   = (0x90)
DS1302_REG_RAM    = (0xC0)
 
class DS1302:
    def __init__(self, clk, dio, cs):
        self.clk = clk
        self.dio = dio
        self.cs = cs
        self.clk.init(Pin.OUT)
        self.cs.init(Pin.OUT)
 
    def _dec2hex(self, dat):
        return (dat//10) * 16 + (dat % 10)
 
    def _hex2dec(self, dat):
        return (dat//16) * 10 + (dat % 16)
 
    def _write_byte(self, dat):
        self.dio.init(Pin.OUT)
        for i in range(8):
            self.dio.value((dat >> i) & 1)
            self.clk.value(1)
            self.clk.value(0)
 
    def _read_byte(self):
        d = 0
        self.dio.init(Pin.IN)
        for i in range(8):
            d = d | (self.dio.value() << i)
            self.clk.value(1)
            self.clk.value(0)
        return d
 
    def _get_reg(self, reg):
        self.cs.value(1)
        self._write_byte(reg)
        t = self._read_byte()
        self.cs.value(0)
        return t
 
    def _set_reg(self, reg, dat):
        self.cs.value(1)
        self._write_byte(reg)
        self._write_byte(dat)
        self.cs.value(0)
 
    def _wr(self, reg, dat):
        self._set_reg(DS1302_REG_WP, 0)
        self._set_reg(reg, dat)
        self._set_reg(DS1302_REG_WP, 0x80)
    #开启
    def start(self):
        t = self._get_reg(DS1302_REG_SECOND + 1)
        self._wr(DS1302_REG_SECOND, t & 0x7f)
    #关闭
    def stop(self):
        t = self._get_reg(DS1302_REG_SECOND + 1)
        self._wr(DS1302_REG_SECOND, t | 0x80)
    #秒
    def second(self, second=None):
        if second == None:
            return self._hex2dec(self._get_reg(DS1302_REG_SECOND+1)) % 60
        else:
            self._wr(DS1302_REG_SECOND, self._dec2hex(second % 60))
    #分
    def minute(self, minute=None):
        if minute == None:
            return self._hex2dec(self._get_reg(DS1302_REG_MINUTE+1))
        else:
            self._wr(DS1302_REG_MINUTE, self._dec2hex(minute % 60))
    #时
    def hour(self, hour=None):
        if hour == None:
            return self._hex2dec(self._get_reg(DS1302_REG_HOUR+1))
        else:
            self._wr(DS1302_REG_HOUR, self._dec2hex(hour % 24))
    #工作日
    def weekday(self, weekday=None):
        if weekday == None:
            return self._hex2dec(self._get_reg(DS1302_REG_WEEKDAY+1))
        else:
            self._wr(DS1302_REG_WEEKDAY, self._dec2hex(weekday % 8))
    #天
    def day(self, day=None):
        if day == None:
            return self._hex2dec(self._get_reg(DS1302_REG_DAY+1))
        else:
            self._wr(DS1302_REG_DAY, self._dec2hex(day % 32))
    #月
    def month(self, month=None):
        if month == None:
            return self._hex2dec(self._get_reg(DS1302_REG_MONTH+1))
        else:
            self._wr(DS1302_REG_MONTH, self._dec2hex(month % 13))
    #年
    def year(self, year=None):
        if year == None:
            return self._hex2dec(self._get_reg(DS1302_REG_YEAR+1)) + 2000
        else:
            self._wr(DS1302_REG_YEAR, self._dec2hex(year % 100))
            
    #获取或设置时间
    def date_time(self, dat=None):
        if dat == None:
            return [self.year(), self.month(), self.day(), self.weekday(), self.hour(), self.minute(), self.second()]
        else:
            self.year(dat[0])
            self.month(dat[1])
            self.day(dat[2])
            self.weekday(dat[3])
            self.hour(dat[4])
            self.minute(dat[5])
            self.second(dat[6])
            
    #返回设置结果
    def ram(self, reg, dat=None):
        if dat == None:
            return self._get_reg(DS1302_REG_RAM + 1 + (reg % 31)*2)
        else:
            self._wr(DS1302_REG_RAM + (reg % 31)*2, dat)

3.ws2812

对于ws2812,micropython有内置的库neopixel,因此我们不需要额外添加驱动

4.坐标转换

neopixel需要灯的序号来给ws2812发送数据,对于点阵屏来说是及其不方便的,因此这里我写了一个函数用于通过坐标点亮指定的灯

def set_pixel(x,y,color):
    if x<0 or x>=32 or y<0 or y>=8:
        raise ValueError("x,y are out of range")
    index = x*8+y
    np[index] = color
    #np.write()

不难看出,我以点阵屏右上角为坐标原点,向下为y轴正方向,向左为x轴正方向建的坐标系。对于为何将np.write()注释掉,稍候我会解释

5.数字显示

这里我写了一个函数,输入指定的数字和坐标(数字为3*5,坐标定位数字右上角)即可显示数字在对应位置

def get_xy(i):
    if i>7 or i<1:
        raise ValueError("i is out of range")
    if i==1:
        return [(2,0),(2,1),(2,2)]
    elif i==2:
        return [(2,2),(2,3),(2,4)]
    elif i==3:
        return [(2,0),(1,0),(0,0)]
    elif i==4:
        return [(2,2),(1,2),(0,2)]
    elif i==5:
        return [(2,4),(1,4),(0,4)]
    elif i==6:
        return [(0,0),(0,1),(0,2)]
    elif i==7:
        return [(0,2),(0,3),(0,4)]

^为了减少代码量,先将“8”字(类似数码管)每个笔画都写在一个函数里 

def set_figure(f,x,y,color):
    ze = get_xy(3)+get_xy(1)+get_xy(2)+get_xy(5)+get_xy(6)+get_xy(7)
    on = [(1,0), (1,1), (2,1), (1,2), (1,3), (1,4),(2,4),(0,4)]
    tw = get_xy(3)+get_xy(6)+get_xy(4)+get_xy(2)+get_xy(5)
    th = get_xy(3)+get_xy(6)+get_xy(4)+get_xy(7)+get_xy(5)
    fo = get_xy(1)+get_xy(4)+get_xy(6)+get_xy(7)
    fi = get_xy(3)+get_xy(1)+get_xy(4)+get_xy(7)+get_xy(5)
    si = get_xy(3)+get_xy(1)+get_xy(4)+get_xy(2)+get_xy(7)+get_xy(5)
    se = get_xy(3)+get_xy(6)+get_xy(7)
    ei = get_xy(3)+get_xy(1)+get_xy(2)+get_xy(4)+get_xy(5)+get_xy(6)+get_xy(7)
    ni = get_xy(3)+get_xy(1)+get_xy(6)+get_xy(4)+get_xy(7)+get_xy(5)
    for i in ei :
        set_pixel(i[0]+x,i[1]+y,(0,0,0))
    for i in on :
        set_pixel(i[0]+x,i[1]+y,(0,0,0))
    if f==0:
        for i in ze :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==1:
        for i in on :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==2:
        for i in tw :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==3:
        for i in th :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==4:
        for i in fo :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==5:
        for i in fi :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==6:
        for i in si :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==7:
        for i in se :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==8:
        for i in ei :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==9:
        for i in ni :
            set_pixel(i[0]+x,i[1]+y,color)

这里由于切换数字要先清除之前的数字,因此先写入“8”的数字颜色为(0,0,0)和1的颜色为(0,0,0)(由于数字“1”与其他数字不一样,因此只用“8”来清空不够(看成果就知道了))

6.时间显示

下面进行时间的显示

def print_time(x,y,color):
    global printtime
    thetime = rtc.datetime()[4:7]
    set_figure(thetime[0]//10,x-3,y,color)
    set_figure(thetime[0]-10*(thetime[0]//10),x-7,y,color)
    set_figure(thetime[1]//10,x-13,y,color)
    set_figure(thetime[1]-10*(thetime[1]//10),x-17,y,color)
    set_figure(thetime[2]//10,x-23,y,color)
    set_figure(thetime[2]-10*(thetime[2]//10),x-27,y,color)
    #left :
    set_pixel(19,2,color)
    set_pixel(19,4,color)
    #right :
    set_pixel(9,2,color)
    set_pixel(9,4,color)
    np.write()

7.时间校准

到这里,已经可以显示基本的时间信息了,但我们需要校准时间并使时间在断电后依旧可以走时

所以这里我写了一个函数,先检查网络连接,若有网则使用网络校准时间并校准ds1302,没有网则使用ds1302校准时间

这里我已经在boot.py内配置好了WIFI如果你还没有配置,添加下面的语句到boot.py

SSID = '(你的WIFI名称)'
PASSWORD = '(你的WIFI密码)'
def connect_wifi(ssid, password, timeout=10):
    start = time.time()
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect(ssid, password)
        while not wlan.isconnected():
            if time.time() - start > timeout:
                return False
            pass
    print('network config:', wlan.ifconfig())
    return True
if not connect_wifi(SSID, PASSWORD):
    print('Failed to connect WiFi')

校准时间函数:(小时+8是因为ntp服务器默认的时间为UTC0)

def set_time():
    if wlan.isconnected():
        try:
            ntptime.host = 'ntp1.aliyun.com'
            ntptime.settime()
            rtc.datetime(rtc.datetime()[0:4]+(int(rtc.datetime()[4])+8,)+rtc.datetime()[5:8])
            ds.date_time(rtc.datetime()[0:7])
        except:
            rtc.datetime(ds.date_time()+[0])
    else:
        rtc.datetime(ds.date_time()+[0])

8.测试时间显示

此时,基本的时间显示已经可以运行了,是时候测试一下了(注意,颜色不要调的过亮,否则可能会发热严重)

该程序会每隔5h校准一次时间

set_time()
while(True):
    if t%180000 == 0:
        set_time()
        t = 0
    print_time(28,1,(20,20,20))
    time.sleep(0.1)
    t += 1

但是,好景不长,我发现每循环一次时,就会闪烁一下,非常不好看(此时我还没有注释掉坐标转换函数内的np.write()语句

我反复思考,怎么让它不会闪烁呢,显然,闪烁是因为每次更新数字时,都要擦掉原来的数字再重新显示,因此我想了老长时间,想出一个麻烦但貌似可行的办法,每次更新时,不擦全部数字,而是擦掉与原来数字不一样的部分,为此,我改动了时间显示函数,将数字显示里的先擦除所有数字语句删掉,然后添加了一个用于擦除不一样的像素的函数

改动的时间显示函数:

def print_time(x,y,color):
    global printtime
    thetime = rtc.datetime()[4:7]
    #print(thetime[4]," ",thetime[5]," ",thetime[6])
    #print(thetime[4]//10,thetime[4]-thetime[4]//10,thetime[5]//10,thetime[5]-thetime[4]//10,thetime[6]//10,thetime[6]-thetime[4]//10)
    if printtime[0] != thetime[0]//10:
        printtime[0] = thetime[0]//10
        smooth_clear(printtime[0],x-3,y) #clear
        set_figure(printtime[0],x-3,y,color)
    if printtime[1] != thetime[0]-10*(thetime[0]//10):
        printtime[1] = thetime[0]-10*(thetime[0]//10)
        smooth_clear(printtime[1],x-7,y)
        set_figure(printtime[1],x-7,y,color)
        
    if printtime[2] != thetime[1]//10:
        printtime[2] = thetime[1]//10
        smooth_clear(printtime[2],x-13,y) #clear
        set_figure(printtime[2],x-13,y,color)
    if printtime[3] != thetime[1]-10*(thetime[1]//10):
        printtime[3] = thetime[1]-10*(thetime[1]//10)
        smooth_clear(printtime[3],x-17,y)#clear
        set_figure(printtime[3],x-17,y,color)
        
    if printtime[4] != thetime[2]//10:
        printtime[4] = thetime[2]//10
        smooth_clear(printtime[4],x-23,y) #clear
        set_figure(printtime[4],x-23,y,color)
    if printtime[5] != thetime[2]-10*(thetime[2]//10):
        printtime[5] = thetime[2]-10*(thetime[2]//10)
        smooth_clear(printtime[5],x-27,y)
        set_figure(printtime[5],x-27,y,color)
    #set_figure(thetime[0]//10,x-3,y,color)
    #set_figure(thetime[0]-10*(thetime[0]//10),x-7,y,color)
    #set_figure(thetime[1]//10,x-13,y,color)
    #set_figure(thetime[1]-10*(thetime[1]//10),x-17,y,color)
    #set_figure(thetime[2]//10,x-23,y,color)
    #set_figure(thetime[2]-10*(thetime[2]//10),x-27,y,color)

添加的擦除函数:

def smooth_clear(later,x,y):
    if later==0:
        cl = [(1,2)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()
    elif later==1:
        cl = [(2,0), (0,0), (0,1), (0,2), (0,3), (2,3), (2,2)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()
    elif later==2:
        cl = [(2,1), (1,1), (1,3)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()
    elif later==3:
        cl = [(2,3)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()
    elif later==4:
        cl = [(1,0),(2,4), (1,4)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()
    elif later==5:
        cl = [(0,1)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()
    elif later==6:
        pass
    elif later==7:
        cl = [(1,2), (2,1), (2,2), (2,3), (2,4), (1,4)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()
    elif later==8:
        pass
    elif later==9:
        cl = [(2,3)]
        for i in cl :
            set_pixel(i[0]+x,i[1]+y,(0,0,0))
        np.write()

是不是非常麻烦,等我写完静下来想了一会之后,突然发现这些根本没必要,因为neopixel是先设置颜色信息,再用np.write()来发送数据,所以我只需要将擦除数字和设置数字全部放在np.write()前就可以了,于是我删除了这一大堆代码,复原函数之后注释掉了坐标转换函数中的np.write()(白忙活了老长时间)

9.日期显示和颜色渐变

丰富一下时钟,我又添加了日期显示功能,不过是通过像素形状和数目来实现的

实现函数:

def print_day():
    day = rtc.datetime()[1:4]
    for i in range(day[1]):
        set_pixel(31-i//8,i-(i//8)*8,get_color(2))
    #clear week
    for i in range(2):
        set_pixel(26-i,6,get_color(3))
    for i in range(2):
        set_pixel(22-i,6,get_color(3))
    for i in range(2):
        set_pixel(18-i,6,get_color(3))
    for i in range(2):
        set_pixel(14-i,6,get_color(3))
    for i in range(2):
        set_pixel(10-i,6,get_color(3))
    for i in range(2):
        set_pixel(6-i,6,get_color(3))
    for i in range(2):
        set_pixel(2-i,6,get_color(3))
    #set week
    for i in range(2):
        set_pixel(26-i-day[2]*4,6,(20,0,0))
    #clear month
    for i in range(12):
        set_pixel(20-i,7,get_color(4))
    #set month
    set_pixel(21-day[0],7,(15,13,13))
    np.write()

 这里的get_color()函数是我写的渐变色函数,它会随着日期或者时间逐渐变化颜色(如正午是偏红色,深夜是深蓝色)

def get_color(mod):
    day = rtc.datetime()[1:4]
    thetime = rtc.datetime()[4:7]
    now = thetime[0]*60+thetime[1]
    if mod==1:#realtime
        if now>720:
            i = now-720
            return (30-int(30*(i/720)),int(10-8*(i/720)),int(15*(i/720)))
        else:
            i = 720-now
            return (30-int(30*(i/720)),int(10-8*(i/720)),int(15*(i/720)))
    elif mod==2:#mday
        return (10,2,10)
    elif mod==3:#week
        return (day[2]*2,12-day[2]*2,0)
    elif mod==4:#month
        return (0,day[0],12-day[0])

10.最终程序

from machine import Pin
from ds1302 import DS1302
from machine import RTC
import machine, neopixel, time, random, _thread, network, ntptime
wlan = network.WLAN(network.STA_IF)
n = 32*8
p = 13
printtime = [10,10,10,10,10,10]
ds  = DS1302(clk = Pin(25), dio = Pin(26), cs = Pin(27))
np = neopixel.NeoPixel(machine.Pin(p), n)
rtc = RTC()
def set_pixel(x,y,color):
    if x<0 or x>=32 or y<0 or y>=8:
        raise ValueError("x,y are out of range")
    index = x*8+y
    np[index] = color
    #np.write()
def set_figure(f,x,y,color):
    ze = get_xy(3)+get_xy(1)+get_xy(2)+get_xy(5)+get_xy(6)+get_xy(7)
    on = [(1,0), (1,1), (2,1), (1,2), (1,3), (1,4),(2,4),(0,4)]
    tw = get_xy(3)+get_xy(6)+get_xy(4)+get_xy(2)+get_xy(5)
    th = get_xy(3)+get_xy(6)+get_xy(4)+get_xy(7)+get_xy(5)
    fo = get_xy(1)+get_xy(4)+get_xy(6)+get_xy(7)
    fi = get_xy(3)+get_xy(1)+get_xy(4)+get_xy(7)+get_xy(5)
    si = get_xy(3)+get_xy(1)+get_xy(4)+get_xy(2)+get_xy(7)+get_xy(5)
    se = get_xy(3)+get_xy(6)+get_xy(7)
    ei = get_xy(3)+get_xy(1)+get_xy(2)+get_xy(4)+get_xy(5)+get_xy(6)+get_xy(7)
    ni = get_xy(3)+get_xy(1)+get_xy(6)+get_xy(4)+get_xy(7)+get_xy(5)
    for i in ei :
        set_pixel(i[0]+x,i[1]+y,(0,0,0))
    for i in on :
        set_pixel(i[0]+x,i[1]+y,(0,0,0))
    if f==0:
        for i in ze :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==1:
        for i in on :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==2:
        for i in tw :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==3:
        for i in th :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==4:
        for i in fo :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==5:
        for i in fi :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==6:
        for i in si :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==7:
        for i in se :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==8:
        for i in ei :
            set_pixel(i[0]+x,i[1]+y,color)
    elif f==9:
        for i in ni :
            set_pixel(i[0]+x,i[1]+y,color)
def get_xy(i):
    if i>7 or i<1:
        raise ValueError("i is out of range")
    if i==1:
        return [(2,0),(2,1),(2,2)]
    elif i==2:
        return [(2,2),(2,3),(2,4)]
    elif i==3:
        return [(2,0),(1,0),(0,0)]
    elif i==4:
        return [(2,2),(1,2),(0,2)]
    elif i==5:
        return [(2,4),(1,4),(0,4)]
    elif i==6:
        return [(0,0),(0,1),(0,2)]
    elif i==7:
        return [(0,2),(0,3),(0,4)]
def set_time():
    if wlan.isconnected():
        try:
            ntptime.host = 'ntp1.aliyun.com'
            ntptime.settime()
            rtc.datetime(rtc.datetime()[0:4]+(int(rtc.datetime()[4])+8,)+rtc.datetime()[5:8])
            ds.date_time(rtc.datetime()[0:7])
        except:
            rtc.datetime(ds.date_time()+[0])
    else:
        rtc.datetime(ds.date_time()+[0])

def print_time(x,y,color):
    global printtime
    thetime = rtc.datetime()[4:7]
    set_figure(thetime[0]//10,x-3,y,color)
    set_figure(thetime[0]-10*(thetime[0]//10),x-7,y,color)
    set_figure(thetime[1]//10,x-13,y,color)
    set_figure(thetime[1]-10*(thetime[1]//10),x-17,y,color)
    set_figure(thetime[2]//10,x-23,y,color)
    set_figure(thetime[2]-10*(thetime[2]//10),x-27,y,color)
    #left :
    set_pixel(19,2,color)
    set_pixel(19,4,color)
    #right :
    set_pixel(9,2,color)
    set_pixel(9,4,color)
    np.write()
def get_color(mod):
    day = rtc.datetime()[1:4]
    thetime = rtc.datetime()[4:7]
    now = thetime[0]*60+thetime[1]
    if mod==1:#realtime
        if now>720:
            i = now-720
            return (30-int(30*(i/720)),int(10-8*(i/720)),int(15*(i/720)))
        else:
            i = 720-now
            return (30-int(30*(i/720)),int(10-8*(i/720)),int(15*(i/720)))
    elif mod==2:#mday
        return (10,2,10)
    elif mod==3:#week
        return (day[2]*2,12-day[2]*2,0)
    elif mod==4:#month
        return (0,day[0],12-day[0])
def print_day():
    day = rtc.datetime()[1:4]
    for i in range(day[1]):
        set_pixel(31-i//8,i-(i//8)*8,get_color(2))
    #clear week
    for i in range(2):
        set_pixel(26-i,6,get_color(3))
    for i in range(2):
        set_pixel(22-i,6,get_color(3))
    for i in range(2):
        set_pixel(18-i,6,get_color(3))
    for i in range(2):
        set_pixel(14-i,6,get_color(3))
    for i in range(2):
        set_pixel(10-i,6,get_color(3))
    for i in range(2):
        set_pixel(6-i,6,get_color(3))
    for i in range(2):
        set_pixel(2-i,6,get_color(3))
    #set week
    for i in range(2):
        set_pixel(26-i-day[2]*4,6,(20,0,0))
    #clear month
    for i in range(12):
        set_pixel(20-i,7,get_color(4))
    #set month
    set_pixel(21-day[0],7,(15,13,13))
    np.write()
set_time()
t=0
while(True):
    if t%180000 == 0:
        set_time()
        t = 0
    print_time(28,1,get_color(1))
    print_day()
    time.sleep(0.1)
    t += 1

四、效果与后记

效果图

我觉得贴上一层纸会更好(因为没粘上所以有的地方纸翘起来导致有点糊)

后记

由于学业原因,暂时只做了这个简陋的像素时钟初版,还有许多想加的功能没有添加 ,如翻页显示功能,温湿度显示功能等等,等学业不紧张后,后面的版本会一一尝试实现。

感谢你的阅读