2.9inch Touch e-Paper HAT Manual
| ||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||
说明
2.9inch触控墨水屏模块
各项参数
尺寸 | 2.9英寸 |
外形尺寸 | 89.1mm × 42.7mm |
驱动板尺寸 | 79.50mm × 37.50mm |
显示尺寸 | 66.89mm × 29.05mm |
工作电压 | 3.3V / 5V(IO电平电压要和供电电压一致) |
通信接口 | SPI |
点距 | 0.227mm × 0.227mm |
分辨率 | 296 × 128 |
显示颜色 | 黑、白 |
灰度等级 | 4 |
刷新时间 | 3s |
刷新功耗 | 26.4mW(typ.) |
休眠电流 | < 0.01uA(接近0) |
触控点数 | 5(MAX) |
触摸类型 | 电容触摸 |
触摸接口 | I2C(地址:0x48) |
触摸面板 | 钢化玻璃面板 |
- 刷新时间:刷新时间为实验测试数据,实际刷新时间会有误差,以实际效果为准。全局刷新过程中会有闪烁效果,这个是正常现象。
- 刷新功耗:功耗数据为实验测试数据,实际功耗由于驱动板的存在和实际使用情况不同,会有一定误差,以实际效果为准。
注意:局刷没有四灰度显示,只有全刷有,具体参考2.9inch e-Paper Module
通信方式
工作原理
本产品使用的电子纸采用“微胶囊电泳显示”技术进行图像显示,其基本原理是悬浮在液体中的带电纳米粒子受到电场作用而产生迁移。电子纸显示屏是靠反射环境光来显示图案的,不需要背光,在环境光下,电子纸显示屏清晰可视,可视角度几乎达到了 180°。因此,电子纸显示屏非常适合阅读。
编程原理
- 对于黑白图片,我们可以规定,如果如果是黑色我们定义成0,如果是白色就定义成1,那么有了表示颜色的方式:
- 白色:□,对应1
- 黑色:■:对应0
- 白色:□,对应1
- 一个点在图形上一般称之为像素点(pixel),而颜色不是1就是0,也就是1个位就可以标识颜色:1Pixel = 1bit,那么一个字节里面就包含了8个像素点。
- 以16个像素点为例,我们假设前8个像素点为黑,后8个像素点为白色,那么可以这么认为,像素点1-16,对应这0位到15位,0表示黑色,1表示白色:
对于计算机而言,它的数据存储方式是高位在前,低位在后,且一个字节只有8个位,因此会有一点改变:
这样只需要2个字节即可表示16个像素点了。
- 下面介绍一下2.9inch e-paper的4灰阶显示(黑白2阶显示和上面的仍然是一样的)
- 首先我们需要了解4灰阶图片,它说明将最亮与最暗之间的亮度变化,区分为4份,从白色到黑色,中间多出了2中颜色,我们可以把它定义浅灰、深灰。
- 黑色:00b
- 深灰:10b
- 浅灰:01b
- 白色:11b
- 黑色:00b
- 一般计算机为了节省存储空间,一像素数据通常用两位存储,还是上面的例子,以8个像素点为例,2个像素点黑,2个像素深灰、2个像素浅灰、2个像素白色:
- 同样一张4灰度的图片可以看成2张图片叠加的,不同图片的同一个像素点叠加而成一个像素点,这个点有4种组合,也就是4灰度:
寄存器 | 白 | 浅灰 | 深灰 | 黑 |
0x24 | 0x01 | 0x00 | 0x01 | 0x00 |
0x26 | 0x01 | 0x01 | 0x00 | 0x00 |
- 上面已经知道了4灰阶与内存的关系,并且知道不同的组合对墨水屏的颜色不一致,因此需要把上述的数据进行转换:
注意事项
- 支持局刷的屏幕,注意使用的时候不能一直用局刷对屏幕进行刷新,需要在做几次局刷之后,对屏幕进行一次全刷清屏。否则会造成屏幕显示效果异常。
- 注意屏幕不能长时间上电,在屏幕不刷新的时候,要将屏幕设置成睡眠模式,或者进行断电处理。否则屏幕长时间保持高电压状态,会损坏膜片,无法修复。
- 使用墨水屏的时候,建议刷新时间间隔至少是180s, 并且至少每24小时做一次刷新,如果长期不使用墨水屏的话,要将墨水屏刷白存放。(具体储存环境需求参考数据手册)
- 屏幕进入睡眠模式之后,会忽略发送的图片数据,只有重新初始化才能正常刷新。
- 控制 0x3C 或 0x50 (具体参照数据手册)寄存器可以调节边框颜色,在例程中可以调节 Border Waveform Control 寄存器或者 VCOM AND DATA INERTVAL SETTING 进行设置。
- 如果发现制作的图片数据在屏幕上显示错误,建议检查一下图片大小设置是否正确,调换一下宽度和高度设置再试一下。
- 墨水屏的工作电压要求是 3.3V,如果您购买的是裸屏的话,设计电路的时候如果需要配合 5V 工作环境的话,建议做一下电平转换处理。新版驱动板(Rev2.1及后续版本)加入了电平处理电路,可以同时支持 3.3V 和 5V 工作环境,老版本只能支持 3.3V 工作环境,使用的时候可以先确认一下版本号(版本号在板名下)。
- 屏幕的 FPC 排线比较脆弱,请注意:不要沿屏幕垂直方向弯曲排线,避免排线被撕裂;不要反复过度弯曲排线,避免排线断裂;不要往屏幕正面方向弯曲排线,避免排线与面板的连接断开。调试研发时建议固定排线后使用。
- 墨水屏屏幕较为脆弱,注意尽量避免跌落、碰撞、用力按压。
- 我们建议客户拿到屏幕之后,先用我们提供的示例程序,使用对应的开发板进行测试。
Raspberry Pi
硬件连接
连接树莓派的时候,可以直接插到树莓派的40PIN排针上去,注意对好引脚。如果是选择用12PIN排线连接的话,请参考下方的引脚对应表格
Touch e-Paper | Raspberry Pi | |
BCM2835编码 | Board物理引脚序号 | |
VCC | 3.3V | 3.3V |
GND | GND | GND |
DIN | MOSI | 19 |
CLK | SCLK | 23 |
CS | CE0 | 24 |
DC | 25 | 22 |
ERST | 17 | 11 |
BUSY | 24 | 18 |
INT | 27 | 13 |
SCL | SCL1 | 5 |
SDA | SDA1 | 3 |
TRST | 22 | 15 |
以2.13inch Touch e-Paper HAT为例,直接插在树莓派上即可:
开启SPI接口
- 打开树莓派终端,输入以下指令进入配置界面:
sudo raspi-config 选择Interfacing Options -> SPI -> Yes 开启SPI接口
- 重启树莓派:
sudo reboot
- 检查 /boot/config.txt,可以看到 'dtparam=spi=on' 已被写入
- 为了确保 SPI 没有被占用,建议其他的驱动覆盖暂时先关闭。可以使用 ls /dev/spi* 来检查 SPI 占用情况,终端输出 /dev/spidev0.0 和 /dev/spidev0.1 表示 SPI 情况正常
开启I2C接口
- 打开树莓派终端,输入以下指令进入配置界面
sudo raspi-config 选择 Interfacing Options -> I2C ->yes 启动 i2C 内核驱动
sudo reboot
安装库
安装C语言函数库
- 安装 lg 库
#打开树莓派终端,并运行以下指令: wget https://github.com/joan2937/lg/archive/master.zip unzip master.zip cd lg-master make sudo make install # 更多的可以参考源码:https://github.com/gpiozero/lg
- 安装 gpiod 库(可选)
#打开树莓派终端,并运行以下指令: sudo apt-get update sudo apt install gpiod libgpiod-dev
- 安装 BCM2835(可选)
#打开树莓派终端,并运行以下指令: wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.71.tar.gz tar zxvf bcm2835-1.71.tar.gz cd bcm2835-1.71/ sudo ./configure && sudo make && sudo make check && sudo make install # 更多的可以参考官网:http://www.airspayce.com/mikem/bcm2835/
- 安装 wiringPi(可选)
#打开树莓派终端,并运行以下指令: sudo apt-get install wiringpi #对于树莓派2019年5月之后的系统(早于之前的可不用执行),可能需要进行升级: wget https://project-downloads.drogon.net/wiringpi-latest.deb sudo dpkg -i wiringpi-latest.deb gpio -v # 运行 gpio -v 会出现 2.52 版本,如果没有出现,说明安装出错。 #Bullseye 分支系统使用如下命令: git clone https://github.com/WiringPi/WiringPi cd WiringPi ./build gpio -v # 运行 gpio -v 会出现 2.60 版本,如果没有出现,说明安装出错。
安装Python函数库
- 安装函数库
sudo apt-get update sudo apt-get install python3-pip sudo apt-get install python3-pil sudo apt-get install python3-numpy sudo pip3 install spidev
- 安装函数库(python2)
sudo apt-get update sudo apt-get install python3-pip sudo apt-get install python3-pil sudo apt-get install python3-numpy sudo pip3 install spidev
- 安装gpiozero库(系统默认已安装,如果没有安装请按照以下命令进行安装)
sudo apt-get update # python3 sudo apt install python3-gpiozero # python2 sudo apt install python-gpiozero
下载测试程序
打开树莓派终端,执行:
方法一:从我们官网下载,推荐使用。
cd ~ wget https://www.waveshare.net/w/upload/3/3e/Touch_e-Paper_Code.zip unzip Touch_e-Paper_Code.zip -d Touch_e-Paper_Code 如果unzip解压遇到问题可使用7z解压: sudo apt-get install p7zip-full 7z x Touch_e-Paper_Code.zip -o./Touch_e-Paper_Code
方法二:使用github仓库,github可能更新会有延迟,推荐使用方法一。
cd ~ git clone https://github.com/waveshare/Touch_e-Paper_HAT
运行测试程序
C语言
- 进入C语言例程目录
cd ~/Touch_e-Paper_Code/c
- (可选)修改Makefile的14-17行切换依赖库,程序默认使用LGPIO库,兼容性最好。
- 修改 main.c 文件选择相应的测试程序:将对应的函数取消注释即可
- 重新编译,然后运行程序,编译过程可能需要几秒
在c目录下,运行以下指令 sudo make clean sudo make -j4 sudo ./main
python
- 进入python程序目录
cd ~/Touch_e-Paper_Code/python/examples
- 运行对应屏幕的例程,程序支持python2/3
以2.13inch Touch e-Paper HAT为例,输入
# python2 sudo python2 TP2in13_V4_test.py # python3 sudo python3 TP2in13_V4_test.py
API 解析
C语言
底层硬件接口
我们进行了底层的封装,由于硬件平台不一样,内部的实现是不一样的,如果需要了解内部实现可以去对应的目录中查看
在DEV_Config.c(.h)可以看到很多定义,在目录:Touch_e-Paper_Code\c\lib\Config
C语言使用了3种方式进行驱动:分别是BCM2835库、WiringPi库和文件IO 默认使用BCM2835库进行操作,如果你需要使用其他库来驱动的话,可以打开Touch_e-Paper_Code\c\Makefile,修改14-16行,如下:
- 数据类型:
#define UBYTE uint8_t #define UWORD uint16_t #define UDOUBLE uint32_t
- 模块初始化与退出的处理:
void DEV_Module_Init(void); void DEV_Module_Exit(void); 注意: 1.这里是处理使用墨水屏前与使用完之后一些GPIO的处理。 2.DEV_Module_Exit()之后整个模块会进入低功耗,经过测试这个功耗基本为0;
- GPIO读写:
UBYTE DEV_Digital_Read(UWORD Pin); void DEV_Digital_Write(UWORD Pin, UBYTE Value);
- SPI写数据
void DEV_SPI_WriteByte(UBYTE Value); void DEV_SPI_Write_nByte(uint8_t *pData, uint32_t Len);
- I2C读写数据
UBYTE I2C_Read_Byte(UWORD Reg, char *Data, UBYTE len); UBYTE I2C_Write_Byte(UWORD Reg, char *Data, UBYTE len);
中间层墨水屏驱动
e-paper驱动代码文件,在目录:Touch_e-Paper_Code\c\lib\e-paper
打开.h可以看到如下的函数
- 墨水屏初始化,在屏幕开始工作时和退出睡眠模式之后调用
void EPD_xxx_Init(void);
其中xxx表示,墨水屏型号。如是是2.13_V2,全屏初始化那么是EPD_2IN13_V2_Init(),
- 清屏,把墨水屏刷成白色
void EPD_xxx_Clear(void);
其中xxx表示,墨水屏型号。如是是2.13_V2,那么是EPD_2IN13_V2_Clear()
- 传输一帧的图片数据并打开显示
//黑白双色墨水屏 void EPD_xxx_Display(UBYTE *Image); //黑白红或黑白黄墨水屏 void EPD_xxx_Display(const UBYTE *blackimage, const UBYTE *ryimage);
//2.13inch e-paper V2由于控制芯片升级,对于局部刷新,需要调用EPD_xxx_DisplayPartBaseImage显示静态的背景图片,也就是以这个图片为基础进行局部刷新,然后调用动态的EPD_xxx_DisplayPart() void EPD_2IN13_V2_DisplayPart(UBYTE *Image); void EPD_2IN13_V2_DisplayPartBaseImage(UBYTE *Image);
- 进入睡眠模式
void EPD_xxx_Sleep(void);
注意进入了睡眠模式,只有两个方式能够重新工作:第一种硬件复位,第二种重新调用初始化函数
其中xxx表示,墨水屏型号。如是是2.13_V2,那么是EPD_2IN13_V2_Sleep()
中间层触控驱动
触摸控制驱动代码,在目录:Touch_e-Paper_Code\c\lib\Driver
打开.h文件可以看到函数列表(以GT1151为例)
- 触控初始化及其相关函数:
void GT_Init(void); // 初始化 void GT_Reset(void); // 复位 void GT_ReadVersion(void); // 读取版本信息
其中,复位函数和读取版本信息在初始化时被调用
- 触控芯片读写数据
void GT_Read(UWORD Reg, char *Data, UBYTE len); // 触控读数据 void GT_Write(UWORD Reg, char *Data, UBYTE len); // 触控写数据
Reg为寄存器地址,Data为数据缓冲区的地址,len为要读写的长度
- 扫描触摸信号
UBYTE GT_Scan(void); // 扫描触摸信号
返回的数据存在结构体GT1151_Dev中
上层应用
对于屏幕而言,如果需要进行画图、显示中英文字符、显示图片等怎么办,这些都是上层应用做的。这有很多小伙伴有问到一些图形的处理,我们这里提供了一些基本的功能
在如下的目录中可以找到GUI,在目录:Touch_e-Paper_Code\c\lib\GUI\GUI_Paint.c(.h)
在如下目录下是GUI依赖的字符字体,在目录:Touch_e-Paper_Code\c\lib\Fonts
- 新建图像属性:新建一个图像属性,这个属性包括图像缓存的名称、宽度、高度、翻转角度、颜色
void Paint_NewImage(UBYTE *image, UWORD Width, UWORD Height, UWORD Rotate, UWORD Color) 参数: image : 图像缓存的名称,实际上是一个指向图像缓存首地址的指针; Width : 图像缓存的宽度; Height: 图像缓存的高度; Rotate:图像的翻转的角度 Color :图像的初始颜色;
- 选择图像缓存:选择图像缓存,选择的目的是你可以创建多个图像属性,图像缓存可以存在多个,你可以选择你所创建的每一张图像
void Paint_SelectImage(UBYTE *image) 参数: image: 图像缓存的名称,实际上是一个指向图像缓存首地址的指针;
- 图像旋转:设置选择好的图像的旋转角度,最好使用在Paint_SelectImage()后,可以选择旋转0、90、180、270
void Paint_SetRotate(UWORD Rotate) 参数: Rotate: 图像选择角度,可以选择ROTATE_0、ROTATE_90、ROTATE_180、ROTATE_270分别对应0、90、180、270度
- 图像镜像翻转:设置选择好的图像的镜像翻转,可以选择不镜像、关于水平镜像、关于垂直镜像、关于图像中心镜像。
void Paint_SetMirroring(UBYTE mirror) 参数: mirror: 图像的镜像方式,可以选择MIRROR_NONE、MIRROR_HORIZONTAL、MIRROR_VERTICAL、MIRROR_ORIGIN分别对应不镜像、关于水平镜像、关于垂直镜像、关于图像中心镜像
- 设置点在缓存中显示位置和颜色:这里是GUI最核心的一个函数、处理点在缓存中显示位置和颜色;
void Paint_SetPixel(UWORD Xpoint, UWORD Ypoint, UWORD Color) 参数: Xpoint: 点在图像缓存中X位置 Ypoint: 点在图像缓存中Y位置 Color : 点显示的颜色
- 图像缓存填充颜色:把图像缓存填充为某颜色,一般作为屏幕刷白的作用
void Paint_Clear(UWORD Color) 参数: Color: 填充的颜色
- 图像缓存部分窗口填充颜色:把图像缓存的某部分窗口填充为某颜色,一般作为窗口刷白的作用,常用于时间的显示,刷白上一秒
void Paint_ClearWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD Color) 参数: Xstart: 窗口的X起点坐标 Ystart: 窗口的Y起点坐标 Xend: 窗口的X终点坐标 Yend: 窗口的Y终点坐标 Color: 填充的颜色
- 画点:在图像缓存中,在(Xpoint, Ypoint)上画点,可以选择颜色,点的大小,点的风格
void Paint_DrawPoint(UWORD Xpoint, UWORD Ypoint, UWORD Color, DOT_PIXEL Dot_Pixel, DOT_STYLE Dot_Style) 参数: Xpoint: 点的X坐标 Ypoint: 点的Y坐标 Color: 填充的颜色 Dot_Pixel: 点的大小,提供默认的8种大小点 typedef enum { DOT_PIXEL_1X1 = 1, // 1 x 1 DOT_PIXEL_2X2 , // 2 X 2 DOT_PIXEL_3X3 , // 3 X 3 DOT_PIXEL_4X4 , // 4 X 4 DOT_PIXEL_5X5 , // 5 X 5 DOT_PIXEL_6X6 , // 6 X 6 DOT_PIXEL_7X7 , // 7 X 7 DOT_PIXEL_8X8 , // 8 X 8 } DOT_PIXEL; Dot_Style: 点的风格,大小扩充方式是以点为中心扩大还是以点为左下角往右上扩大 typedef enum { DOT_FILL_AROUND = 1, DOT_FILL_RIGHTUP, } DOT_STYLE;
- 画线:在图像缓存中,从 (Xstart, Ystart) 到 (Xend, Yend) 画线,可以选择颜色,线的宽度,线的风格
void Paint_DrawLine(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD Color, LINE_STYLE Line_Style , LINE_STYLE Line_Style) 参数: Xstart: 线的X起点坐标 Ystart: 线的Y起点坐标 Xend: 线的X终点坐标 Yend: 线的Y终点坐标 Color: 填充的颜色 Line_width: 线的宽度,提供默认的8种宽度 typedef enum { DOT_PIXEL_1X1 = 1, // 1 x 1 DOT_PIXEL_2X2 , // 2 X 2 DOT_PIXEL_3X3 , // 3 X 3 DOT_PIXEL_4X4 , // 4 X 4 DOT_PIXEL_5X5 , // 5 X 5 DOT_PIXEL_6X6 , // 6 X 6 DOT_PIXEL_7X7 , // 7 X 7 DOT_PIXEL_8X8 , // 8 X 8 } DOT_PIXEL; Line_Style: 线的风格,选择线是以直线连接还是以虚线的方式连接 typedef enum { LINE_STYLE_SOLID = 0, LINE_STYLE_DOTTED, } LINE_STYLE;
- 画矩形:在图像缓存中,从 (Xstart, Ystart) 到 (Xend, Yend) 画一个矩形,可以选择颜色,线的宽度,是否填充矩形内部
void Paint_DrawRectangle(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD Color, DOT_PIXEL Line_width, DRAW_FILL Draw_Fill) 参数: Xstart: 矩形的X起点坐标 Ystart: 矩形的Y起点坐标 Xend: 矩形的X终点坐标 Yend: 矩形的Y终点坐标 Color: 填充的颜色 Line_width: 矩形四边的宽度,提供默认的8种宽度 typedef enum { DOT_PIXEL_1X1 = 1, // 1 x 1 DOT_PIXEL_2X2 , // 2 X 2 DOT_PIXEL_3X3 , // 3 X 3 DOT_PIXEL_4X4 , // 4 X 4 DOT_PIXEL_5X5 , // 5 X 5 DOT_PIXEL_6X6 , // 6 X 6 DOT_PIXEL_7X7 , // 7 X 7 DOT_PIXEL_8X8 , // 8 X 8 } DOT_PIXEL; Draw_Fill: 填充,是否填充矩形的内部 typedef enum { DRAW_FILL_EMPTY = 0, DRAW_FILL_FULL, } DRAW_FILL;
- 画圆:在图像缓存中,以 (X_Center Y_Center) 为圆心,画一个半径为Radius的圆,可以选择颜色,线的宽度,是否填充圆内部
void Paint_DrawCircle(UWORD X_Center, UWORD Y_Center, UWORD Radius, UWORD Color, DOT_PIXEL Line_width, DRAW_FILL Draw_Fill) 参数: X_Center: 圆心的X坐标 Y_Center: 圆心的Y坐标 Radius:圆的半径 Color: 填充的颜色 Line_width: 圆弧的宽度,提供默认的8种宽度 typedef enum { DOT_PIXEL_1X1 = 1, // 1 x 1 DOT_PIXEL_2X2 , // 2 X 2 DOT_PIXEL_3X3 , // 3 X 3 DOT_PIXEL_4X4 , // 4 X 4 DOT_PIXEL_5X5 , // 5 X 5 DOT_PIXEL_6X6 , // 6 X 6 DOT_PIXEL_7X7 , // 7 X 7 DOT_PIXEL_8X8 , // 8 X 8 } DOT_PIXEL; Draw_Fill: 填充,是否填充圆的内部 typedef enum { DRAW_FILL_EMPTY = 0, DRAW_FILL_FULL, } DRAW_FILL;
- 写Ascii字符:在图像缓存中,在 (Xstart Ystart) 为左顶点,写一个Ascii字符,可以选择Ascii码可视字符字库、字体前景色、字体背景色
void Paint_DrawChar(UWORD Xstart, UWORD Ystart, const char Ascii_Char, sFONT* Font, UWORD Color_Foreground, UWORD Color_Background) 参数: Xstart: 字符的左顶点X坐标 Ystart: 字体的左顶点Y坐标 Ascii_Char:Ascii字符 Font: Ascii码可视字符字库,在Fonts文件夹中提供了以下字体: font8:5*8的字体 font12:7*12的字体 font16:11*16的字体 font20:14*20的字体 font24:17*24的字体 Color_Foreground: 字体颜色 Color_Background: 背景颜色
- 写英文字符串:在图像缓存中,在 (Xstart Ystart) 为左顶点,写一串英文字符,可以选择Ascii码可视字符字库、字体前景色、字体背景色
void Paint_DrawString_EN(UWORD Xstart, UWORD Ystart, const char * pString, sFONT* Font, UWORD Color_Foreground, UWORD Color_Background) 参数: Xstart: 字符的左顶点X坐标 Ystart: 字体的左顶点Y坐标 pString:字符串,字符串是一个指针 Font: Ascii码可视字符字库,在Fonts文件夹中提供了以下字体: font8:5*8的字体 font12:7*12的字体 font16:11*16的字体 font20:14*20的字体 font24:17*24的字体 Color_Foreground: 字体颜色 Color_Background: 背景颜色
- 写中文字符串:在图像缓存中,在 (Xstart Ystart) 为左顶点,写一串中文字符,可以选择GB2312编码字符字库、字体前景色、字体背景色;
void Paint_DrawString_CN(UWORD Xstart, UWORD Ystart, const char * pString, cFONT* font, UWORD Color_Foreground, UWORD Color_Background) 参数: Xstart: 字符的左顶点X坐标 Ystart: 字体的左顶点Y坐标 pString:字符串,字符串是一个指针 Font: GB2312编码字符字库,在Fonts文件夹中提供了以下字体: font12CN:ascii字符字体11*21,中文字体16*21 font24CN:ascii字符字体24*41,中文字体32*41 Color_Foreground: 字体颜色 Color_Background: 背景颜色
- 写数字:在图像缓存中,在 (Xstart Ystart) 为左顶点,写一串数字,可以选择Ascii码可视字符字库、字体前景色、字体背景色
void Paint_DrawNum(UWORD Xpoint, UWORD Ypoint, int32_t Nummber, sFONT* Font, UWORD Color_Foreground, UWORD Color_Background) 参数: Xstart: 字符的左顶点X坐标 Ystart: 字体的左顶点Y坐标 Nummber:显示的数字,这里使用的是32位长的int型保存,可以最大显示到2147483647 Font: Ascii码可视字符字库,在Fonts文件夹中提供了以下字体: font8:5*8的字体 font12:7*12的字体 font16:11*16的字体 font20:14*20的字体 font24:17*24的字体 Color_Foreground: 字体颜色 Color_Background: 背景颜色
- 显示时间:在图像缓存中,在 (Xstart Ystart) 为左顶点,显示一段时间,可以选择Ascii码可视字符字库、字体前景色、字体背景色;这里是方便测试局部刷新而写的,因为局部刷新需要的时间为0.3S,整体显示少于1S加上数据的传输,可以做到1S刷新一次
void Paint_DrawTime(UWORD Xstart, UWORD Ystart, PAINT_TIME *pTime, sFONT* Font, UWORD Color_Background, UWORD Color_Foreground) 参数: Xstart: 字符的左顶点X坐标 Ystart: 字体的左顶点Y坐标 pTime:显示的时间,这里定义好了一个时间的结构体,只要把时分秒各位数传给参数; Font: Ascii码可视字符字库,在Fonts文件夹中提供了以下字体: font8:5*8的字体 font12:7*12的字体 font16:11*16的字体 font20:14*20的字体 font24:17*24的字体 Color_Foreground: 字体颜色 Color_Background: 背景颜色
- 写图片:把一个位图写入图像缓存中
void Paint_DrawBitMap(const unsigned char* image_buffer) 参数: image_buffer: 图像数据的缓存中的首地址
- 读取本地的bmp图片并写到缓存中
对于Jetson Nano, Raspberry Pi这些Linux操作系统的,可以读写图片
对于Raspberry Pi和Jetson Nano,在目录:RaspberryPi_JetsonNano\c\lib\GUI\GUI_BMPfile.c(.h)
UBYTE GUI_ReadBmp(const char *path, UWORD Xstart, UWORD Ystart) 参数: path:BMP图片的相对路径 Xstart: 图片的左顶点X坐标,一般默认传0 Ystart: 图片的左顶点Y坐标,一般默认传0
用户测试代码
前三个章节介绍了经典的linux三层代码结构,这里稍微讲解一下用户测试代码
在目录:Touch_e-Paper_Code\c\examples,为全部的测试代码
示例程序展示了画板和相册功能,用户可以按照已有的图片名字和尺寸自行替换图片以在该程序的基础上进行二次开发
Python
适用于python2.7和python3
对于python而言他的调用没有C复杂
库文件都在:Touch_e-Paper_Code\python\lib\TP_lib\
epdconfig.py
- 模块初始化与退出的处理:
def module_init() def module_exit() 注意: 1.这里是处理使用墨水屏前与使用完之后一些GPIO的处理。 2.module_exit()之后整个模块会进入低功耗,经过测试这个功耗基本为0;
- GPIO读写:
def digital_write(pin, value) def digital_read(pin)
- SPI写数据
def spi_writebyte(data)
- I2C读写数据:
def i2c_readbyte(reg, len) def i2c_write(reg) def i2c_writebyte(reg, value)
epdxxx.py
(xxx表示尺寸,若是2.13inch V2 e-paper,则为epd2in13_V2.py,依此类推)
- 墨水屏初始化,再屏幕开始工作时和退出睡眠模式之后调用
def init(self)
- 清屏,把墨水屏刷成白色
def Clear(self)
- 把图片转换成数组
def getbuffer(self, image)
- 传输一帧的图片数据并打开显示
def display(self, image)
对于2.13inch e-paper V2由于控制芯片升级,对于局部刷新,需要调用displayPartBaseImage()显示静态的背景图片,也就是以这个图片为基础进行局部刷新,然后调用动态的 displayPart()
def displayPartBaseImage(self, image) def displayPart(self, image)
- 进入睡眠模式
def sleep(self)
main.py
进行例程测试,示例程序展示了画板和相册功能,用户可以按照已有的图片名字和尺寸自行替换图片以在该程序的基础上进行二次开发
关于旋转设置
如果在python程序中你需要设置屏幕旋转,可以通过语句blackimage = blackimage.transpose(Image.ROTATE_270)设置。
blackimage = blackimage.transpose(Image.ROTATE_270) redimage = redimage.transpose(Image.ROTATE_270) #支持ROTATE_90, ROTATE_180, ROTATE_270三个参数
画图GUI
由于python有一个image库pil官方库链接,他十分的强大,不需要像C从逻辑层出发编写代码,可以直接引用image库进行图像处理,以下将以1.54inch e-paper为例,对程序中使用了的进行简要说明
- 需要使用image库,需要安装库
sudo apt-get install python3-pil 安装库
然后导入库
from PIL import Image,ImageDraw,ImageFont
其中Image为基本库、ImageDraw为画图功能、ImageFont为文字
- 定义一个图像缓存,以方便在图片上进行画图、写字等功能
image = Image.new('1', (epd.width, epd.height), 255) # 255: clear the frame
第一个参数定义图片的颜色深度,定义为1说明是2位图,第二个参数是一个元组,定义好图片的宽度和高度,第三个参数是定义缓存的默认颜色,0为黑色,255为白色。
- 创建一个基于image的画图对象,所有的画图操作都在这个对象上
draw = ImageDraw.Draw(image)
- 画框
draw.rectangle((0, 10, 200, 34), fill = 0)
第一个参数为一个4个元素的元组,(0,10)矩形左上角坐标值,(200,34)为矩形右下角坐标值,fill=0表示内部填充黑色。
- 画线
draw.line((16, 60, 56, 60), fill = 0)
第一个参数为一个4个元素的元组,以(16,60)为起始点,(200,34)为终止点,画一条直线,fill=0表示线为黑色。
- 画圆
draw.arc((90, 60, 150, 120), 0, 360, fill = 0)
在正方形内画一个内切圆,第一个参数为一个4个元素的元组,以(90,60)为正方形的左上角顶点,(150,120)为正方形右下角顶点,规定矩形框的水平中位线为0度角,角度顺时针变大,第二个参数表示开始角度,第三个参数标识结束角度,fill=0线为黑色
如果不是正方形,画出来的就是椭圆,这个实际上是圆弧的绘制。
除了arc可以话圆之外,还有chord可以画实心圆
draw.chord((90, 130, 150, 190), 0, 360, fill = 0)
实质是弦的绘制,第一个参数指定弦的圆外切矩形,第二、三两个参数分别是弦的起始和终止角度, 第四个参数是填充颜色,将弦从0度到360度连接并填充就变成了填充的圆了。
- 写字符
写字符往往需要写不同大小的字符,需要导入ImageFont模块,并实例化:
font = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 24)
为了丰富字体库,这里使用的是windows目录下的字符文件,如果是其他的ttc结尾的字符文件也是支持的。
写英文字符直接使用即可,写中文,由于编码是GB2312所以需要在前面加个u:
draw.text((8, 12), 'hello world', font = font, fill = 255) draw.text((8, 36), u'微雪电子', font = font, fill = 0)
第一个参数为一个2个元素的元组,以(8,12)为左顶点,字体为font,点,fill为字体颜色,第一句fill=255所以看上去是不会显示的,第二句显示微雪电子。
- 读取本地图片
image = Image.open(os.path.join(picdir, '1in54.bmp'))
参数为图片路径。
- 其他功能
python的image库十分强大,如果需要实现其他的更多功能,可以上官网学习http://effbot.org/imagingbook pil,官方的是英文的,如果感觉对你不友好,当然我们国内也有很多的优秀的博客都有讲解。
资料
文档
程序
开发资料
相关链接
FAQ
软件问题
- 我们例程使用的是 STM32f103ZET6,如果客户在 MDK 中修改其他的型号,例如 STM32F103RBT6,RAM 空间变小了,需要在原基础上修改启动文件中的 stack size 和 heap size。
- 在 Data Start Transmission 1 时,发送上一次的数据,即所谓的“OLD”数据,一般在程序中就直接发送 0x00;在 Data Start Transmission 2 时,就发送需要刷新的数据,即所谓的“NEW”数据。
- 我们的例程的中文字库是使用 GB2312 的编码方式,请将您的 xxx_test.c 文件改成 GB2312 编码格式编译下载后即可正常显示。
- 可以通过 Border Waveform Control 寄存器或者 VCOM AND DATA INTERVAL SETTING 寄存器设置边框显示颜色。
- 这种情况需要客户减少局刷位置并且在局刷5次后进行一次清屏。
- 电子墨水屏重新唤醒的过程,实际是重新上电的过程,所以 EPD 在 wake up 时,要先进行清屏的动作,这样才能最大程度地避免残影现象。
- 可能是 SPI 驱动不成功导致的:
- 1.先检查接线是否正确。
- 2.在检查 SPI 是否开启,参数是否配置正确。(波特率、模式等参数)
- 墨水屏从局刷切换为全刷时需要加入全刷初始化函数。
- 可能是之前运行过C语言的基于 BCM2835 库的例程,此时需要重启树莓派再运行 python 例程。
- 使用指令 "sudo apt-get install python-imaging" 安装一下 imaging 函数库。
硬件问题
- 可以,现在已经板载了电平转换芯片,支持 5V 驱动。
- 墨水屏额定输入电压是 2.3~3.6V,如果是 5V 系统需要做电平转换,另外电压最好不要低于 2.5V,以免影响墨水屏显示效果。
- 器件选型可以使用我们提供的原理图中的型号或者根据数据手册选择都是可以的。
- 可以,注意需要时序正确。
- 确认 SPI 通信是否正常。
- 确认 BUSY 引脚是否正常初始化为输入模式。
- 可能是没有正常复位,尝试缩短复位时低电平的持续时间。(因为驱动电路加入了断电开关,复位低电平过长会导致驱动板断电导致复位失败)
- 如果判忙函数有发送 0x71 命令,可以尝试注释掉。
- 1.64inch、2.36inch、3inch,为0.5mm 间距,26Pin
- 1.02inch,为0.5mm 间距,30Pin
- 4.37inch、7.3inch,为0.5mm 间距,50Pin
- 其余(非并口),为0.5mm 间距,24Pin。
- 排线插座 0.5-XXpin 后翻盖式 2.0H(FPC连接器)。
屏幕问题
- 【工作条件】温度范围:0~50°C;湿度范围:35%~65%RH。
- 【存储条件】:温度范围:30°C以下; 湿度范围:55%RH 以下;存储最长时间:6个月。
- 【运输条件】:温度范围:-25~70°C;运输最长时间:10天。
- 【拆包后】:温度范围:20°C±5°C; 湿度范围:50±5%RH;存储最长时间:72小时内完成组装。
- 刷新模式:
- 全刷:电子墨水屏在刷新过程中会闪烁多次(闪烁次数取决于刷新时长),闪烁是为了清除残影达到最佳的显示效果。
- 局刷:电子墨水屏在刷新过程中无闪烁效果。使用局刷功能的用户注意在刷新几次之后,要进行一次全刷操作清除残影,否则残影问题会越来越严重,甚至损坏屏幕。(目前只有部分黑白电子墨水屏支持局刷,具体参考产品页面说明)
- 刷新频率:
- 使用过程中,建议客户设置电子墨水屏的刷新间隔至少为180秒。(支持局刷功能的产品除外)
- 待机过程(即刷新操作后)建议客户将电子墨水屏设置为睡眠模式,或者断电操作(可以将墨水屏供电部分用模拟开关断开), 降低功耗并且延长电子墨水屏寿命。(部分电子墨水屏如果长时间处于上电状态的话,会出现屏幕损坏无法修复的情况)
- 使用场所:
- 电子墨水屏建议是在室内使用,不建议在户外使用。
- 如果使用场景是在户外,我们不保证其显示效果,如果因为是在户外使用导致出现的墨水屏损坏,我们不提供保修服务
- 以下是一些户外使用的防护,我们不保证做好这些防护后墨水屏可以正常使用
- 避免电子墨水屏受阳光直射,同时要做好紫外线防护措施,因为带电粒子长时间在强光的照射下会发干,导致失去活性无法刷新,这种情况是不可逆的。
- 在墨水屏连接排线上面白胶部分,使用3M胶将其完全覆盖,完全覆盖与不加,在紫外线下是有不同反应的。
- 将墨水屏放在相对阴凉的区域,如树荫底下、屋檐阴影下面
- 在设计电子墨水屏产品的时候,客户注意要确定好使用环境是否满足电子墨水屏的要求。
- 理想情况下,正常使用,可以刷新 1000000次(100万次)。
- 长时间上电开发板,在每次刷新操作之后,建议将屏幕设置为睡眠模式或者直接断电处理,否则屏幕长时间处于高电压状态下可能烧坏屏幕。
- 可以,但是需要用软件重新做电子纸初始化操作。
- 可能 SPI 速率过高,导致数据丢失,尝试降低 SPI 速率。
- 供电不足或者电源不稳定导致数据丢失。
- 数据线过长导致数据丢失,延长线最好不要超过20cm。
- 电泳电子纸的显示灰阶由粒子在微胶囊或者微杯的空间位置所决定,黑色粒子与白色粒子在电压的作用下发生电泳现象,这种促使粒子发生电泳运动的电压时序就是电子纸的驱动波形。驱动波形为电子纸显示器的核心部分,对驱动波形的优化将直接影响显示器的显示效果。而驱动波形文件是用来说明促使粒子发生电泳运动的电压时序而形成的参数,在电子纸刷新时需要定期被调用。
- 不同批次的电子纸膜片,电泳矩阵因为材料、制作工艺等原因,在驱动显示时所需电压值会有所差异,反映在灰度与电压、温度关系的就是电子墨水屏的波形。一般来说,每一批次的电泳矩阵生成后,会有相应的波形文件,以 .wbf 文件形式存在,由膜片生产商将波形文件和电泳矩阵提供给生产电子纸屏的厂家,再由生产电子纸屏厂家集成保护板、基板和驱动器以后提供给客户;如果波形文件和屏幕不对应,很可能造成无法显示或者显示效果不理想。一般出厂时波形文件已经 OTP 内置于墨水屏的驱动 IC 内,并且我们提供的部分程序也有调用外部的波形文件来驱动电子墨水屏。
- LUT 是 LOOK UP TABLE 的缩写,OTP 是 ONE TIME PROGRAM 的缩写,LUT 本意就是加载波形文件,而波形文件分 OTP 和 REGISTER 两种,其中 OTP 为内置波形存储方式,REGISTER 为外置波形存储方式。
- 主要有两种类型的墨水屏:
- 一种是先刷背景图。
- 另外一种是交替刷新旧数据和新数据。
- 在不同位置同时局刷需要在程序设计进行操作,即先把不同位置的数据刷到电子纸 IC 内,最后统一做好 Updata/TurnOnDisplay。
- 有覆膜。
- 目前所有屏幕都有内置温度传感器,也可以使用 IIC 管脚外置 LM75 温度传感器。