树莓派使用Nokia5110屏幕 高级版

我有一块(未)吃灰多年的树莓派2和很多块(真)吃灰多年的 Nokia 5110 屏幕,最近收拾了一下,翻出了这块屏幕,然后找出了以前为它写的代码,基本就是网上摘抄的代码。心想不能真的就让它永远吃灰下去,于是今天就重新为它写了代码。

为什么叫高级版呢,因为是以前代码的升级啊。

具体效果如图

前期准备:

  • 树莓派: 理论上从一到四代均可。
  • Nokia 5110:淘宝几块到十几块不等。
  • Linux 基础:基础的不能再基础的基础。
  • Python 能力:会打空格就行。如果需要自己定制,那还需要一点基础

要求:

  • python 3:2.7已经死了,早点抛弃吧。树莓派自带有python3。
  • 知晓如何科学的提问:我不是神,问题不讲清楚怎么帮你解决。

缺陷:

  • 不能显示中文:因为我使用的包没有中文字库而且其他能显示中文的字太大了,信息量太少,排版也不好看,就放弃了。

因为是好几年(也就一两年)前的代码。今天去看一个库的时候发现已经停止维护了。也就是不能用 pip 直接安装了(好像一直都不能直接用 pip 安装)。

代码会在最后打包提供下载。

硬件连接

连接方式我直接使用的 https://www.algissalys.com/how-to/nokia-5110-lcd-on-raspberry-pi 的连接方式。一般库用的也是这种连接方式。注意LIGHT口图上是没有标注的,可以连接到3.3V或者5V(但是有些屏幕LIGHT需要接地,具体看淘宝上的描述把)

测试

连接好以后需要测试一下屏幕是否能用或者是否连对了。

在树莓派shell下执行

1
2
3
4
5
6
7
git clone https://github.com/adafruit/Adafruit_Nokia_LCD
# 先安装这个包
cd Adafruit_Nokia_LCD
sudo python3 setup.py install
# 如果没有问题就进行下一步
cd examples
python3 shapes.py # 还有 image.py和animate.py可以执行,都可以试试

如果执行成功会出现

这个图形,这里我偷懒用的网上的图片。

这时候就可以开始下一步了。

添加代码

我的屏幕主要显示如下几项信息:

  1. 时间

  2. 天气(使用的和风天气的api)

  3. CPU信息

  4. ram信息

  5. 磁盘信息

理论上可以定制无限多的信息,只要你觉得自己看得过来。

主代码(显示代码)

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# filename: display.py
# -*- coding: utf-8 -*-
import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_Nokia_LCD as LCD
import pi
import my_weather
import requests
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from bs4 import BeautifulSoup

get_ip_url = 'http://icanhazip.com/'
get_ip_time: str = str() # 更新ip时间
ip: str = str()
get_weather_time: str = str()
weather: list = list()
max_height = 5 # 屏幕显示的最大行数
sleep_time = 5 # 隔多少秒切换一次屏幕,最低值为1,建议3以上。

# Raspberry Pi hardware SPI config:
DC = 23
RST = 24
SPI_PORT = 0
SPI_DEVICE = 0


def get_my_ip() -> str:
"""
每天更新一次公网IP地址
:return:
"""
global get_ip_time, ip
today_date = time.strftime("%y-%m-%d", time.localtime())
if today_date == get_ip_time or get_ip_time != "":
return str(ip)
else:
get_ip_time = today_date
ip = BeautifulSoup(requests.get(get_ip_url).content, "html.parser", from_encoding='gbk')
return str(ip)


def get_weather() -> list:
"""
每小时更新一次天气情况
:return:
"""
global get_weather_time, weather

now_hour: str = time.strftime("%y-%m-%d %H", time.localtime())
if now_hour == get_weather_time or get_weather_time != "": # 查看天气更新没有
return weather
else:
tmp, pm25, pm10 = my_weather.main() # 温度, pm2.5, pm10
text = 'TEMP:%s' % tmp
pm25_text = 'PM2.5:%s' % pm25
pm10_text = 'PM10:%s' % pm10
current_weather = list([str(text), str(pm25_text), str(pm10_text)])

get_weather_time = now_hour
weather = current_weather
return weather


def split_content(content) -> list:
"""
5110只能显示五行数据,如果超过六行,做分割
:param content:
:return:
"""
temp_list = list()
if len(content) > max_height:
i = 1
while i < len(content):
temp: list = list([content[0]]) # 先把时间append
while len(temp) < max_height and i < len(content):
temp.append(content[i])
i = i + 1
temp_list.append(temp)
else:
temp_list.append(content)
return temp_list


def draw_text(wait_to_draw_content):
# Hardware SPI usage:
disp = LCD.PCD8544(DC, RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=4000000))
# Initialize library.
disp.begin(contrast=60)

# Clear display.
disp.clear()
disp.display()

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.

image = Image.new('1', (LCD.LCDWIDTH, LCD.LCDHEIGHT))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a white filled box to clear the image.
draw.rectangle((0, 0, LCD.LCDWIDTH, LCD.LCDHEIGHT), outline=255, fill=255)

# Load default font.
font = ImageFont.load_default()

for each in wait_to_draw_content:
text = each
# 根据传进来的字符串进行x轴的确定, 5110宽84 高48, 一个字符宽6个像素点
x_pos = 42 - (len(text) * 6 / 2)
if x_pos < 0:
x_pos = 0

# 一共传进来几个数据就依次从中间开始显示
y_base = int((6 - len(wait_to_draw_content)) / 2)
# y_pos = y_base * 8 + draw_content.index(each) * 8 - 8
y_pos = 8 * (y_base + wait_to_draw_content.index(each))

draw.text((x_pos, y_pos), text, font=font)

# Display image.
disp.image(image)
disp.display()


if __name__ == '__main__':
try:
while True:
now_time = time.strftime("%y-%m-%d %H:%M", time.localtime())
draw_content = [now_time, str(get_my_ip())]

now_weather = get_weather()
draw_content.extend(now_weather)

pi_info: list = pi.main(all=True) # 返回CPU温度和使用率
draw_content.extend(pi_info)

draw_content = split_content(draw_content)
for each in draw_content:
draw_text(each) # 注意消息不要超过六条
time.sleep(sleep_time)
except KeyboardInterrupt as e:
print("exit...")

这是经过我简化的代码,但是所有的必要功能都在。

获取树莓派状态信息

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
# filename: pi.py
# -*- coding: utf-8 -*-
# 读取树莓派信息
import os


# Return CPU temperature as a character string
def getCPUtemperature():
res = os.popen('/usr/bin/vcgencmd measure_temp').readline()
return res.replace("temp=", "").replace("'C\n", "")

# Return % of CPU used by user as a character string
def getCPUuse():
return str(os.popen(r"/usr/bin/top -n 1 -b| /usr/bin/awk '/Cpu\(s\):/ {print $2}'").readline().strip())


# Return RAM information (unit=kb) in a list
# Index 0: total RAM
# Index 1: used RAM
# Index 2: free RAM
def getRAMinfo():
p = os.popen('free')
i = 0
while 1:
i = i + 1
line = p.readline()
if i == 2:
return line.split()[1:4]


# Return information about disk space as a list (unit included)
# Index 0: total disk space
# Index 1: used disk space
# Index 2: remaining disk space
# Index 3: percentage of disk used
def getDiskSpace():
p = os.popen("df -h /")
i = 0
while 1:
i = i + 1
line = p.readline()
if i == 2:
return line.split()[1:5]


def main(all=False, cpu=True, ram=False, disk=False) -> list:
pi = list()
if all:
cpu = True
ram = True
disk = True
if cpu:
CPU_temp = getCPUtemperature()
CPU_usage = getCPUuse()
cpu_tmp = 'CPU TMP:%s' % CPU_temp
cpu_usg = 'CPU USE:%s' % CPU_usage
# pi = list([str(cpu_tmp), str(cpu_usg)])
pi.append(str(cpu_tmp))
pi.append(str(cpu_usg))
if ram:
RAM_stats = getRAMinfo()
RAM_total = round(int(RAM_stats[0]) / 1000, 1)
RAM_used = round(int(RAM_stats[1]) / 1000, 1)
RAM_free = round(int(RAM_stats[2]) / 1000, 1)
RAM_total = 'RAM|All:' + str(RAM_total)
RAM_used = 'RAM|Used:' + str(RAM_used)
RAM_free = 'RAM|Free:' + str(RAM_free)
pi.append(RAM_total)
pi.append(RAM_used)
pi.append(RAM_free)
if disk:
# Disk information
DISK_stats = getDiskSpace()
DISK_total = DISK_stats[0]
DISK_used = DISK_stats[1]
DISK_perc = DISK_stats[3]
DISK_total = 'DISK|Size:' + str(DISK_total)
DISK_used = 'DISK|Used:' + str(DISK_used)
DISK_perc = 'DISK|Used:' + str(DISK_perc)
pi.append(DISK_total)
pi.append(DISK_used)
pi.append(DISK_perc)
return pi

这个文件主要获取树莓派的CPU、RAM、磁盘的信息。

天气获取

注意:这个文件需要你的 api key,具体可以在 https://console.heweather.com/my/service 申请,同时需要你填入自己的所在地。需要填的项目都用星号表示了

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
# filename: my_weather.py
# -*- coding: utf-8 -*-
import json
import requests
from bs4 import BeautifulSoup

# ---------基本信息-------------------
# key在网站上获取:https://console.heweather.com/my/service
key = "key=**************" # 填入自己的key
locate = "location=****" # 填入自己的地址,可以具体到区
Regular_weather_data = 'https://free-api.heweather.com/s6/weather?' # 常规天气数据集合


# 根据接口查询
def weather_url(weather_api):
url = weather_api + locate + "&" + key
return url


def get_raw_data(url):
data = requests.get(url)
soup = BeautifulSoup(data.content, "html.parser", from_encoding='utf-8')
soup = str(soup)
json_data = json.loads(soup)
return json_data


def LiveWeather(data):
now_cond = data['HeWeather6'][0]['now']['cond_txt'] # 天气:阴,晴
Sensible_temperature = data['HeWeather6'][0]['now']['fl'] # 体感温度
tmp = data['HeWeather6'][0]['now']['tmp'] # 温度
vis = data['HeWeather6'][0]['now']['vis'] # 能见度
update_time = data['HeWeather6'][0]['update']['loc'] # 更新时间
dress_suggestion_brf = data['HeWeather6'][0]['lifestyle'][1]['brf'] # 生活指数简介
dress_suggestion_description = data['HeWeather6'][0]['lifestyle'][1]['txt'] # 生活指数详细描述
return tmp


def air_quality(data):
aqi = data['HeWeather6'][0]['air_now_station'][0]['aqi'] # 空气质量指数
qlty = data['HeWeather6'][0]['air_now_station'][0]['qlty'] # 空气质量
co = data['HeWeather6'][0]['air_now_station'][0]['co'] # CO
pm25 = data['HeWeather6'][0]['air_now_station'][0]['pm25']
pm10 = data['HeWeather6'][0]['air_now_station'][0]['pm10']
main = data['HeWeather6'][0]['air_now_station'][0]['main'] # 主要污染物
air_sta = data['HeWeather6'][0]['air_now_station'][0]['air_sta'] # 观测站
pub_time = data['HeWeather6'][0]['air_now_station'][0]['pub_time']

return pm25, pm10


def main():
# -------常用数据-------------
url = weather_url(Regular_weather_data)
data = get_raw_data(url)
# --------空气质量------------
ac_url = 'https://free-api.heweather.com/s6/air/now?location=beijing&' + key # 把北京改为你的城市
ac_data = get_raw_data(ac_url)

# 实时天气及空气质量
tmp = LiveWeather(data)
pm25, pm10 = air_quality(ac_data)
return tmp, pm25, pm10

可以看到返回了很多数据,但是我只使用了tmp(温度),PM2.5,PM10三项数据,如果你有一定的python基础,可以自己修改。如果需要我帮忙修改的,可以在下面留言。

其他设置

主要的代码就是以上三个。

还需要安装依赖

1
sudo python3 -m pip install requests bs4 Adafruit_GPIO Pillow 

以及一个第一步就手动安装的包。

在所有的依赖都安装完成后,可以测试一下代码了。

1
python3 display.py

成功了就是如下图的效果。

systemctl 服务

如果测试没有问题,我们就可以把它作为服务,以后就可以开启启动了

在 display.py 文件的目录下执行

1
pwd

获得当前目录,可以看到我的是 /home/pi/Nokia5110 复制下来

继续输入

1
sudo nano /etc/systemd/system/Nokia5110.service

添加如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Unit]
Description=Nokia 5110 Display
After=network.target

[Service]
# 下面两项改为你的用户名,一般都是pi
User=pi
Group=pi

Type=simple
# 将下面两个 /home/pi/Nokia5110 改为你的地址
WorkingDirectory=/home/pi/Nokia5110
ExecStart=/usr/bin/python3 /home/pi/Nokia5110/display.py
Restart=on-failure

[Install]
WantedBy=multi-user.target

如果不放心配置是否正确,可以在shell中执行

1
/usr/bin/python3 /home/pi/Nokia5110/display.py

看看是否显示成功。

如果提示 -bash: /usr/bin/python3: 没有那个文件或目录 有可能是你没有安装python3或者python3的执行文件不在/usr/bin/python3。

如果是第二种情况(输入python3可以执行,/usr/bin/python3却不能执行的情况)可以输入

1
which python3

然后将 /usr/bin/python3 替换为 输出的结果即可。


输入 ctrl + o 保存 ctrl + x 退出。

依次执行:

1
2
3
4
sudo systemctl daemon-reload
sudo systemctl enable Nokia5110.service
sudo systemctl start Nokia5110
sudo systemctl status Nokia5110

如果是如上结果,并且屏幕正常显示,说明没有问题了。

到此,所有的设置结束。

代码下载

点击下载