Micropython学习交流群 学习QQ群:786510434 提供多种固件下载和学习交流。

Micropython-扇贝物联 QQ群:31324057 扇贝物联是一个让你与智能设备沟通更方便的物联网云平台

Micropython学习交流群 学习QQ群:468985481 学习交流ESP8266、ESP32、ESP8285、wifi模块开发交流、物联网。

Micropython老哥俩的IT农场分享QQ群:929132891 为喜欢科创制作的小白们分享一些自制的计算机软硬件免费公益课程,由两位多年从事IT研发的中年大叔发起。

Micropython ESP频道

micropython esp32c3 驱动合宙墨水屏EINK-1.54 输出BMP


这里推荐个UP主的视频:https://www.bilibili.com/video/BV1ht4y147Wd?spm_id_from=333.337.search-card.all.click&vd_source=c8ea456c9e5d3eba6bfa9d1c2362caf2


micropython esp32c3 驱动合宙墨水屏EINK-1.54 输出BMP图像

bmp图片:

123.bmp


效果图:

微信图片_20220723144122.jpg


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.0097191333770752 seconds