1.项目需求
- 制作一个时钟,可以通过板上的12个彩色LED灯来指示时间
- 通过蜂鸣器在整点以播放音乐的方式报时
- 板上的按键可以设置时间
实现方式:程序通过定时器计数的方式来生成时、分、秒信号,并根据这些信号来改变12个彩色LED灯的亮灭,产生PWM信号驱动蜂鸣器播放定时长度的音乐。
2.设计思路
我所设计的是有闹钟效果的时钟
- 在显示屏上显示现在的年,月,日,并附带一张动图
- 用12个WS2812B RGB三色灯 实现时钟的效果
- 用k1,k2两个按键输入时间并在显示屏上显示
- 当时间到达设置的时间时蜂鸣器会放一首歌曲,起到闹钟的作用
3.硬件介绍
3.1板卡介绍
- 2个按键输入
- 4个单色LED
- 12个WS2812B RGB三色灯
- 1个姿态传感器
- 1个128*64 OLED显示屏
- 1个蜂鸣器
- 1个可调电位计(用于电压表)
- 1路音频信号输入(用于示波器)
- 8位R-2R电阻网络构成的DAC(用于DDS信号发生器)
我所用到是其中的两个按键,12个WS2812B RGB三色灯,128*64 OLED显示屏和蜂鸣器。RGB灯来表示时钟,显示屏显示时间,蜂鸣器起到报警的作用。
3.2学习板的功能、性能要求
-
能够体验输入、输出的外设,尤其是典型总线的连接
-
能够构建多种有趣、有技术含量的项目
-
声音的输入和输出
-
主要显示器件的使用 - LED、OLED、WS2812
-
能够使用到PIO功能并体现其优势的外设
4.实现过程
4.1流程图
4.2在显示屏上显示现在的年,月,日,并附带一张动图
class OledTime():
def __init__(self, oled, frames):
self.oled = oled
self.frames = frames
self.oled.fill(0)
self.i = len(frames) - 1
self.wri = Writer(oled, freesans20)
def show_date(self, year, month, day, set_time):
self.y = year
self.m = month
self.d = day
self.set_time = set_time
def draw(self):
if self.i == 0:
self.i = len(frames) - 1
else:
self.i = self.i - 1
fb = framebuf.FrameBuffer(self.frames[self.i], 64, 64, framebuf.MONO_HLSB)
self.oled.blit(fb, 0, 0, 0)
self.wri.set_textpos(oled, 10, 70)
self.wri.printstring(str(self.y))
self.wri.set_textpos(oled, 30, 75)
self.wri.printstring(str(self.m))
self.wri.set_textpos(oled, 30, 90)
self.wri.printstring(str(self.d))
self.wri.set_textpos(oled, 30, 10)
self.wri.printstring(str(self.set_time))
使得显示屏显示北京时间,还有宇航员的动态动画。
设置年,月,日,还有宇航员动态动画在屏幕上的展示位置,还有后续输入时间在显示屏上呈现出来的位置信息。
4.3用12个WS2812B RGB三色灯 实现时钟的效果
class Ws2812Time():
def __init__(self, pd):
self.pd = pd
self.h = 0
self.m = 0
self.s = 0
def show_time(self, h, m, s):
h_tmp = h
m_tmp = m
s_tmp = s
self.h = (h_tmp - 1) % 12 + 1
self.m = (int(m_tmp / 5) - 1) % 12 + 1
self.s = (int(s_tmp / 5) - 1) % 12 + 1
def draw(self):
pd.set_color(self.h, (0xff, 0, 0))
pd.set_color(self.m, (0, 0xff, 0))
pd.set_color(self.s, (0xff, 0xff, 0))
因为只有十二个灯,所以我们计算事件的时候要以12取余的方式,例如,时间为一点,那么输出就是在第一号RGB灯。小时用红灯表示、分钟用绿灯表示、秒是以黄色灯光(RGB三原色,红色跟绿色混合就得到了黄色)表示。
4.4用k1,k2两个按键输入时间并在显示屏上显示
while True:
set_time = set_time_old
if k1.value():
set_time = (set_time + 1) % 24
print('k1')
print(set_time)
if k2.value():
set_time = (set_time - 1) % 24
print(set_time)
set_time_old = set_time
输入的数字是从0到23。k1按钮可以使数字增加,k2可以使数字减小。最后定格的数字就是表示闹钟的时间。当时间到达设置时间后会自动响起。
4.5当时间到达设置的时间时蜂鸣器会放一首歌曲,起到闹钟的作用
if h == set_time_old and m == 0:
singer.tick()
if s == 10 :
singer.stop()
set_time_old = set_time
当时间到达设置时间后,会响起10秒的音乐,起到闹钟的作用。
5.实现的功能
5.1在显示屏上显示现在的年,月,日,并附带一张宇航员的动图
当连接到本地电脑时,会自动提取本地电脑显示的时间。
附带的动图就是图片上显示的宇航员的图片。
5.2用12个WS2812B RGB三色灯 实现时钟的效果
5.3用k1,k2两个按键输入时间并在显示屏上显示
5.4当时间到达设置的时间时蜂鸣器会放一首歌曲,起到闹钟的作用
闹钟的展示可以移步视频观看,谢谢。
6.遇到的难题
6.1 12个WS2812B RGB三色灯的显示问题
项目要求我们用三钟颜色来实分别表示时,分,秒。但是我发现,我的树莓派板卡上的9号,10号,11号RGB灯的蓝色显示不出来。
我就从代码入手,当(R,G,B)为(0,255,255)时按三原色混合原理,会出现青色。但是显示的是绿色。当(R,G,B)为(255,0,255)时,应出现紫色,但是显示的还是红色。所以,最后得到这三个灯的蓝灯是坏的。所以只能用三原色混合的原理,绿色加红色显示出了黄色。
6.2 按钮个数问题
因板卡的按钮只有两个,所以很难精确的表示时间。我就换了思路,设计完成了整点报时的时钟。k1按钮可以使得数字增加,k2按钮可以使得数字减小。当屏幕上的数字不变时,就设置好了闹钟。这个时间是可以随时更改的。使用起来很方便。
6.3 内存问题
与上文提到的不能精确的表示时间也有一些关系。我试过用k1按钮表示小时,K2按钮表示分钟。这之后碰到的问题就是内存不够,运行到一半就终止了。而且歌也只能放短短的几秒钟,不满足闹钟长达十秒钟或更久的设计理念。所以,只能退而求稳。用两个按钮只表示时间,做一个只能“整点”报时的闹钟。但是,也不是没有优点,因为如果只用一个按钮来表示小时,当你错过了你要选择的时间,那么只能0~23这个循环结束后才能再次选择自己想要的时间,是没有容错的。当用两个按钮的时候,一个增加,另一个减小,互相配合,可以很快地设置时间。
7.未来的计划及实现
该项目已经成功实现了整点定时报警时钟的功能,并达到了预期指标。然而在实现的过程中有几处不足:
- WS2812B RGB三色灯的检修,避免类似我这种用不了蓝灯的情况。
- 可以适当增加按键的个数,可以实现更多的功能。
- 内存可以尽可能多一点,以便实现更多的功能。
8.心得体会
通过这次的“寒假在家练”的活动,对嵌入式系统有了新的认知,并且python语言的使用度也提高了不少。很大程度的提高了专业能力,是不可多得的一次项目经验,受益良多。