Redian新闻
>
使用树莓派做一个倒计时器 | Linux 中国

使用树莓派做一个倒计时器 | Linux 中国

科技
 
导读:使用树莓派和电子纸显示屏开始倒计时你的下一个假期。                                 
本文字数:9501,阅读时长大约:12分钟

圆周率日🔗 en.wikipedia.org(Pi Day)(3 月 14 日) 来了又走,留下美好的回忆以及 许多树莓派项目🔗 opensource.com 等待我们去尝试。在任何令人精神振奋、充满欢乐的假期后回到工作中都很难,圆周率日也不例外。当我们回望三月的时候,渴望那些天的快乐。但是不用害怕,亲爱的圆周率日庆祝者们,我们开始下一个节日的漫长倒计时!

好了,严肃点。我做了一个圆周率日倒计时器,你也可以!

不久前,我购买了一个 树莓派 Zero W🔗 www.raspberrypi.org,并且用它来 解决 WiFi 信号较差的原因🔗 opensource.com 。我也对使用电子纸(ePaper)来作为它的显示屏十分感兴趣。虽然我不知道该用它来干什么,但是!它看起来真的很有趣!我买了一个十分适合放在树莓派的顶部的 2.13 英寸的 WaveShare 显示器🔗 www.waveshare.com 。安装很简单:只需要将显示器接到树莓派的 GPIO 上即可。

我使用 树莓派操作系统🔗 www.raspberrypi.org 来实现该项目,虽然其他的操作系统肯定也能完成。但是下面的 raspi-config 命令在树莓派系统上很容易使用。

设置树莓派和电子纸显示屏

设置树莓派和电子纸显示屏一起工作,需要你在树莓派软件中启用串行外设接口(SPI),安装 BCM2835 C 库(来访问树莓派上的博通 BCM 2835 芯片的 GPIO 功能),安装 Python GPIO 库来控制电子纸显示屏。最后,你需要安装 WaveShare 的库来使用 Python 控制这个 2.13 英寸的显示屏。

下面是完成这些的步骤。

启用 SPI

树莓派上启用 SPI 最简单的方式是使用 raspi-config 命令。SPI 总线允许与设备进行串行数据通信——在本例中,电子纸显示:

  1. $ sudo raspi-config

从弹出的菜单中, 选择 “接口选项(Interfacing Options)-> SPI -> (Yes)” 来启用 SPI 接口,然后启动。

安装 BCM2835 库

如上所述,BCM2835 库是用于树莓派博通 BCM2385 芯片的软件,它允许访问 GPIO 引脚来控制设备。

在我写这篇文章之时,用于树莓派的最新博通 BCM2385 库版本是 v1.68 。安装此库需要下载软件压缩包然后使用 make 来安装:

  1. # 下载 BCM2853 库并解压
  2. $ curl -sSL http://www.airspayce.com/mikem/bcm2835/bcm2835-1.68.tar.g> -o - | tar -xzf -
  3. # 进入解压后的文件夹
  4. $ pushd bcm2835-1.68/
  5. # 配置、检查并安装 BCM2853
  6. $ sudo ./configure
  7. $ sudo make check
  8. $ sudo make install
  9. # 返回上级目录
  10. $ popd

安装需要的 Python 库

你用 Python 控制电子纸显示屏需要安装 Python 库 RPi.GPIO,还需要使用 python3-pil 包来画图。显然,PIL 包已经不行了,但 Pillow 可以作为代替方案。我还没有为该项目测试过 Pillow ,但它可行:

  1. # 安装需要的 Python
  2. $ sudo apt-get update
  3. $ sudo apt-get install python3-pip python3-pil
  4. $ sudo pip3 install RPi.GPIO

注意:这些是 Python3 的指令。你可以在 WaveShare 网站查到 Python2 的指令。

下载 WaveShare 示例和 Python 库

Waveshare 维护了一个 Python 和 C 的 Git 库,用于使用其电子纸显示屏和一些展示如何使用它们的示例。对这个倒计时时钟而言,你需要克隆这个库并使用用于 2.13 英寸显示屏的库:

  1. # 克隆这个 WaveShare e-Paper git
  2. $ git clone https://github.com/waveshare/e-Paper.gi>

如果你用不同的显示器或者其他公司产品,需要使用适配软件。

Waveshare 提供了很多指导:

◈ WaveShare 电子纸设置指导🔗 www.waveshare.com
◈ WaveShare 电子纸库安装指导🔗 www.waveshare.com

获得有趣的字体(选做)

你可以随心所欲的使用显示器,为什么不搞点花样?找一个炫酷的字体!

这有大量 开放字体许可🔗 scripts.sil.org 的字体可供选择。我十分喜爱 Bangers 字体。如果你看过 YouTube 那你见过这种字体了,它十分流行。你可以下载到本地的共享字体目录文件中,并且所有的应用都可以使用,包括这个项目:

  1. # Bangers 字体是 Vernon Adams 使用 Google 字体开放许可授权的字体
  2. $ mkdir -p ~/.local/share/fonts
  3. $ curl -sSL https://github.com/google/fonts/raw/master/ofl/bangers/Bangers-Regular.ttf -o fonts/Bangers-Regular.ttf

创建一个圆周率日倒计时器

现在你已经安装好了软件,可以使用带有炫酷字体的电子纸显示屏了。你可以创建一个有趣的项目:倒计时到下一个圆周率日!

如果你想,你可以从该项目的 GitHub 仓库🔗 github.com 直接下载 countdown.py🔗 github.com 这个 Python 文件并跳到文章结尾。

为了满足大家的好奇心,我将逐步讲解。

导入一些库

  1. #!/usr/bin/python3
  2. # -*- coding:utf-8 -*-
  3. import logging
  4. import os
  5. import sys
  6. import time
  7. from datetime import datetime
  8. from pathlib import Path
  9. from PIL import Image,ImageDraw,ImageFont
  10. logging.basicConfig(level=logging.INFO)
  11. basedir = Path(__file__).parent
  12. waveshare_base = basedir.joinpath('e-Paper', 'RaspberryPi_JetsonNano', 'python')
  13. libdir = waveshare_base.joinpath('lib')

开始先导入一些标准库之后脚本中用。也需要你从 PIL 添加 ImageImageDraw 和 ImageFont,你会用到这些来画一些简单的图形。最后,为本地 lib 目录设置一些变量,该目录包含了用于 2.13 英寸显示屏的 Waveshare Python 库,稍后你可以使用这些变量从本地目录加载库。

字体大小辅助函数

下一部分是为你选择的 Bangers-Regular.ttf 字体建立一个修改大小的辅助函数。该函数将整型变量作为大小参数,并返回一个图形字体对象来用于显示:

  1. def set_font_size(font_size):
  2.     logging.info("Loading font...")
  3.     return ImageFont.truetype(f"{basedir.joinpath('Bangers-Regular.ttf').resolve()}", font_size)

倒计时逻辑

接下来是计算这个项目的一个函数:距下次圆周率日还有多久。如果是在一月,那么计算剩余天数将很简单。但是你需要考虑是否今年的圆周率日是否已经过去了(允悲)。如果是的话,那么计算在你可以再次庆祝之前还有多少天:

  1. def countdown(now):
  2.     piday = datetime(now.year, 3, 14)
  3.     # 如果错过了就增加一年
  4.     if piday < now:
  5.         piday = datetime((now.year + 1), 3, 14)
  6.     days = (piday - now).days
  7.     logging.info(f"Days till piday: {days}")
  8.     return day

主函数

最后,到了主函数,需要初始化显示屏并向它写数据。这时,你应该写一个欢迎语然后再开始倒计时。但是首先,你需要加载 Waveshare 库:

  1. def main():
  2.     if os.path.exists(libdir):
  3.         sys.path.append(f"{libdir}")
  4.         from waveshare_epd import epd2in13_V2
  5.     else:
  6.         logging.fatal(f"not found: {libdir}")
  7.         sys.exit(1)

上面的代码片段检查以确保该库已下载到倒计时脚本旁边的目录中,然后加载epd2in13_V2 库。如果你使用不同的显示屏,则需要使用不同的库。如果你愿意,也可以自己编写。我发现阅读 Waveshare 随显示屏提供的 Python 代码很有趣,它比我想象的要简单得多。

下一段代码创建一个 EPD(电子纸显示屏)对象以与显示器交互并初始化硬件:

  1.     logging.info("Starting...")
  2.     try:
  3.         # 创建一个显示对象
  4.         epd = epd2in13_V2.EPD()
  5.         # 初始化并清空显示
  6.         # ePaper 保持它的状态处分更新
  7.         logging.info("Initialize and clear...")
  8.         epd.init(epd.FULL_UPDATE)
  9.         epd.Clear(0xFF)

关于电子纸的一个有趣之处:它仅在将像素从白色变为黑色或从黑色变为白色时才耗电。这意味着当设备断电或应用程序因任何原因停止时,屏幕上的任何内容都会保留下来。从功耗的角度来看,这很好,但这也意味着你需要在启动时清除显示,否则你的脚本只会覆盖屏幕上已有的内容。因此,epd.Clear(0xFF) 用于在脚本启动时清除显示。

接下来,创建一个“画布”来绘制剩余的显示输出:

  1.     # 创建一个图形对象
  2. # 注意:"epd.heigh" 是屏幕的长边
  3. # 注意:"epd.width" 是屏幕的短边
  4.     # 真是反直觉…
  5.     logging.info(f"Creating canvas - height: {epd.height}, width: {epd.width}")
  6.     image = Image.new('1', (epd.height, epd.width), 255)  # 255: clear the frame
  7.     draw = ImageDraw.Draw(image)

这与显示器的宽度和高度相匹配——但它有点反直觉,因为显示器的短边是宽度。我认为长边是宽度,所以这只是需要注意的一点。请注意,epd.height 和 epd.width 由 Waveshare 库设置以对应于你使用的设备。

欢迎语

接下来,你将开始画一些画。这涉及在你之前创建的“画布”对象上设置数据。这还没有将它绘制到电子纸显示屏上——你现在只是在构建你想要的图像。由你为这个项目绘制带有一块馅饼的图像,来创建一个庆祝圆周率日的欢迎信息:

画一块馅饼

很可爱,不是吗?

  1.     logging.info("Set text text...")
  2.     bangers64 = set_font_size(64)
  3.     draw.text((0, 30), 'PI DAY!', font = bangers64, fill = 0)
  4.     logging.info("Set BMP...")
  5.     bmp = Image.open(basedir.joinpath("img", "pie.bmp"))
  6.     image.paste(bmp, (150,2))

最后,真是是最后了,你可以展示你画的图画:

  1.     logging.info("Display text and BMP")
  2.     epd.display(epd.getbuffer(image))

上面那段话更新了显示屏,以显示你所画的图像。

接下来,准备另一幅图像展示你的倒计时:

圆周率日倒计时

首先,创建一个用来展示倒计时的图像对象。也需要设置数字的字体大小:

  1.     logging.info("Pi Date countdown; press CTRL-C to exit")
  2.     piday_image = Image.new('1', (epd.height, epd.width), 255)
  3.     piday_draw = ImageDraw.Draw(piday_image)
  4.     # 设置字体大小
  5.     bangers36 = set_font_size(36)
  6.     bangers64 = set_font_size(64)

为了使它显示的时候更像一个倒计时,更新图像的一部分是更加有效的手段,仅更改已经改变的显示数据部分。下面的代码准备以这样方式运行:

  1.     # 准备更新显示
  2.     epd.displayPartBaseImage(epd.getbuffer(piday_image))
  3.     epd.init(epd.PART_UPDATE)

最后,需要计时,开始一个无限循环来检查据下次圆周率日还有多久,并显示在电子纸上。如果到了圆周率日,你可以输出一些庆祝短语:

  1.     while (True):
  2.         days = countdown(datetime.now())
  3.         unit = get_days_unit(days)
  4.         # 通过绘制一个填充有白色的矩形来清除屏幕的下半部分
  5.         piday_draw.rectangle((0, 50, 250, 122), fill = 255)
  6.         # 绘制页眉
  7.         piday_draw.text((10,10), "Days till Pi-day:", font = bangers36, fill = 0)
  8.         if days == 0:
  9.             # 绘制庆祝语
  10.             piday_draw.text((0, 50), f"It's Pi Day!", font = bangers64, fill = 0)
  11.         else:
  12.             # 绘制距下一次 Pi Day 的时间
  13.             piday_draw.text((70, 50), f"{str(days)} {unit}", font = bangers64, fill = 0)
  14.         # 渲染屏幕
  15.         epd.displayPartial(epd.getbuffer(piday_image))
  16.         time.sleep(5)

脚本最后做了一些错误处理,包括捕获键盘中断,这样你可以使用 Ctrl + C 来结束无限循环,以及一个根据计数来打印 day 或 days 的函数:

  1.     except IOError as e:
  2.         logging.info(e)
  3.     except KeyboardInterrupt:
  4.         logging.info("Exiting...")
  5.         epd.init(epd.FULL_UPDATE)
  6.         epd.Clear(0xFF)
  7.         time.sleep(1)
  8.         epd2in13_V2.epdconfig.module_exit()
  9.         exit()
  10. def get_days_unit(count):
  11.     if count == 1:
  12.         return "day"
  13.     return "days"
  14. if __name__ == "__main__":
  15.     main()

现在你已经拥有一个倒计时并显示剩余天数的脚本!

安装 systemd 服务(选做)

如果你希望在系统打开时运行倒计时显示,并且无需登录并运行脚本,你可以将可选的 systemd 单元安装为 systemd 用户服务🔗 wiki.archlinux.org

将 GitHub 上的 piday.service🔗 github.com 文件复制到 ${HOME}/.config/systemd/user,如果该目录不存在,请先创建该目录。然后你可以启用该服务并启动它:

  1. $ mkdir -p ~/.config/systemd/user
  2. $ cp piday.service ~/.config/systemd/user
  3. $ systemctl --user enable piday.service
  4. $ systemctl --user start piday.service
  5. # Enable lingering, to create a user session at boot
  6. # and allow services to run after logout
  7. $ loginctl enable-linger $USER

该脚本将输出到 systemd 日志,可以使用 journalctl 命令查看输出。

它开始看起来像是圆周率日了!

这就是你的作品!一个显示在电子纸显示屏上的树莓派 Zero W 圆周率日倒计时器!并在系统启动时使用 systemd 单元文件启动!现在距离我们可以再次相聚庆祝圆周率日还有好多天的奇妙设备———树莓派。通过我们的小项目,我们可以一目了然地看到确切的天数。

但实际上,每个人都可以在每一天在心中庆祝圆周率日,因此请使用自己的树莓派创建一些有趣且具有教育意义的项目吧!


via: https://opensource.com/article/21/3/raspberry-pi-countdown-clock

作者:Chris Collins 选题:lujun9972 译者:Donkey 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出


LCTT 译者 :Donkey
🌟🌟
翻译: 2.0 篇
|
贡献: 9 天
2022-06-09
2022-06-18
https://linux.cn/lctt/Donkey-Hao
欢迎遵照 CC-BY-SA 协议规定转载,
如需转载,请在文章下留言 “转载:公众号名称”,
我们将为您添加白名单,授权“转载文章时可以修改”。

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
硬核观察 #681 首颗树莓派卫星完成了创纪录的飞行十二月的雪在 Linux 上使用 sudo 命令的 5 个理由 | Linux 中国英伟达在提升 Linux 上的 GPU 使用体验上迈出了一大步 | Linux 中国Pop!_OS 22.04 Linux 发行版现在支持树莓派 4 了 | Linux 中国[掌设] 最最折腾的开源掌机,GPI CASE2 +树莓派CM4 8GB WIFI合体如何在 Linux 桌面中启用 “激活 Linux” 水印通知 | Linux 中国在 Linux 中使用组合键输入隐藏的字形 | Linux 中国Fedora Linux 37 即将正式支持树莓派 4 | Linux 中国鼓励居民缩短淋浴时间 阿罕布拉分发计时器上一个说“丼”不读jǐng的人,已经被我骂哭了检查 Linux 磁盘使用情况 | Linux 中国HydraPaper:一个支持多显示器的 Linux 壁纸管理器 | Linux 中国诺基亚勒令一个开源 Linux 手机项目 “NOTKIA” 改名字 | Linux 中国我是如何使用 Linux fmt 命令来格式化文本 | Linux 中国使用 dnf 进行 Linux 包管理 | Linux 中国如何在 Linux 中使用 Pandoc 转换文件格式 | Linux 中国分享 8 篇使用 Linux 命令行的技巧 | Linux 中国石头与姚老先生的对话录(二)使用 Go 和树莓派排查 WiFi 问题 | Linux 中国在 Linux 上使用 Rhythbox 听音乐 | Linux 中国在 Linux 上使用 Bash 创建一个临时文件 | Linux 中国要算政治账, 别只算”医学账“!如何使用 Linux sed 命令自动进行文件编辑 | Linux 中国使用 watch 和 tail 命令监视 Linux 上的活动 | Linux 中国神秘的 GeckoLinux 创建者推出了一个新的 Debian 合成发行版 | Linux 中国Dr. Long Health Management Center of Canada (DLHMC)用 XML 和 Java 构建树莓派打印机的用户界面 | Linux 中国Linux Lite 6.0 发布:弃用 Firefox,默认浏览器使用 Chrome | Linux 中国Linux 中国开通播客频道:“开源朗读者”和“硬核观察” | Linux 中国都像德国人骂娘,中共敢不顾死活抗疫?有了扩展,GNOME Web 正逐渐成为 Linux 桌面上一个有吸引力的选择 | Linux 中国使用 Linux 上的开源财务工具 Skrooge 管理你的预算 | Linux 中国使用 apt 进行 Linux 包管理 | Linux 中国微软还有另一个 Linux 发行版,而且是基于 Debian 的 | Linux 中国
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。