树莓派Zero电子墨水屏状态监控:硬件连接、驱动配置与Python脚本实现 1. 项目缘起为什么我们需要一个物理状态看板在智能家居、家庭实验室或者小型服务器集群的管理中我们常常需要监控一些关键信息树莓派的CPU温度、内存使用率、网络连接状态或者某个关键服务的运行状态。通常我们会通过SSH登录查看或者打开一个网页仪表盘。但这种方式总感觉隔了一层不够直观也缺乏一点“掌控感”。想象一下如果有一个像机场航班信息屏一样的小设备静静地放在桌角实时、无声地告诉你所有系统的健康状况那该多酷。这正是PiHut Status Board和PiSquare组合能带来的体验。PiHut Status Board是一款小巧的电子墨水屏e-ink模块以其低功耗、高可视性和类纸质感著称非常适合用来显示静态或低频更新的信息。而PiSquare则是为树莓派Zero/Zero 2 W量身打造的“帽子”HAT它最大的特点是提供了一个标准、优雅的40针GPIO接口扩展方式让为Zero系列添加各种外设变得整洁而简单。这个项目的核心就是将Status Board这块精致的墨水屏通过PiSquare这个“桥梁”稳稳地连接到树莓派Zero上打造一个专属的、离线可用的硬件状态监控终端。它不依赖网络浏览器开机即显示功耗极低甚至可以由电池长时间供电成为一个真正“物理化”的系统仪表盘。接下来我将详细拆解从硬件组装、驱动配置到软件定制的全过程并分享我在这个过程中趟过的坑和收获的技巧。2. 硬件准备与组装当Status Board遇上PiSquare工欲善其事必先利其器。正确的硬件连接是项目成功的第一步。我们需要理解各个组件之间的接口逻辑而不仅仅是机械地插拔。2.1 核心组件清单与接口解析首先明确我们需要的所有硬件树莓派 Zero 2 W推荐使用Zero 2 W因为其性能比初代Zero强得多能更流畅地运行驱动和生成显示内容。初代Zero也可用但在刷新复杂图像时可能稍慢。PiSquare这是一块扩展板其底部有排母可以插入树莓派Zero的40针GPIO排针。PiSquare板子的顶部则提供了另一组40针的排母并且将GPIO、电源等引脚清晰地标注了出来。它的核心价值在于“抬升”和“规整”了接口。PiHut Status Board这是一块2.13英寸的电子墨水屏模块通常为250x122像素。它本身带有一小段排线末端是一个22针的FPC柔性印刷电路连接器。22针FPC转DIP适配板这是最关键的一个小配件。Status Board的22针FPC接口无法直接连接到GPIO排针上。因此我们需要一块转换板将柔性的FPC接口转换为标准的、可以插在面包板或排母上的双列直插DIP引脚。40针2.54mm间距排线用于连接PiSquare的排母和FPC转接板的排针。螺丝与铜柱可选但推荐用于固定树莓派、PiSquare和Status Board形成一个稳固的整体避免因排线松动导致接触不良。接口的逻辑关系是这样的Status Board (FPC) - FPC转DIP适配板 - 40针排线 - PiSquare - 树莓派Zero 2 W。电力、数据和信号通过这一链路传输。2.2 分步组装与关键注意事项组装过程需要耐心和细致错误的连接可能会损坏屏幕。步骤一连接FPC排线到转接板这是最精细的一步。找到Status Board附带的FPC排线以及FPC转DIP适配板。转接板上会有一个FPC插座通常有一个黑色的翻盖锁扣。轻轻抬起锁扣使其处于打开状态。将FPC排线的金色触点一面朝向转接板上通常标有“元件面”或图示的一侧具体请参考转接板说明书通常触点朝下。将排线平稳地插入插座底部确保完全插入且没有歪斜。压下黑色锁扣听到轻微的“咔哒”声或感觉锁紧即可。切勿用力过猛这个锁扣非常脆弱。注意在操作FPC排线时尽量避免用手直接触碰金色触点以免汗渍导致氧化。如果不确定方向可以对比Status Board屏幕驱动芯片和转接板上的芯片方向通常需要使两边的芯片位于同一侧。步骤二将转接板安装到排线上FPC转DIP适配板另一侧是两排标准的2.54mm间距排针。取一根40针的排线将其一端公头小心地插到转接板的排针上。确保排线的第1针通常有线缆标记如红色或黑色线与转接板上标有“1”或“VCC”的引脚对齐。如果转接板没有明确标记你需要查阅其原理图或商品描述找到VCC引脚位置。步骤三将PiSquare安装到树莓派上将PiSquare底部的排母对准树莓派Zero 2 W上的40针GPIO排针垂直均匀用力按下确保完全贴合。此时PiSquare就像一顶“帽子”戴在了树莓派上并通过其顶部的排母提供了新的、规整的GPIO接口。步骤四连接排线到PiSquare现在将排线的另一端也是公头插入PiSquare顶部的40针排母中。这是连接的关键引脚对应必须正确。Status Board以常见的GDEH0213B73型号为例通常需要以下主要引脚连接VCC-3.3V(物理引脚1或17)GND-GND(物理引脚6, 9, 14, 20, 25, 30, 34, 39等)DIN-GPIO10 (MOSI)(物理引脚19)CLK-GPIO11 (SCLK)(物理引脚23)CS-GPIO8 (CE0)(物理引脚24)DC-GPIO24(物理引脚18)RST-GPIO25(物理引脚22)BUSY-GPIO23(物理引脚16)你需要根据FPC转接板的引脚定义将上述信号线对应连接到PiSquare也就是树莓派的相应GPIO引脚上。最可靠的方法是使用万用表的导通档从转接板的每个引脚开始追踪到排线的具体针脚再确认该针脚在PiSquare排母上的位置。如果排线是单色所有线一样的这个过程至关重要。如果排线是彩色的通常红色是VCC黑色是GND其他颜色需要你根据卖家提供的线序图或自行测试确定。步骤五固定与供电连接无误后可以先使用树莓派的Micro USB口供电进行测试。为了长期使用建议使用M2.5规格的螺丝和铜柱将树莓派、PiSquare和Status Board通过转接板上的安装孔固定在一起形成一个坚固的三明治结构。这能有效防止搬运或震动导致的连接问题。3. 软件驱动配置让系统识别你的墨水屏硬件连接妥当后我们需要在树莓派操作系统上安装驱动让系统能够控制这块特殊的显示屏。这里我们通常使用Waveshare微雪提供的通用驱动库因为很多小型e-ink屏都使用了类似的控制器。3.1 系统准备与SPI接口启用首先确保你的树莓派Zero 2 W已经安装了最新的Raspberry Pi OSBullseye或Bookworm版本并完成了基本的网络和SSH配置。电子墨水屏通常通过SPI接口与树莓派通信。SPI在树莓派上默认是关闭的需要手动开启。通过SSH登录到你的树莓派。运行配置工具sudo raspi-config使用方向键选择Interface Options-SPI-Yes来启用SPI接口。完成后选择Finish并建议重启系统sudo reboot重启后你可以验证SPI是否启用lsmod | grep spi如果看到spi_bcm2835相关的输出说明SPI驱动已加载。3.2 安装驱动库与基础测试我们使用Python来进行控制因此需要安装相关的库。# 更新软件包列表 sudo apt update sudo apt upgrade -y # 安装Python3及pip如果尚未安装 sudo apt install python3-pip -y # 安装必要的系统库 sudo apt install libopenjp2-7 libtiff5 -y # 使用pip安装waveshare的e-ink驱动库 # 注意直接pip安装的可能是最新版如果遇到问题可以尝试指定版本或从GitHub安装 sudo pip3 install waveshare-epd安装完成后我们需要确认屏幕的具体型号。PiHut Status Board通常使用GDEH0213B73这款2.13英寸屏幕。你可以在屏幕背面的标签或产品说明书上找到型号。然后前往Waveshare的GitHub仓库找到对应的示例程序。# 克隆示例代码仓库较大包含所有屏幕型号的示例 git clone https://github.com/waveshare/e-Paper.git cd e-Paper/RaspberryPi_JetsonNano/python在examples目录下你会看到很多以屏幕型号命名的测试文件。找到epd_2in13b_V3_test.py因为GDEH0213B73属于V3版本。在运行前必须根据你的实际接线修改代码中的GPIO引脚定义。用编辑器打开该文件nano examples/epd_2in13b_V3_test.py找到代码开头的引脚定义部分它可能看起来像这样RST_PIN 17 DC_PIN 25 CS_PIN 8 BUSY_PIN 24你需要将其修改为你在硬件连接阶段实际使用的GPIO引脚编号BCM编码即GPIO编号而非物理引脚号。根据我们之前的假设应修改为RST_PIN 25 # 对应GPIO25物理引脚22 DC_PIN 24 # 对应GPIO24物理引脚18 CS_PIN 8 # 对应GPIO8 (CE0)物理引脚24 BUSY_PIN 23 # 对应GPIO23物理引脚16务必仔细核对错误的引脚定义可能导致屏幕无反应、花屏甚至损坏。保存退出后以root权限运行测试程序因为直接操作GPIO需要权限sudo python3 examples/epd_2in13b_V3_test.py如果一切顺利你将看到屏幕依次进行清屏、显示预置图片和文字的过程。这个测试验证了从硬件连接到驱动库的整个链路是通的。实操心得第一次运行测试脚本时屏幕刷新可能会非常慢并且会经历多次全屏闪烁黑变白白变黑这是电子墨水屏正常的工作波形过程用于清除残影请勿担心。如果屏幕毫无反应首先检查电源用万用表量转接板VCC和GND之间是否有3.3V然后检查SPI是否启用最后逐条检查GPIO引脚定义。4. 定制状态显示内容从系统信息到个性仪表盘驱动跑通后我们就进入了最有趣的部分让这块屏幕显示我们想要的信息。我们将编写一个Python脚本定期收集系统状态并将其绘制到屏幕上。4.1 设计显示布局与信息元素对于一块250x122像素的小屏幕信息布局需要精打细算。一个典型的状态板可能包含以下信息标题栏固定显示设备名称或“系统状态”等标题。IP地址树莓派在当前网络中的IP对于SSH连接非常有用。CPU使用率以百分比和进度条形式显示。内存使用率显示已用内存和总内存以及使用百分比。存储使用率根目录的使用情况。CPU温度树莓派的SOC温度。系统运行时间自上次启动以来的运行时间。当前时间简单的日期和时间显示。我们可以将屏幕分为几个区域来放置这些信息。由于屏幕是黑白的或黑白红三色如果是有红色版本的屏幕我们可以用黑色表示文字和图形用红色如果支持来高亮警告信息如高温、高使用率。4.2 编写状态收集与绘图脚本我们将创建一个新的Python脚本例如status_display.py。这个脚本需要做以下几件事导入必要的库epd2in13b_V3屏幕驱动、PIL图像处理、psutil系统信息、datetime、socket等。初始化屏幕对象。进入一个主循环在每次循环中 a. 创建一个新的图像缓冲区黑图像和红图像。 b. 使用PIL.ImageDraw在缓冲区上绘制文本和图形。 c. 调用屏幕驱动的方法将缓冲区显示到屏幕上。 d. 休眠一段时间例如60秒然后刷新。以下是脚本的核心部分示例#!/usr/bin/env python3 # -*- coding:utf-8 -*- import epd2in13b_V3 from PIL import Image, ImageDraw, ImageFont import psutil import datetime import socket import time import os # 初始化屏幕 epd epd2in13b_V3.EPD() epd.init() epd.Clear() # 准备字体使用系统自带字体或指定路径的字体文件 # 小屏幕需要小字号字体 font_small ImageFont.truetype(/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf, 12) font_large ImageFont.truetype(/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf, 14) def get_ip_address(): 获取本机IP地址排除回环地址 try: s socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect((8.8.8.8, 80)) ip s.getsockname()[0] s.close() return ip except Exception: return N/A def draw_progress_bar(draw, x, y, width, height, percentage, color0): 绘制一个简单的进度条 # 绘制边框 draw.rectangle((x, y, xwidth, yheight), outlinecolor) # 计算填充宽度 fill_width int((width - 2) * percentage / 100.0) # 绘制填充部分留1像素边距 draw.rectangle((x1, y1, x1fill_width, yheight-1), fillcolor) while True: try: # 创建两个图像缓冲区一个用于黑色内容一个用于红色内容 HBlackImage Image.new(1, (epd.height, epd.width), 255) # 255: clear the frame HRedImage Image.new(1, (epd.height, epd.width), 255) draw_black ImageDraw.Draw(HBlackImage) draw_red ImageDraw.Draw(HRedImage) y_offset 2 # 1. 绘制标题 draw_black.text((2, y_offset), PiZero2 Status, fontfont_large, fill0) y_offset 18 # 2. IP地址 ip get_ip_address() draw_black.text((2, y_offset), fIP: {ip}, fontfont_small, fill0) y_offset 16 # 3. CPU使用率 cpu_percent psutil.cpu_percent(interval0.5) draw_black.text((2, y_offset), fCPU: {cpu_percent:5.1f}%, fontfont_small, fill0) draw_progress_bar(draw_black, 70, y_offset2, 100, 10, cpu_percent) y_offset 16 # 4. 内存使用率 mem psutil.virtual_memory() mem_percent mem.percent draw_black.text((2, y_offset), fMEM: {mem_percent:5.1f}%, fontfont_small, fill0) draw_progress_bar(draw_black, 70, y_offset2, 100, 10, mem_percent) draw_black.text((2, y_offset12), f({mem.used//1024**2}M/{mem.total//1024**2}M), fontfont_small, fill0) y_offset 28 # 5. 存储使用率 disk psutil.disk_usage(/) disk_percent disk.percent draw_black.text((2, y_offset), fDISK: {disk_percent:5.1f}%, fontfont_small, fill0) draw_progress_bar(draw_black, 70, y_offset2, 100, 10, disk_percent) y_offset 16 # 6. CPU温度 try: temp psutil.sensors_temperatures().get(cpu_thermal, [None])[0] if temp: cpu_temp temp.current # 如果温度过高用红色显示 if cpu_temp 70: draw_red.text((2, y_offset), fTEMP: {cpu_temp:4.1f}C, fontfont_small, fill0) else: draw_black.text((2, y_offset), fTEMP: {cpu_temp:4.1f}C, fontfont_small, fill0) except: draw_black.text((2, y_offset), TEMP: N/A, fontfont_small, fill0) y_offset 16 # 7. 运行时间 uptime_seconds time.time() - psutil.boot_time() uptime_str str(datetime.timedelta(secondsint(uptime_seconds))) draw_black.text((2, y_offset), fUP: {uptime_str}, fontfont_small, fill0) y_offset 16 # 8. 当前时间 current_time datetime.datetime.now().strftime(%Y-%m-%d %H:%M) draw_black.text((2, y_offset), current_time, fontfont_small, fill0) # 将图像旋转90度以适应屏幕方向根据你的安装方向调整 HBlackImage HBlackImage.rotate(90, expandTrue) HRedImage HRedImage.rotate(90, expandTrue) # 显示到屏幕 epd.display(epd.getbuffer(HBlackImage), epd.getbuffer(HRedImage)) time.sleep(60) # 每60秒刷新一次 except KeyboardInterrupt: print(Exiting...) epd.sleep() # 让屏幕进入低功耗睡眠模式 exit() except Exception as e: print(fError: {e}) time.sleep(10) # 出错后等待一段时间再重试这个脚本定义了一个主循环每分钟收集一次系统信息绘制到图像缓冲区然后刷新屏幕。psutil库使得获取CPU、内存、磁盘、温度等信息变得非常简单。注意温度传感器的路径可能因树莓派型号和OS版本而异上述代码使用了psutil的通用接口如果获取失败可能需要直接读取/sys/class/thermal/thermal_zone0/temp文件。4.3 设置为系统服务实现开机自启我们不希望每次启动后都手动登录运行脚本。最好的方式是将其设置为一个系统服务systemd service。创建服务文件sudo nano /etc/systemd/system/status-board.service写入以下内容根据你的实际路径修改[Unit] DescriptionPiHut Status Board Display Service Aftermulti-user.target [Service] Typesimple Userpi WorkingDirectory/home/pi/e-Paper/RaspberryPi_JetsonNano/python ExecStart/usr/bin/python3 /home/pi/status_display.py Restarton-failure RestartSec10 [Install] WantedBymulti-user.target保存退出后启用并启动服务sudo systemctl daemon-reload sudo systemctl enable status-board.service sudo systemctl start status-board.service检查服务状态和日志sudo systemctl status status-board.service journalctl -u status-board.service -f如果服务运行正常你的Status Board现在应该已经开始周期性地显示系统状态了。重启树莓派它也会自动启动。5. 进阶优化与故障排查项目基本跑通后我们可以从稳定性、显示效果和功耗方面进行一些优化并了解常见问题的排查方法。5.1 降低刷新频率与功耗优化电子墨水屏只有在刷新时才消耗较多电量静态显示时几乎不耗电。我们的脚本每分钟刷新一次对于状态监控来说已经足够。但我们可以进一步优化动态休眠在脚本中当系统负载很低、信息变化不大时可以延长刷新间隔比如在夜间设置为5分钟一次。使用epd.sleep()在我们的脚本捕获到退出信号如KeyboardInterrupt时会调用epd.sleep()让屏幕进入深度睡眠。确保服务停止时能正确调用此函数。树莓派自身功耗考虑使用raspi-config关闭未使用的接口如HDMI、蓝牙、WiFi如果不用的话或使用tvservice -o关闭HDMI输出。5.2 改善显示效果与残影处理电子墨水屏长期显示静态图像后在刷新时可能会留下上一帧的“残影”。为了最大限度地保持显示清晰定期全刷墨水屏驱动通常提供Clear()方法用于全屏黑白刷新以清除残影。可以在每第10次或第20次正常刷新后强制进行一次epd.Clear()后再显示新内容。但要注意全刷过程较慢且屏幕会剧烈闪烁。避免局部频繁刷新尽量以完整的帧为单位进行刷新避免对屏幕局部进行高频次的写操作。图像反色如果显示的内容以深色背景为主可以考虑定期反色显示如黑变白白变黑利用完整的刷新周期来清除残影。我们的驱动库显示时已经包含了必要的清除波形。5.3 常见问题与排查指南屏幕一片空白无任何显示检查电源用万用表测量转接板VCC和GND之间是否有稳定的3.3V电压。树莓派GPIO的3.3V引脚输出能力有限确保没有短路。检查SPI确认raspi-config中SPI已启用且lsmod | grep spi有输出。检查引脚定义这是最常见的问题。再次用万用表逐线核对FPC转接板到树莓派GPIO的每一根连接线确保VCC、GND、DIN、CLK、CS、DC、RST、BUSY一一对应。特别注意GPIO编号BCM与物理引脚编号的区别。检查屏幕型号确认驱动代码中初始化的屏幕型号如epd2in13b_V3.EPD()与实际屏幕完全一致。屏幕有显示但内容错乱、花屏或只有部分显示图像方向确认在调用epd.display()前对HBlackImage和HRedImage做了正确的旋转rotate。屏幕的物理坐标系可能与你的预期不同。缓冲区大小创建Image对象时尺寸是(epd.height, epd.width)注意高和宽的顺序。显示时又旋转了90度这需要根据你的绘图逻辑来调整。接线虚焊或接触不良特别是FPC排线和杜邦线连接处轻轻按压或重新插拔试试。这也是为什么强调要用螺丝固定。脚本运行报错提示找不到模块或权限错误模块未安装确保在正确的Python环境下用pip3安装了waveshare-epd和PillowPIL、psutil。权限问题操作GPIO需要root权限。确保测试时使用sudo或者将运行脚本的用户如pi加入gpio用户组sudo usermod -a -G gpio pi。但最省事的方式还是用sudo运行或配置systemd服务。屏幕刷新异常缓慢或刷新后残影严重这是正常现象电子墨水屏的刷新速度尤其是全刷就是比较慢V3版本可能也需要2-3秒。残影是e-ink技术特性通过定期全刷可以缓解。检查BUSY引脚驱动库依赖BUSY引脚来判断屏幕是否忙。确保BUSY引脚接线正确并且代码中对应的引脚号正确。如果BUSY信号没被正确读取库可能会在屏幕忙时强行发送数据导致显示异常。这个项目将精致的PiHut Status Board与便捷的PiSquare结合为树莓派Zero打造了一个极具实用性和观赏性的物理状态监视器。整个过程涉及了硬件接口、底层驱动、系统信息获取和自动化部署是一个综合性很强的嵌入式小项目。最关键也最耗时的部分往往是硬件连接和引脚定义的确认耐心和细致的排查在这里至关重要。当看到自定义的系统信息稳定地显示在那块类纸质的屏幕上时所有的调试都是值得的。你可以在此基础上继续扩展比如增加显示天气预报、待办事项、日历事件甚至连接到Home Assistant显示智能家居状态让它成为一个真正的信息中枢。