Lolin D1 Mini and Lolin 2.13 Inch Epaper Display (250x122)

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
Post Reply
martygoing88mph
Posts: 1
Joined: Sun Jun 23, 2019 4:29 am

Lolin D1 Mini and Lolin 2.13 Inch Epaper Display (250x122)

Post by martygoing88mph » Sun Jun 23, 2019 6:18 am

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()

Post Reply