树莓派如何控制LED矩阵,用Raspberry Pi制作HAT数字时钟

在本教程中,详细记录了使用树莓派控制LED矩阵,制作一个酷酷的Raspberry Pi HAT数字时钟。

Digital-Clock-SenseHAT-Thumbnail.jpg

还详细描述了如何在Raspberry Pi上编写一个Python脚本,它可以读取系统的当前时间,然后通过LED矩阵展示出来。

本教程会展示如何利用数组和数值来逐行打印数值到Raspberry Pi的Sense HAT LED矩阵上。

为了使时钟更准确,特别是不想让树莓派一直联网,可以使用一个实时时钟模块,时钟模块可以保证即使是树莓派断电了时间依然是准确的。

设备清单

以下是完成这篇树莓派Sense HAT数字时钟教程所需的全部设备清单。

建议

可选

开始使用Sense HAT

现在,在开始使用SenseHAT作为数字时钟之前,必须对它进行设置和测试,以确保一切工作正常。

1. 首先在Raspberry Pi上运行以下命令,将操作系统更新到最新版本。

sudo apt-get update
sudo apt-get upgrade

2. 现在已经更新了Raspberry Pi的操作系统,必须安装sense-hat包。这个包包含了与设备交互所需的所有库。

sudo apt-get install sense-hat
sudo reboot

3. 将sense-hat库下载到Raspberry Pi后,需要写一个脚本,以确保能够与设备交互。

可以在Raspberry Pi上用以下命令开始编写这个脚本。

sudo nano ~/sensehat_test.py

4. 现在,在这个脚本中,需要编写以下几行代码。我将边写边解释每段代码的作用。

from sense_hat import SenseHat

这一行从sense_hat库中导入SenseHat模块。这样就可以通过Python本身与Sense HAT进行交互。

sense = SenseHat()

这一行将SenseHat类的副本实例化到sense变量中。将使用sense变量与SenseHat类交互,并调用它的函数。

sense.show_message("Hello World")

这一行只是简单地将文字信息推送到SenseHAT的LED矩阵上。这里是 “Hello World “。

5. 现在按CTRL + X,然后按Y,最后按ENTER键保存文件。

6. 现在已经保存了文件,在终端机上使用以下命令运行它。

sudo python ~/sensehat_test.py

现在应该看到 “Hello World “的文字在Sense Hat上的Led矩阵上滚动。

如果Sense HAT上没有任何显示,很可能是Sense HAT没有正确地接在GPIO引脚上面,或者是设备出现了故障。

如果还是不行,请尝试在Raspberry Pi上运行以下命令来重新启动它。

sudo reboot

将Sense HAT变成数字时钟

接下来,就是写出Sense Hat数字时钟的代码了。这段代码的灵感来自于Steve Amor使用Sense Hat开发Raspberry Pi数字时钟的工作。

在本教程中,使用了大量的Python代码,如果你是Python的新手,可以阅读我的Python入门指南

1. 现在,已经安装了脚本所需的一切,并测试Sense Hat正在工作。可以继续编写脚本了。

创建一个文件夹来保存新脚本。将这个文件夹命名为 digitialclock,并将其保存在 Pi 用户的主目录中。

在终端中运行以下命令来创建这个文件夹。

mkdir ~/digitalclock

2. 现在已经创建了文件夹,将改变到目录中,并通过运行以下两个命令开始编写脚本。

cd ~/digitalclock
nano digitalclock.py

3. 现在将以下几行代码写到文件中。我会对代码的每一部分进行解释,这样你就能很好地理解一切是如何工作的。

#!/usr/bin/env python

from sense_hat import SenseHat
import time

sense = SenseHat()

第一行告诉操作系统如何解释这个文件,在我的例子中,我是用它来告诉操作系统使用Python来运行这个文件。

下一行从sense_hat库中导入SenseHat模块,这就是我在本教程第一节中安装的库。

利用这个脚本中的SenseHat模块与Sense Hat设备进行对话,并通过打开矩阵上的特定LED灯将时间显示在8×8 LED矩阵上。

在下一行,导入另一个库,这次导入的是时间库。利用时间库直接从操作系统本身获取当前时间。

通过得到这些值,可以从数组中选择决定哪些像素需要被打开或关闭。

接下来,创建一个SenseHat对象,在整个脚本中利用这个对象来控制Sense Hat。只需要这个能够将我们的数组传递给设备,告诉它哪些像素需要被打开或关闭。

在接下来的几节代码中看到如何利用这些库。

number = [
[[0,1,1,1], # Zero
[0,1,0,1],
[0,1,0,1],
[0,1,1,1]],
[[0,0,1,0], # One
[0,1,1,0],
[0,0,1,0],
[0,1,1,1]],
[[0,1,1,1], # Two
[0,0,1,1],
[0,1,1,0],
[0,1,1,1]],
[[0,1,1,1], # Three
[0,0,1,1],
[0,0,1,1],
[0,1,1,1]],
[[0,1,0,1], # Four
[0,1,1,1],
[0,0,0,1],
[0,0,0,1]],
[[0,1,1,1], # Five
[0,1,1,0],
[0,0,1,1],
[0,1,1,1]],
[[0,1,0,0], # Six
[0,1,1,1],
[0,1,0,1],
[0,1,1,1]],
[[0,1,1,1], # Seven
[0,0,0,1],
[0,0,1,0],
[0,1,0,0]],
[[0,1,1,1], # Eight
[0,1,1,1],
[0,1,1,1],
[0,1,1,1]],
[[0,1,1,1], # Nine
[0,1,0,1],
[0,1,1,1],
[0,0,0,1]]
]

这个非常大的数组就是要用来显示时钟的数字。时钟的每一个数字都被分割到自己的列表中,然后再次被分割成四个独立的部分。

将数组分割成这些列表,以方便输出到LED矩阵。很快就会看到如何利用数组将这些数字推送到设备上。

noNumber = [0,0,0,0]

还有一个小数组,只有四个零值。使用这个数组来填充LED矩阵中不希望显示数字的地方。

hourColor = [255,0,0] # Red
minuteColor = [0,255,255] # Cyan
empty = [0,0,0] # Black/Off

这三个变量用于声明LED的时、分和空槽的RGB值。

如果想改变小时的颜色,只需要将数组的三个值改为相关的RGB值即可。

clockImage = []

hour = time.localtime().tm_hour
minute = time.localtime().tm_min

在这部分代码中,首先创建一个名为clockImage的空数组。需要这个空数组,因为将从大数组填充数字给它。

接下来,获取当前的小时和分钟,并将其存储在变量中。利用这些变量来决定需要显示的数字。

for index in range(0, 4):
    if (hour >= 10):
        clockImage.extend(number[int(hour/10)][index])
    else:
        clockImage.extend(noNumber)
    clockImage.extend(number[int(hour%10)][index])

for index in range(0, 4):
    clockImage.extend(number[int(minute/10)][index])
    clockImage.extend(number[int(minute%10)][index])

运行两个不同的for循环,第一个循环处理顶部的小时数,第二个循环处理LED矩阵底部显示的分钟数。

对于每个循环,使用Pythons的.extend函数来处理列表,利用这个函数,在一次调用中从每个数字中插入一行4个元素,这就避免了必须运行两个并发循环的问题。

为了从数组中得到正确的数字,做一些简单的数学运输。在一个两位数的数字中,使用除以10的方法来获取第一个数字。例如12,从10的求余中得到1。

为了得到第二位数,利用模数,它将除法的余数返回,所以在之前的数字(12)的情况下,得到2。

for index in range(0, 64):
    if (clockImage[index]):
        if index < 32:
            clockImage[index] = hourColor
        else:
            clockImage[index] = minuteColor
    else:
        clockImage[index] = empty

现在,的最后一个循环将遍历整个 clockImage 数组,这个循环的目的是将每个数字与 RGB 值交换。

只需检查该索引中是否有数字0或1即可实现。如果是0,就向这个数字输出空变量值。

否则,检查是否在处理前32个像素(LED矩阵的上半部分),如果在上半部分,从小时颜色变量中获取RGB值。否则,利用minuteColor变量中的RGB值。

sense.set_rotation(90) # Optional
sense.low_light = True # Optional
sense.set_pixels(clockImage)

现在是最后的三行代码。

这些行的第一行设置了LED矩阵的旋转,可以根据你想让数字时钟显示的方向来改变。

第二行将Sense HAT的低光模式设置为 “开启”,这基本上是将LED灯的亮度调低,使其没有那么亮。如果把Sense HAT放在一个有亮光的地方,请把这行注释掉或删除。

最后一行输出clockImage数组到Sense HAT,这一行是最后在Sense HAT的led矩阵上显示时间。

4. 下面附上了一份最终的脚本。

写完之后,可以按CTRL + X然后按Y,最后按ENTER键保存文件。

#!/usr/bin/env python

from sense_hat import SenseHat
import time

sense = SenseHat()

number = [
[[0,1,1,1], # Zero
[0,1,0,1],
[0,1,0,1],
[0,1,1,1]],
[[0,0,1,0], # One
[0,1,1,0],
[0,0,1,0],
[0,1,1,1]],
[[0,1,1,1], # Two
[0,0,1,1],
[0,1,1,0],
[0,1,1,1]],
[[0,1,1,1], # Three
[0,0,1,1],
[0,0,1,1],
[0,1,1,1]],
[[0,1,0,1], # Four
[0,1,1,1],
[0,0,0,1],
[0,0,0,1]],
[[0,1,1,1], # Five
[0,1,1,0],
[0,0,1,1],
[0,1,1,1]],
[[0,1,0,0], # Six
[0,1,1,1],
[0,1,0,1],
[0,1,1,1]],
[[0,1,1,1], # Seven
[0,0,0,1],
[0,0,1,0],
[0,1,0,0]],
[[0,1,1,1], # Eight
[0,1,1,1],
[0,1,1,1],
[0,1,1,1]],
[[0,1,1,1], # Nine
[0,1,0,1],
[0,1,1,1],
[0,0,0,1]]
]
noNumber = [0,0,0,0]

hourColor = [255,0,0] # Red
minuteColor = [0,255,255] # Cyan
empty = [0,0,0] # Black/Off

clockImage = []

hour = time.localtime().tm_hour
minute = time.localtime().tm_min

for index in range(0, 4):
    if (hour >= 10):
        clockImage.extend(number[int(hour/10)][index])
    else:
        clockImage.extend(noNumber)
    clockImage.extend(number[int(hour%10)][index])

for index in range(0, 4):
    clockImage.extend(number[int(minute/10)][index])
    clockImage.extend(number[int(minute%10)][index])

for index in range(0, 64):
    if (clockImage[index]):
        if index < 32:
            clockImage[index] = hourColor
        else:
            clockImage[index] = minuteColor
    else:
        clockImage[index] = empty

sense.set_rotation(90) # Optional
sense.low_light = True # Optional
sense.set_pixels(clockImage)

5. 现在可以测试运行代码了,只要在Raspberry Pi上运行以下命令即可。

python ~/digitalclock/digitalclock.py

如果一切运行正常,现在应该可以看到当前时间出现在设备上。

当然,拥有一个永不更新的时钟是没有用的。可以利用crontab来每分钟更新一下时间。

如果想扩展这个脚本,可以显示不同时区的时间,那么可以按照下一节详细介绍如何处理树莓派数字时钟的时区。

处理SenseHAT数字钟的时区问题。

在本节中,我将展示如何修改SenseHat数字时钟脚本,可以显示不同时区的时间,而不仅仅是操作系统定义的时间。

1. 在开始改变脚本来处理不同的时区之前,必须首先确保Python pip包已经安装到Raspberry Pi上,使用这个包来安装所需的python库。

可以通过先更新包列表,然后使用apt-get安装pip,运行下面的命令。

sudo apt-get update
sudo apt-get install python-pip

2. 为了处理不同的时区,利用一个名为Arrow的Python包。

这个包极大地简化了检索特定时区时间的过程,不需要将几个不同的包串在一起。

使用pip运行下面的命令将库安装到Raspberry Pi上。

sudo pip install arrow

3. 现在已经安装了Arrow Python包,需要修改脚本,使它能利用这个包而不是时间库。

输入下面的命令,开始修改SenseHAT数字时钟脚本。

nano ~/digitalclock/digitalclock.py

4. 现在修改脚本,先用新安装的Arrow包替换时间包。

找到下面一行:

import time

替换为:

import arrow

5. 现在时间包被替换了,需要继续修改一下实际脚本逻辑,因为现在需要使用Arrow包来检索时间。

找到下面的代码部分。

hour = time.localtime().tm_hour
minute = time.localtime().tm_min

改为:

time = arrow.now('Asia/Tokyo')

hour = time.hour
minute = time.minute

如果看一下这段新的代码,已经改变了它,没有利用Arrow的 “now “函数从Arrow获取时间。在这个 “now “函数中,要输入想要获取当前时间的时区,在我的例子中,我使用的是 “亚洲/东京 “时区。

Arrow软件包使用由datutil软件包提供的tz数据库中的时区。可以在TZ数据库的维基百科上找到这些时区的列表。这个网页很容易找到想要的时区。

6. 这就是需要做的所有事情,把脚本改成使用Arrow包,现在SenseHAT上显示的时间应该出现在arrow.now(“)函数中定义的时区。

改好后,按CTRL + X然后按Y然后按ENTER键保存文件。

7. 现在对脚本进行了修改,继续运行它来测试修改是否正确。

python ~/digitalclock/digitalclock.py

如果一切正常,现在应该可以看到你指定的时区的时间出现在SenseHAT上。

在下一节中,完成Sense HAT数字时钟自动更新。

自动化Sense HAT数字钟

1. 在将脚本添加到crontab之前,做的第一件事是使其可执行。

可以在Raspberry Pi上使用以下命令来实现。这条命令将使用chmod来添加脚本的执行权限。

chmod +x ~/digitalclock/digitalclock.py

2. 现在已经给了数字钟脚本执行权限,可以开始编辑crontab了。

在Raspberry Pi上运行以下命令来编辑crontab。

sudo crontab -e

3. 在文件中添加以下一行。这一行会告诉操作系统,需要每分钟运行这个文件。

* * * * * /home/pi/digitalclock/digitalclock.py

4. 在对文件进行修改后,可以按CTRL + X,然后按Y,最后按ENTER键保存。

系统现在会自动加载新的crontab并开始处理。

5. 应该可以看到Sense HAT上的时间每分钟更新一次。

希望通过本教程,你现在已经成功地将Raspberry Pi的Sense HAT设置为一个数字时钟。

这个教程只是众多例子中的一个,你可以用Raspberry Pi Sense Hat来做什么。一个同样值得一试的项目是使用Raspberry Pi Sense HAT制作的气象站。

如果你对这个Raspberry Pi Sense HAT数字时钟教程有任何反馈,请在下面留言讨论。

平均: 0 / 5. votes: 0

到目前为止还没有投票!成为第一位评论此文章。

欢迎转载,请留下出处链接:Labno3 » 树莓派如何控制LED矩阵,用Raspberry Pi制作HAT数字时钟

赞 (1)

评论

9+8=