初步设想
之前买了一个早鸟唤醒的“光闹钟”,即使用灯光唤醒。但不知是哪里出了问题,尝试了几天闹钟既没能亮也没能响,遂火速退货。于是想着何不用树莓派自制一个呢?
材料清单
- 树莓派3B+
- 树莓派zero
- 压电式蜂鸣器
- LED小灯泡
- 按钮式开关
- 跳线若干
说明:
之所以我用了两个树莓派,是因为树莓派zero性能较差而树莓派3B+价格较高(我买的二手的,¥220)。又考虑到二者的GPIO几乎一样(见下两图),所以便使用树莓派3B+进行研发测试,而使用树莓派zero作为最终产品。
R-Pi-3-B-Pinout.png
RPI-Zero-Pinout.png
Raspbian的使用
参考:Raspberry
Pi Basics: installing Raspbian and getting it up and running
(howtoforge.com)
树莓派系统对时
参考:Debian/Ubuntu
时区和自动校时设置_debian时间校准-CSDN博客
所需Python包
1 2 3 4
| import gpiozero import time import threading as thr import smbus
|
设定时间的调节
电路连接
设定时间主要是通过两个按钮(一个设定小时,一个设定分钟)实现的。
设定时间的调节.jpg
代码实现
首先定义两个按钮
1 2
| buttonH = gpiozero.Button(22) buttonM = gpiozero.Button(15)
|
在项目目录下新建两个文件分别为minute和hour用来存储我们的时间,并在里面先输入两个值作为初始值。
编写调节函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| def format(num): if num >= 10: return str(num) if num < 10: return "0" + str(num)
def setMin(): with open("minute", "r") as minute_file: minutes = int(minute_file.read()) print(minutes) while True: if buttonM.is_pressed: if minutes - 60 >= -1: minutes = minutes - 59 else: minutes += 1 with open("minute", "w") as minute_file: minute_file.write(str(minutes)) print(minutes) time.sleep(0.2)
def setHour(): with open("hour", "r") as hour_file: hours = int(hour_file.read()) print(hours) while True: if buttonH.is_pressed: if hours - 24 >= -1: hours = hours - 23 else: hours += 1 with open("hour", "w") as hour_file: hour_file.write(str(hours)) print(format(hours)) time.sleep(0.2)
|
上面的format()函数用于将个位数变为"0"+数字的形式,便于后续在LCD显示屏上显示。
设定时间和当前时间的显示
在这里,我们选用LCD显示屏。有关树莓派和LCD屏幕的更多信息,可以参考:树莓派通过
I2C 驱动 LCD1602 液晶屏 | 树莓派实验室 (nxez.com)
电路连接
连接LCD.jpg
所需库的写入
复制以下这段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| import time import smbus BUS = smbus.SMBus(1) LCD_ADDR = 0x27 BLEN = 1 def turn_light(key): global BLEN BLEN = key if key ==1 : BUS.write_byte(LCD_ADDR ,0x08) else: BUS.write_byte(LCD_ADDR ,0x00) def write_word(addr, data): global BLEN temp = data if BLEN == 1: temp |= 0x08 else: temp &= 0xF7 BUS.write_byte(addr ,temp) def send_command(comm): buf = comm & 0xF0 buf |= 0x04 write_word(LCD_ADDR ,buf) time.sleep(0.002) buf &= 0xFB write_word(LCD_ADDR ,buf) buf = (comm & 0x0F) << 4 buf |= 0x04 write_word(LCD_ADDR ,buf) time.sleep(0.002) buf &= 0xFB write_word(LCD_ADDR ,buf) def send_data(data): buf = data & 0xF0 buf |= 0x05 write_word(LCD_ADDR ,buf) time.sleep(0.002) buf &= 0xFB write_word(LCD_ADDR ,buf) buf = (data & 0x0F) << 4 buf |= 0x05 write_word(LCD_ADDR ,buf) time.sleep(0.002) buf &= 0xFB write_word(LCD_ADDR ,buf) def init_lcd(): try: send_command(0x33) time.sleep(0.005) send_command(0x32) time.sleep(0.005) send_command(0x28) time.sleep(0.005) send_command(0x0C) time.sleep(0.005) send_command(0x01) BUS.write_byte(LCD_ADDR ,0x08) except: return False else: return True def clear_lcd(): send_command(0x01) def print_lcd(x, y, str): if x < 0: x = 0 if x > 15: x = 15 if y <0: y = 0 if y > 1: y = 1 addr = 0x80 + 0x40 * y + x send_command(addr) for chr in str: send_data(ord(chr)) if __name__ == '__main__': init_lcd() print_lcd(0, 0, 'Hello, world!')
|
保存为LCD1602.py于项目目录下。
显示
编写函数,实现实时显示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| def screening(): while True: t = time.localtime() hour = t.tm_hour minute = t.tm_min lcd.print_lcd(0, 1, "NOW:") lcd.print_lcd(0, 0, "ALARM AT:") lcd.print_lcd(9, 1, format(hour) + ":" + format(minute)) with open("minute", "r") as minute_file: minutes = int(minute_file.read()) print(minutes) lcd.print_lcd(12, 0, format(minutes)) with open("hour", "r") as hour_file: hours = int(hour_file.read()) print(hours) lcd.print_lcd(9, 0, format(hours) + ":") time.sleep(0.1)
|
注意,下面使用这个函数时需要先初始化LCD屏幕:
声闹钟实现
电路连接
连接蜂鸣器.jpg
代码实现
定义蜂鸣器:
1
| buzzer = gpiozero.Buzzer(26)
|
蜂鸣:
1 2 3 4 5
| def buzzing(): buzzer.on() time.sleep(0.5) buzzer.off() time.sleep(0.5)
|