一、起因
很早之前在社交媒体上看到过一个帖子,大概的意思是:在公司会议室门上,挂了一个电子墨水屏,可以实时显示这个会议室的日程安排。
看到之后感觉非常有趣,当时没有什么开发经验,所以只留下一点小印象。后来,慢慢熟悉了Python语言、了解了企业微信的开发文档,隐隐觉得我自己可以把这个产品模拟出来。
断断续续做了些准备工作,6、7月份开始花比较多的时间在这个上面,最近终于比较完美的解决了所有问题。
二、效果
话不多少,我们先来看看实际效果:
- 模拟那篇帖子的效果,实时显示某个会议室的日程安排。

- 显示一张黑白图片。

- 显示一段文字。

三、硬件材料及其架构
1、主控ESP32
主控使用的是ESP32,本来想使用更便宜的ESP8266,但是8266的内存实在太小,带不动4.2寸的墨水屏。所以被迫采用了ESP3,单个价格大概是30元左右。
如果使用树莓派、香橙派之类的设备,应该可以减少点业务复杂度,但是价格会更高。
2、4.2寸电子墨水屏
电子墨水屏的价格蛮高的,微雪4.2寸的电子墨水屏价格大概是130元左右。通过万能某宝,找到了单个15元左右的杂牌墨水屏。为什么这么便宜?因为这些屏是二手的,它们可能在某个超市已经默默服役了好多年。先买了两个,结果在拆屏的时候都拆坏了,最后还是直接简单用切割机把排线位置切开,保证可以把排线拉出来就可以了。
3、电子墨水屏驱动板
电子墨水屏的接口是24PIN的排线,ESP32上并没有这样的接口,所以需要一个「驱动板」桥接,一个驱动板大概5元左右。
4、3D打印外壳
以上都是一些散件,把散件连接起来看起来不像是一个产品,所以3D打印了一个外壳,把零件都放在壳子里,看起来就完美多了。
四、熟悉ESP32和MicroPython
ESP8266是一种常见且便宜的单片机,而ESP32是它的升级版,有更多的内存空间。单片机开发,一般都会使用Arduino的开发环境,但是因为我没有相关的知识储备,所以采用了MicroPython的开发环境。
MicroPython是一种简化版的Python,可以运行在单片机上。当运行在单片机上时,MicroPython既是一种开发语言,也是这个单片机的OS。
在这个过程中:
- 学习了解了如何使用Thonny软件、使用Mac命令行给单片机刷写MicroPython固件系统。如何给单片机连接WIFI网络、同步时间。如何让单片机开启热点模式,让其他设备连接后进行配网和文件管理。如何在单片机上发起HTTP请求,获取网络上的资源,在这个过程中解决了中文编码的问题。
五、SPI协议驱动电子墨水屏
适用于单片机的显示设备不仅有电子墨水屏,更常见的其实是OLED屏、LCD屏。而单片机驱动这些屏幕的协议,常见的有SPI和I2C。因为了解到这一款电子墨水屏支持的是SPI协议,所以首先熟悉了SPI协议。
SPI协议一般来说只需要三个接口,分别是SCK接口、MOSI接口、MSIO接口。
- SCK,也叫SCL,是SPI时钟引脚。MOSI,也叫SDA、DIN,是SPI数据发送引脚。MISO,是SPI数据输入脚,一般屏幕只是输出设备,这个接口是可以不接的。
SPI分为硬件SPI和软件SPI,硬件SPI是指三个接口使用单片机上固定的PIN引脚,软件SPI是三个接口只需要普通的PIN引脚。
根据官方文档ESP32的硬件SPI的引脚分别是:SCK使用的是PIN14引脚,MOSI使用的是PIN13引脚,MISO不需要接。同时baudrate参数,从80000000调整到10000000。代码如下:
hspi = SPI(1, baudrate=10000000,sck=Pin(14), mosi=Pin(13), miso=Pin(12))
SPI只是一种驱动协议,想要真正驱动起来,还需要使用显示屏对应的驱动程序。某宝上淘的这个电子墨水屏没有任何资料,但是根据评论知道其兼容微雪的屏幕驱动。经过一番寻找之后,终于找到了Python版本的驱动。这个过程也遇到了一些坑,比如:
- 驱动程序中,BUSY = const(0),需要改为 BUSY = const(1),不然系统会认为BUSY一直处于繁忙状态,不做任何的驱动工作。要熟悉MicroPython自带的framebuf库。这个库,会在单片上开辟一块内存缓存区,可以通过程序向这个区域写入内容,然后最后一次性同步到屏幕中。framebuf可以绘制点、线、矩形、圆形、英文字符等,但是不能显示中文,也不能改变英文字符的字体大小。
七、显示中文/图片
「显示中文内容」是整个项目花费时间最长的环节,经过长时间的折腾,最终理解了其中的大概原理,并且实现了效果。
4.2寸的墨水屏,其实就是宽400高300像素的像素矩阵,总共有120000的像素点,通过控制每个像素点为0或1的值,分别代表黑白两种颜色。 因为framebuf只能绘制点、线、矩形、圆形、英文,而且还不能调整英文字体大小,所以其他方案,都是需要把文字转成其他形式的像素点阵图。
1、使用取模软件生成每个字的像素矩阵
通过「PCtoLCD」软件生成3000多个常用汉字、字符的像素点阵图,制作成配置文件,需要用哪一个字时,在这个配置文件中进行检索。
这种方法,需要针对每个汉字、每个字体、每个字号,都需要生成一套配置文件,会导致这个配置文件特别大,大到ESP32都无法处理这样的配置文件。
所以,最终解决方法是,把这个配置文件放在云端,设备需要用到哪些文字,发起一个HTTP请求,从云端进行获取之后,再显示在墨水屏上。

2、将所有显示内容生成一整张图片的点阵图
将要展示的内容,通过PIL图片处理工具生成图片,再把整张图片转为像素点阵图。这种方法,生成的效果要明显好于前面一种的效果 (对比上下图,字体显示要平滑很多),但是ESP32安装的MicroPython不支持PIL库。
解决方案同样是,把PIL图片处理程序放在云端进行,ESP32只需要把需要显示的文字、位置、大小发送给云端,云端处理之后将数据同步回传给ESP32。为了减少回传数据的大小,还需要继续压缩回传的数据。这个过程大概是:
首先,将黑白图片的每个像素点,生成一个400乘300的嵌套列表,每个元素的值只有0(黑色)和1(白色)。
其次,可以把每8个值合并为一个bit,然后生成一个二进制数据嵌套列表,这个时候返回数据的大小就变为了50乘300。
第三,把这个二进制的嵌套列表,做16进制的编码,进一步降低了其长度。
最后,在ESP32通过HTTP请求获取到数据后,进行反向计算即可还原数据,并显示图片。
八、其他问题
1、函数计算
以上两种方法都利用了云端计算的能力,但是为此买服务器搭建服务也很麻烦。这个时候,我们可以使用云服务商提供的「函数计算」能力。
「函数计算」可以将Python、NodeJS等语言的脚本在线化,并提供一个HTTP的触发器。在客户端只需要发起一个HTTP的请求,就可以触发调用这段脚本,实现想要的效果。
2、3D打印外壳
测试阶段,开发版、驱动板、墨水屏都是通过杜邦线简单相连。原型走通后,就要考虑整个成品的外观问题。在这个环节,乘机购入了一台拓竹A1 mini的3D打印机,并简单学习了3D设计,给这套产品设计了一个外壳。最终成品如下:


九、总结
以上从产生想法到最终实现,断断续续持续了很长时间。有时候遇到一些没有头绪的问题,就会搁置一段时间,比如电子墨水屏的驱动问题、显示中文的问题。但是心中就一直有一个“挂念”,好在重整思绪后最终都得以解决。
最后一个问题,很多人可能会问:这个有啥有用?我只能说,好玩!