Hi All,
I have a Lolin D1 Mini and a Lolin 2.13 Inch Epaper Display (250x122).
Starting from these drivers https://github.com/mcauser/micropython-waveshare-epaper, specifically Epaper2in13.py and examples/2in9-hello-world/ and modifying them the best I can, I’m not really making any progress. Really hoping someone can shed some light on what I’m missing.
The closest I’ve come to getting anything displaying is in the pic below. I seem to be able to reset the display memory to a “height” dimension and have that represented on the display. Strangely it doesn't seem to use both the “width” and “height” dimensions. It’s only using the “height” dimension (I’m not sure why). In the code posted below I have set the height and width to 64px.
https://imgur.com/DM6ePnY
Pins on the display
https://imgur.com/jAZ3cSh
Pins on the board
https://imgur.com/emSIATB
https://imgur.com/3XqNmR4
This is the spec sheet for the Driver IC: IL3897
http://www.e-paper-display.com/download ... 82&v=0.zip
Any help would be great, thanks in advance.
####CODE STARTS HERE#####
from machine import Pin, SPI
from micropython import const
from time import sleep_ms
import ustruct
# Display resolution
EPD_WIDTH = const(64)
EPD_HEIGHT = const(64) #bottom is "2.13 EPD"
# datasheet says 250x122 (increased to 128 to be multiples of 8)
BOOSTER_SOFT_START_CONTROL = const(0x0C)
DRIVER_OUTPUT_CONTROL = const(0x01)
DEEP_SLEEP_MODE = const(0x10)
DATA_ENTRY_MODE_SETTING = const(0x11)
MASTER_ACTIVATION = const(0x20)
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)
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(0x7F)
BUSY = const(1) # 1=busy, 0=idle
class EPD:
def __init__(self, spi, cs, dc, rst, busy):
self.spi = spi
self.cs = cs
self.dc = dc
self.rst = rst
self.busy = busy
self.cs.init(self.cs.OUT, value=1)
self.dc.init(self.dc.OUT, value=0)
self.rst.init(self.rst.OUT, value=0)
self.busy.init(self.busy.IN)
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
def _command(self, command, data=None):
self.dc(0)
self.cs(0)
self.spi.write(bytearray([command]))
self.cs(1)
if data is not None:
self._data(data)
def _data(self, data):
self.dc(1)
self.cs(0)
self.spi.write(data)
self.cs(1)
def init(self):
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
def wait_until_idle(self):
while self.busy.value() == BUSY:
print("wait_until_idle - is busy")
sleep_ms(100)
def reset(self):
self.rst(0)
sleep_ms(200)
self.rst(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
#print(image)
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):
print("clear_frame_memory")
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))
# draw the current frame memory and switch to the next memory area
def display_frame(self):
print("display_frame")
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("<HH", y_start, y_end))
# specify the start point for data R/W
def set_memory_pointer(self, x, y):
self._command(SET_RAM_X_ADDRESS_COUNTER)
# x point must be the multiple of 8 or the last 3 bits will be ignored
self._data(bytearray([(x >> 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)
self.wait_until_idle()
baudrate = int(20e6)
spi = SPI(
-1,
baudrate=baudrate,
polarity=0,
phase=0,
bits=8,
firstbit=0,
sck=Pin(14),
mosi=Pin(13),
miso=Pin(12)
)
dc = Pin(16)
cs = Pin(15)
rst = Pin(4)
busy = Pin(2)
w = EPD_WIDTH
h = EPD_HEIGHT
x = 0
y = 0
e = EPD(spi, cs, dc, rst, busy)
e.init()
# clear display
e.clear_frame_memory(0xFF)
e.display_frame()
# use a frame buffer
import framebuf
buf = bytearray(w * h // 8)
fb = framebuf.FrameBuffer(buf, w, h, framebuf.MONO_HLSB)
black = 0
white = 1
fb.fill(white)
fb.text('HI',0,0,black)
fb.pixel(30, 10, black)
fb.hline(30, 30, 10, black)
e.set_frame_memory(buf, x, y, w, h)
e.display_frame()
Lolin D1 Mini and Lolin 2.13 Inch Epaper Display (250x122)
-
- Posts: 1
- Joined: Sun Jun 23, 2019 4:29 am