项目总结报告
本次我有幸参加了2023寒假一起练活动。本次活动我选择了基于STEP Pico的嵌入式系统学习平台中的项目7 - 制作一个定时报警的时钟。
该项目的具体要求是:制作一个时钟,可以通过板上的12个彩色LED灯来指示时间,并通过蜂鸣器在整点以播放音乐的方式报时,板上的按键可以设置时间。其实现方式是:程序通过定时器计数的方式来生成时、分、秒信号,并根据这些信号来改变12个彩色LED灯的亮灭,产生PWM信号驱动蜂鸣器播放定时长度的音乐。
设计思路:本项目我将其分成两大部分进行解决。一部分是时钟部分,一部分是闹钟部分。时钟部分首先从RTC提取出时间信息,将时间信息给12个WS2812B RGB三色灯和OLED显示屏,并显示出来。正如时钟的时、分、秒针可能会重合一样,RGB三色灯的亮起也会重合,我按照在一个位置的三色灯亮起时长排序,代表秒针的颜色显示为最优先,其次是分针,最后是时针。闹钟部分因为只有两个按钮k1和k2,故我决定用k1当做开始设置闹钟时间和确定闹钟时间并计时的按钮,k2当做增加增加倒计时的按钮。同时要在按下k1时,在OLED显示屏上显示倒计时的时间和按钮的作用,这也就需要在按下k1时需要取消显示时间。倒计时结束时播放音乐,为了方便起见,我使用了老师事先准备的音乐文件。
软件流程图如下:
简单的硬件介绍:STEP Pico是一款低成本,高性能的微控制器开发板,具有灵活数字接口,软件上,可以通过C/C++以及MicroPython编程来学习嵌入式系统的工作原理和应用。平台包含一个树莓派Pico扩展板和一个硬禾版本树莓派Pico核心模块 - STEP Pico。板卡硬件包括2个按键输入、12个WS2812B RGB三色灯、1个128*64 OLED显示屏、1个蜂鸣器、4个单色LED、1个姿态传感器、1个可调电位计(用于电压表)、1路音频信号输入(用于示波器)、8位R-2R电阻网络构成的DAC(用于DDS信号发生器)。本次项目我主要使用了按键输入、RGB三色灯、OLED显示屏、蜂鸣器四种硬件。
实现的功能及图片展示:实现的功能包括用12个WS2812B RGB三色灯和OLED显示屏显示当前的时间,其中红灯表示时针,绿灯表示分针,蓝灯表示秒针,显示优先级为蓝灯>绿灯>红灯;在按下k1按钮后可以用k2按钮进行闹钟时间的设置,并再次按下k1按钮时开始计时,计时结束时播放歌曲,设置期间OLED显示屏显示相关信息。具体效果如下图:
程序均使用micropython编写,我是第一次使用micropython,对程序的编写并不是十分熟悉,部分代码参考了直播课老师所讲述的内容。主要代码片段及说明:
硬件初始化如下:
import ws2812b as wb
from machine import RTC, ADC, Pin
from board import pin_cfg
from time import sleep, sleep_us
from oled import oled
import freesans20
from writer import Writer
import array
from buzzer_music import music
from my_people_my_country import song
from button import k1, k2
import gc
其中因为我没有找到其他歌曲的代码,所以播放的音乐使用的是老师发的代码,剩下的是比较通用的代码了。
主体循环如下:
while True:
oled.fill(0)
dt_tuple = rtc.datetime()#下面几行是从RTC中获取时间信息
year = dt_tuple[0]
month = dt_tuple[1]
day =dt_tuple[2]
hour = dt_tuple[4]
minite = dt_tuple[5]
second = dt_tuple[6]
oled_time.show_date(year, month, day) #下面几行把时间信息传递给RGB三色灯和OLED显示屏显示程序
oled_time.show_tim(hour, minite, second)
ws2812_time.show_time(hour, minite, second)
alarm_time.update(second) #下面几行从两个按键获取值并传递给闹钟程序
k1_value = k1.value()
k2_value = k2.value()
fsm.update(k1_value, k2_value, second)
if fsm.state == StateMachine.ShowCurrentTime: #两个if语句控制OLED的显示状态,使未按k1及确定闹钟时间时显示时间,按下k1还未确定闹钟时间时显示闹钟相关信息。
oled_time.draw2()
oled_time.draw1()
if fsm.state == StateMachine.SettingAlarmTime:
alarm_time.draw()
ws2812_time.draw() #使RGB灯显示时间
oled.show()
pd.render()
alarm_time.render() #闹钟计时结束时播放音乐
tick = (tick + 1) % 65536
sleep(0.04) # fps = 25
OLED显示时间子程序代码:
class OledTime():
def __init__(self, oled):
self.oled = oled
self.oled.fill(0)
self.wri = Writer(oled, freesans20)
def show_tim(self, hour, minite, second):
self.h=hour
self.mi=minite
self.s=second
def draw1(self): #draw1和2控制显示的内容和位置
self.wri.set_textpos(oled, 30, 20)
self.wri.printstring(str(self.h))
self.wri.set_textpos(oled, 30, 60)
self.wri.printstring(str(self.mi))
self.wri.set_textpos(oled, 30, 100)
self.wri.printstring(str(self.s))
def show_date(self, year, month, day):
self.y = year
self.m = month
self.d = day
def draw2(self):
self.wri.set_textpos(oled, 10, 10)
self.wri.printstring(str(self.y))
self.wri.set_textpos(oled, 10, 70)
self.wri.printstring(str(self.m))
self.wri.set_textpos(oled, 10, 100)
self.wri.printstring(str(self.d))
控制闹钟子程序:
class StateMachine():
SettingAlarmTime = 0
ShowCurrentTime = 1
def __init__(self, alarmTime):
self.state = StateMachine.ShowCurrentTime
self.old_state = self.state
self.alarmTime = alarmTime
def update(self, k1, k2, s):
self.old_state = self.state
if self.state == StateMachine.ShowCurrentTime:
self.showCurrentTime(k1)
elif self.state == StateMachine.SettingAlarmTime:
self.settingAlarmTime(k1, k2, s)
def showCurrentTime(self, k1):#未按k1显示时间
if k1 == False:
pass
elif k1 == True:
self.alarmTime.on = False
self.state = StateMachine.SettingAlarmTime
def settingAlarmTime(self, k1, k2, s):#按k1显示倒计时的时间
if k1 == False:
if k2:
self.alarmTime.s = (self.alarmTime.s + 5) % 60
pass
if k1 == True:
self.alarmTime.ss = (s + self.alarmTime.s + 1) % 60
self.alarmTime.on = True
self.state = StateMachine.ShowCurrentTime
遇到的主要问题及解决方法:在项目执行的过程中我遇到了一些比较棘手的问题,在时钟部分中rgb灯的显示优先级出现错误以及在调试的过程中有时会出现过了显示的时间但是灯并没有熄灭,最终导致12个灯均是亮的,无法看出时间;在闹钟部分,设定响一段时间的音乐在结束后,蜂鸣器改为发出蜂鸣声。遇到这些问题后,我询问了几位做过STEP Pico的同学,又反复观看了老师的直播课程,对照老师的源代码进行了一定的修改,最后解决了问题。
通过这次项目的开发,我掌握了基本的micropython开发,自己动手完成了一个有趣的项目,拓宽了我的视野,使我对嵌入式系统学习平台有了初步的了解。在以后的学习工作中,如果有时间的话,我可能会继续学习相关知识,动手做点有趣的项目。