Micropython学习交流群 学习QQ群:786510434 提供多种固件下载和学习交流。
Micropython-扇贝物联 QQ群:31324057 扇贝物联是一个让你与智能设备沟通更方便的物联网云平台
Micropython学习交流群 学习QQ群:468985481 学习交流ESP8266、ESP32、ESP8285、wifi模块开发交流、物联网。
Micropython老哥俩的IT农场分享QQ群:929132891 为喜欢科创制作的小白们分享一些自制的计算机软硬件免费公益课程,由两位多年从事IT研发的中年大叔发起。
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
执行时间: 0.010849952697754 seconds