本站改版新增arduino频道
micropython esp32c3 驱动合宙墨水屏EINK-1.54 输出BMP图像
bmp图片:

效果图:

main.py
from machine import SPI,Pin
from e1in54 import EPD
import time,sys
#esp32接线 11没有解锁
#spi = SPI(1, 60000000, sck=Pin(0), mosi=Pin(1))
#rst 2 dc 3 cs 10 busy 6
#display = EPD(spi,10,3,2,6,True)#(self, spi, cs, dc, rst, busy)
#esp32c3接线 11没有解锁
spi = SPI(1, 30000000, sck=Pin(2), mosi=Pin(3))
#rst 5 dc 4 cs 8 busy 9
display = EPD(spi,8,4,5,9)#(self, spi, cs, dc, rst, busy)
# print(len(display.buffer))
# time.sleep_ms(200)
#print(len(display.buffer))
from eSprite2 import BinloaderFile,bmpdecode
p = bmpdecode('123.bmp',InvertColor=False,limit=180)
#是否翻转颜色 灰度值
p.draw(display)
display.show()e1in54.py
#该驱动文件也可到QQ群:786510434下载
from micropython import const
from time import sleep_ms
import ustruct
from machine import Pin
import framebuf
# Display resolution
EPD_WIDTH = const(200)
EPD_HEIGHT = const(200)
# Display commands
DRIVER_OUTPUT_CONTROL = const(0x01)
BOOSTER_SOFT_START_CONTROL = const(0x0C)
#GATE_SCAN_START_POSITION = const(0x0F)
DEEP_SLEEP_MODE = const(0x10)
DATA_ENTRY_MODE_SETTING = const(0x11)
#SW_RESET = const(0x12)
#TEMPERATURE_SENSOR_CONTROL = const(0x1A)
MASTER_ACTIVATION = const(0x20)
#DISPLAY_UPDATE_CONTROL_1 = const(0x21)
DISPLAY_UPDATE_CONTROL_2 = const(0x22)
WRITE_RAM = const(0x24)
WRITE_VCOM_REGISTER = const(0x2C)
WRITE_LUT_REGISTER = const(0x32)
SET_DUMMY_LINE_PERIOD = const(0x3A)
SET_GATE_TIME = const(0x3B) # not in datasheet
#BORDER_WAVEFORM_CONTROL = const(0x3C)
SET_RAM_X_ADDRESS_START_END_POSITION = const(0x44)
SET_RAM_Y_ADDRESS_START_END_POSITION = const(0x45)
SET_RAM_X_ADDRESS_COUNTER = const(0x4E)
SET_RAM_Y_ADDRESS_COUNTER = const(0x4F)
TERMINATE_FRAME_READ_WRITE = const(0xFF) # aka NOOP
class EPD(framebuf.FrameBuffer):
LUT_FULL_UPDATE = bytearray(b'\x02\x02\x01\x11\x12\x12\x22\x22\x66\x69\x69\x59\x58\x99\x99\x88\x00\x00\x00\x00\xF8\xB4\x13\x51\x35\x51\x51\x19\x01\x00')
LUT_PARTIAL_UPDATE = bytearray(b'\x10\x18\x18\x08\x18\x18\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x14\x44\x12\x00\x00\x00\x00\x00\x00')
def __init__(self, spi, cs, dc, rst, busy):
self.spi = spi
self.cs = Pin(cs,Pin.OUT,value = 1)
self.dc = Pin(dc,Pin.OUT,value = 0)
self.rst = Pin(rst,Pin.OUT,value = 0)
self.busy = Pin(busy,Pin.IN)
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
self.pages = self.height//8
self.buffer = bytearray(self.width*self.pages)
super().__init__(self.buffer, self.width, self.height,
framebuf.MONO_HLSB)
self.init()
def clear(self):
self.buffer = bytearray(self.width*self.pages)
def show(self):
self.set_frame_memory(self.buffer,0,0,200,200)
self.display_frame()
def _command(self, command, data=None):
self.dc.value(0)
self.cs.value(0)
self.spi.write(command.to_bytes(1,'big'))
#self.spi.write(bytearray([command]))
self.cs.value(1)
if data is not None:
self._data(data)
def _data(self, data):
self.dc.value(1)
self.cs.value(0)
self.spi.write(data)
self.cs.value(1)
def init(self,isPART = True):
self.reset()
self._command(DRIVER_OUTPUT_CONTROL)
self._data(bytearray([(EPD_HEIGHT - 1) & 0xFF]))
self._data(bytearray([((EPD_HEIGHT - 1) >> 8) & 0xFF]))
self._data(bytearray([0x00])) # GD = 0 SM = 0 TB = 0
self._command(BOOSTER_SOFT_START_CONTROL, b'\xD7\xD6\x9D')
self._command(WRITE_VCOM_REGISTER, b'\xA8') # VCOM 7C
self._command(SET_DUMMY_LINE_PERIOD, b'\x1A') # 4 dummy lines per gate
self._command(SET_GATE_TIME, b'\x08') # 2us per line
self._command(DATA_ENTRY_MODE_SETTING, b'\x03') # X increment Y increment
#self._command(DATA_ENTRY_MODE_SETTING, b'\x07') # X increment Y increment
if isPART:
self.set_lut(self.LUT_FULL_UPDATE)
else:
self.set_lut(self.LUT_PARTIAL_UPDATE)
def wait_until_idle(self):
while self.busy.value() == 1:
sleep_ms(100)
def reset(self):
self.rst.value(0)
sleep_ms(200)
self.rst.value(1)
sleep_ms(200)
def set_lut(self, lut):
self._command(WRITE_LUT_REGISTER, lut)
# put an image in the frame memory
def set_frame_memory(self, image, x, y, w, h):
# x point must be the multiple of 8 or the last 3 bits will be ignored
x = x & 0xF8
w = w & 0xF8
if (x + w >= self.width):
x_end = self.width - 1
else:
x_end = x + w - 1
if (y + h >= self.height):
y_end = self.height - 1
else:
y_end = y + h - 1
self.set_memory_area(x, y, x_end, y_end)
self.set_memory_pointer(x, y)
self._command(WRITE_RAM, image)
# replace the frame memory with the specified color
def clear_frame_memory(self, color):
self.set_memory_area(0, 0, self.width - 1, self.height - 1)
self.set_memory_pointer(0, 0)
self._command(WRITE_RAM)
# send the color data
for i in range(0, self.width // 8 * self.height):
#self._data(bytearray([color]))
self._data(bytearray(color))
# draw the current frame memory and switch to the next memory area
def display_frame(self):
self._command(DISPLAY_UPDATE_CONTROL_2, b'\xC4')
self._command(MASTER_ACTIVATION)
self._command(TERMINATE_FRAME_READ_WRITE)
self.wait_until_idle()
# specify the memory area for data R/W
def set_memory_area(self, x_start, y_start, x_end, y_end):
self._command(SET_RAM_X_ADDRESS_START_END_POSITION)
# x point must be the multiple of 8 or the last 3 bits will be ignored
self._data(bytearray([(x_start >> 3) & 0xFF]))
self._data(bytearray([(x_end >> 3) & 0xFF]))
self._command(SET_RAM_Y_ADDRESS_START_END_POSITION, ustruct.pack("> 3) & 0xFF]))
self._command(SET_RAM_Y_ADDRESS_COUNTER, ustruct.pack("<H", y))
self.wait_until_idle()
# to wake call reset() or init()
def sleep(self):
self._command(DEEP_SLEEP_MODE, b'\x01') # enter deep sleep A0=1, A0=0 power on
#self.wait_until_idle()eSprite2.py
# The MIT License (MIT)
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# Author:爱玩游戏的陆千辰
# Video:https://space.bilibili.com/87690728
# Describe:屏幕精灵控制
# Version:v0.51at
# The project deponds on Micropython
# Support: SSD1306(i2c spi) SSH1106(i2c spi)
import framebuf
import math
import time,os
# def getbin(inta: int, x: int) -> int:
# if x > 0:
# return (inta >> x) - (inta >> (x + 1)) * 2
# elif x == 0:
# return inta - (inta >> 1) * 2
def getbin(inta: int, x: int) -> int:
return (inta & (1<>x
def clamp(a,min,max):
global aa,bb,cc
if max < min:
return min
if a>max:
return min
elif a int:
temp = num >> 3
if (num == temp << 3):
return temp
else:
return temp + 1
def getPageLen(num: int) -> int:
temp = num >> 3
if (num & 7):
return temp + 1
else:
return temp
def DataScale(data,scale):
re = []
inv = False
if scale == 0:
return re
if scale < 0:
scale = - scale
inv = True
scale = len(data)/(scale*len(data))
i = 0
while math.ceil(i) < len(data):
re.append(data[math.ceil(i)])
i += scale
if inv:
re.reverse()
return re
def bmpdecode(filename,newname = None,biasY = 0,limit=128,log=True,InvertColor=False,delAfterDecode = False):
f=open(filename, 'rb')
if f.read(2) == b'BM': #header
dummy = f.read(8) #file size(4), creator bytes(4)
offset = int.from_bytes(f.read(4), 'little')
hdrsize = int.from_bytes(f.read(4), 'little')
width = int.from_bytes(f.read(4), 'little')
height = int.from_bytes(f.read(4), 'little')
if int.from_bytes(f.read(2), 'little') == 1: #planes must be 1
depth = int.from_bytes(f.read(2), 'little')
if depth == 24 and int.from_bytes(f.read(4), 'little') == 0:#compress method == uncompressed
print("Image size:", width, "x", height)
rowsize = (width * 3 + 3) & ~3
if height < 0:
height = -height
flip = False
else:
flip = True
#display._setwindowloc((posX,posY),(posX+w - 1,posY+h - 1))
row = 0
if newname == None:
newname = filename[:-4]
buff = open(newname+'.ebin','wb+')
buff.write(b'\x00\x01')
buff.write((getPageLen(width)*8).to_bytes(2,'little'))
buff.write(height.to_bytes(2,'little'))
temp = [0]*(getPageLen(width))
temp2 = height - 1+ biasY
dataCounter = 0
dataPointer = 0
if(InvertColor):
while row < height:
# 写入
buff.write(bytearray(temp))
temp = [0]*getPageLen(width)
dataCounter = 0
dataPointer = 0
if flip:
pos = offset + ( temp2 - row ) * rowsize
else:
pos = offset + (row + biasY)* rowsize
if f.tell() != pos:
f.seek(pos)
col = 0
while col < width:
bgr = f.read(3)
gray = (bgr[2]*77+ bgr[1]*151+bgr[0]*28)>>8
#(R*77+G*151+B*28)>>8
if(gray<=limit):
data = 128 # 1<>dataCounter)
dataCounter = dataCounter + 1
if dataCounter >=8 :
dataCounter = 0
dataPointer += 1
#temp[col] = (temp[col]>>1)+data
col = col+ 1
row = row+1
if log:
print("decoding :%d%%"%(row*100//height))
else:# 空间换时间 本质一个if
while row < height:
# 写入
buff.write(bytearray(temp))
temp = [0]*getPageLen(width)
dataCounter = 0
dataPointer = 0
if flip:
pos = offset + ( temp2 - row ) * rowsize
else:
pos = offset + (row + biasY)* rowsize
if f.tell() != pos:
f.seek(pos)
col = 0
while col < width:
bgr = f.read(3)
gray = (bgr[2]*77+ bgr[1]*151+bgr[0]*28)>>8
#(R*77+G*151+B*28)>>8
if(gray>limit):
data = 128 # 1<>dataCounter)
dataCounter = dataCounter + 1
if dataCounter >=8 :
dataCounter = 0
dataPointer += 1
#temp[col] = (temp[col]>>1)+data
col = col+ 1
row = row+1
if log:
print("decoding :%d%%"%(row*100//height))
else:
raise TypeError("Type not support")
f.close()
buff.close()
if(delAfterDecode):
os.remove(filename)
print('Encode Finish save to: '+newname+'.ebin')
return BinloaderFile(newname+'.ebin')
class BinloaderFile:
def __init__(self, filename, x =0, y =0):
self.x, self.y = x, y
self.f = open(filename, "rb")
temp = self.f.read(6)
self.w = temp[2] + (temp[3] << 8)
self.h = temp[4] + (temp[5] << 8)
def draw(self, display,x = 0,y = 0):
if x < 0:
x = 0
if y < 0:
y = 0
width = getPageLen(self.w)
displayW = display.width // 8
drawWidth = min(width,displayW - x)
displayW = min(displayW,displayW + self.w - x)
start = x + y * width
y = 0
while y < self.h:
self.f.seek(6+y*width)
#print(start + y * displayW + drawWidth)
if start + y * displayW + drawWidth > len(display.buffer):
return
display.buffer[start + y * displayW:start + y * displayW + drawWidth] = self.f.read(drawWidth)
y += 1
def __del__(self):
self.f.close()
Copyright © 2014 ESP56.com All Rights Reserved
晋ICP备14006235号-22 晋公网安备14108102001165号
执行时间: 0.01213812828064 seconds