一直想有一个电子墨水屏作为桌面提示器,显示一些信息提示。没有现成的产品,那么就想自己做一个。

用树莓派 Zero W 外接微雪的三色电子墨水屏制作一个小型的桌面提示器。

直接买微雪 2.13 寸带驱动板三色显示屏,这款直接接上树莓派就可以用了。我买的树莓派 Zero W 没有排针,所以我还买了电烙铁给板子焊上排针。然后接上就屏幕驱动板就可以直接用了。


驱动安装

微雪官网的『RPI使用教程』就有显示屏的驱动和使用方式,照着说明安装就可以了。

驱动方式有 C 和 Python 两种,我不懂 C,只能用 Python,而且 Python 用起来比 C 方便很多。

我买这块显示屏型号是 EPD_2in13bc_test(),安装好驱动和库之后运行对应的文件。

sudo python3 ~/e-Paper/RaspberryPi\&JetsonNano/python/examples/epd_2in13bc_test.py

显示屏测试启动。怎么编程其实在这个文件里全部都给出来了,相当简单。


使用例子

我按着这个文件做了两个例子,一个是直接显示三色图案,一个是获取树莓派的信息再生成图片显示。你可以直接下载我的 Demo 文件然后放到 Python 文件夹对应的文件夹中。

~/e-Paper/RaspberryPi\&JetsonNano/python/

Python 的使用方式就是使用 Image 模块分别引用或者生成两个黑色和黄色两个图层图片再分别刷新。


图片显示

树莓派 Zero W 使用微雪电子墨水屏

想要显示图片的时候注意的是,图片需要拆分黑色通道和黄色通道各一张单色图片,而且刷新时候的逻辑是黑色通道先刷新,黄色通道后刷新,而黄色通道会覆盖黑色通道,所以你需要再黄色通道图片上镂空黑色通道的图案。也就是我文件里的 epd_2in13bc_imgs.py

#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys
import os
picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic')
libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')
if os.path.exists(libdir):
    sys.path.append(libdir)
import logging
from waveshare_epd import epd2in13bc
import time
from PIL import Image,ImageFont,ImageChops
import traceback
logging.basicConfig(level=logging.DEBUG)
try:
    logging.info("epd2in13_V2 Demo")
    epd = epd2in13bc.EPD()
    logging.info("init and Clear")
    # 初始化
    epd.init()
    # 清空屏幕
    epd.Clear()
    logging.info("1.Drawing on the image...")
    # 黑白图,先刷新
    HBlackimage = Image.open(os.path.join(picdir, 'gw_b.bmp'))
    # 黄色部分,后刷新,黄色会覆盖黑色
    HRYimage = Image.open(os.path.join(picdir, 'gw_y.bmp'))
    # 旋转180度,根据自己设备方向调整,90,180,270
    HBlackimage = HBlackimage.transpose(Image.ROTATE_180)
    HRYimage = HRYimage.transpose(Image.ROTATE_180)
    # def display(self, 黑白图像, 黄色图像)
    epd.display(epd.getbuffer(HBlackimage), epd.getbuffer(HRYimage))
    # 休眠
    time.sleep(2)
        
except IOError as e:
    logging.info(e)
    
except KeyboardInterrupt:    
    logging.info("ctrl + c:")
    epd2in13bc.epdconfig.module_exit()
    exit()

而且两个通道图片的模式必须一样的,例如:我给的 Demo 图片就是两张图片都是灰度模式的就是只有黑白灰的颜色,没有彩色。而一般图片都是 RGB 模式的。

还有就是通过 Image 生成图片的时候也要根据你背景图的色彩模式设置,要不然就会报错了!


信息显示

动态生成黑色文字的时候就需要用运算的方式在黄色通道上删除黑色通道部分的内容了。 我的压缩包中的 epd_2in13bc_demo.py

#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys
import os
picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic')
libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')
if os.path.exists(libdir):
    sys.path.append(libdir)
import logging
from waveshare_epd import epd2in13bc
import time
from PIL import Image, ImageDraw, ImageFont, ImageChops
import traceback
# 获取时间
NowTime = time.strftime('%Y-%m-%d %H:%M:%S',  time.localtime(time.time()));
# 内网 IP
import socket
hostName = socket.gethostname()
def get_host_ip():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    finally:
        s.close()
    return ip
# 外网 IP, sudo pip3 install requests
import json
import requests
wan_ip = requests.get('https://api.ipify.org/?format=json').json()['ip']
# 输出日志等级
logging.basicConfig(level=logging.DEBUG)
try:
    logging.info("1.read bmp file And Text")
    # 初始化
    epd = epd2in13bc.EPD()
    logging.info("init and Clear")
    epd.init()
    epd.Clear()
    # 载入字体,Zipx 这款字体 12/24/36/40 这几个字号能看,其他的都粗细不一
    # higher = ImageFont.truetype(os.path.join(picdir, 'higher_8.ttf'), 14)
    # zipx12 = ImageFont.truetype(os.path.join(picdir, 'zipx.ttf'), 12)
    # fz14 = ImageFont.truetype(os.path.join(picdir, 'FZXIANGSU14.otf'), 14)
    pxlxxlcond = ImageFont.truetype(os.path.join(picdir, 'pxlxxlcond.ttf'), 20)
    logging.info("1.Drawing on the image...")
    # 下层,黑白图,先刷新(白底黑字)
    HBlackimage = Image.new('1', (epd.height, epd.width), 255)  # 212*104 获取 epd 的尺寸
    drawblack = ImageDraw.Draw(HBlackimage)
    drawblack.text((12, 10), 'Host: '+hostName, font = pxlxxlcond)
    drawblack.text((12, 32), 'LAN: '+get_host_ip(), font = pxlxxlcond)
    drawblack.text((12, 54), 'WAN: '+wan_ip, font = pxlxxlcond)
    drawblack.text((12, 76), NowTime, font = pxlxxlcond)
    # 上层,黄色部分,后刷新,黄色会覆盖黑白色
    # 这个 bmp 图片必须是灰阶的,不能是 RGB 的!
    # 如果图片是 RGB 模式怎上面 Image.new('1' 改为 'RGB'
    HRYimage = Image.open(os.path.join(picdir, 'bg_boxks.bmp'))
    # 文字蒙版裁剪背景图,使用差值运算生成反色图像,然后 invert() 反色为想要的颜色。
    HRYimage = ImageChops.subtract_modulo(HBlackimage, HRYimage)
    HRYimage = ImageChops.invert(HRYimage)
    # 旋转180度,根据自己设备方向调整,90,180,270
    HBlackimage = HBlackimage.transpose(Image.ROTATE_180)
    HRYimage = HRYimage.transpose(Image.ROTATE_180)
    # 创建纯色图像,如果你想全屏幕显示黄色就用纯黑色图像代替 HRYimage
    # 如果只想显示黑白,不显示黄色就用纯白色图像代替 HRYimage
    # Whiteimage = Image.new('1', (epd.height, epd.width), 255)
    # Blackimage = Image.new('1', (epd.height, epd.width), 0)
    
    # def display(self, 黑白图像, 黄色图像)
    epd.display(epd.getbuffer(HBlackimage), epd.getbuffer(HRYimage))
    # 休眠
    time.sleep(2)
        
except IOError as e:
    logging.info(e)
    
except KeyboardInterrupt:    
    logging.info("ctrl + c:")
    epd2in13bc.epdconfig.module_exit()
    exit()

照着上面的代码修改基本就可以了,然后可以设置成开机启动,每次开机都会显示 IP 信息了。

后面我会在研究更实用的例子。