kopia lustrzana https://github.com/peterhinch/micropython-nano-gui
Merge pull request #56 from EnricoRoss98/WeActStudio-EDP
Added driver for the WeAct Studio 2.9in EPD (SSD1680)pull/61/head
commit
6894c4fbb6
55
DISPLAYS.md
55
DISPLAYS.md
|
@ -13,32 +13,33 @@ owing to their long update time.
|
|||
Size is diagonal in inches. C/M/GS color/1-bit monochrome/greyscale.
|
||||
Width and height are pixels.
|
||||
|
||||
| Size | Width | Height | Tech | Driver | Description | Notes |
|
||||
|:------:|:-----:|:------:|:------|:--------------|:----------------------------|:------|
|
||||
| 0.96C | 94 | 64 | OLED | [SSD1331][1d] | [Adafruit 684][1m] | |
|
||||
| 1.12GS | 96 | 96 | OLED | [SSD1327][11d]| [Seeed 104030011][21m] | Obsolescent. |
|
||||
| 1.27C | 128 | 96 | OLED | [SSD1351][2d] | [Adafruit 1673][2m] | |
|
||||
| 1.5C | 128 | 128 | OLED | [SSD1351][2d] | [Adafruit 1431][3m] | |
|
||||
| 1.44C | 128 | 128 | TFT | [ST7735R][4d] | [Adafruit 2088][5m] | |
|
||||
| 1.5C | 160 | 128 | TFT | [ST7735R][4d] | [Adafruit 358][6m] | |
|
||||
| 1.3C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 4313][7m] | |
|
||||
| 1.5GS | 128 | 128 | OLED | [SSD1327][11d]| [Waveshare 13992][20m] | |
|
||||
| 2.0C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare Pico LCD 2][18m] | For Pi Pico. |
|
||||
| 1.54C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 3787][8m] | |
|
||||
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [T-Display][9m] | ESP32 with attached display. |
|
||||
| 2.8C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare pico 2.8][10m] | Display for Pi Pico. |
|
||||
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Waveshare pico 1.14][11m] | For Pi Pico. Buttons good for micro-gui. |
|
||||
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Pimoroni pico 1.14][23m] | For Pi Pico. Buttons good for micro-gui. |
|
||||
| 3.2C | 320 | 240 | TFT | [ILI9341][6d] | [Adafruit 1743][12m] | Big display. eBay equivalents work here. |
|
||||
| 3.5C | 480 | 320 | TFT | [ILI9486][12d]| [Waveshare Rpi 3.5 LCD][22m]| Pi HAT. Many pixels. Needs plenty of RAM. |
|
||||
| 3.5C | 480 | 320 | TFT | [ILI9486][12d]| [Adafruit 3.5 LCD][24m] | 3.5" HX8357D display, notes as above. |
|
||||
| 3.5C | 480 | 320 | TFT | [ILI9486][12d]| [Waveshere RPI 3.5 LCD][25m]| 3.5" ILI9488 display, notes as above. |
|
||||
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4262][13m] | Flexible ePaper display. |
|
||||
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4777][15m] | FeatherWing ePaper display. |
|
||||
| 4.2M | 400 | 300 | eInk | [WS][10d] | [Waveshare pico 4.2][19m] | Pico, Pico W plug in. Other hosts via cable. |
|
||||
| 2.7M | 274 | 176 | eInk | [HAT][8d] | [Waveshare HAT][14m] | HAT designed for Raspberry Pi, repurposed. |
|
||||
| 2.7M | 400 | 240 | Sharp | [Sharp][9d] | [Adafruit 4694][16m] | Micropower monochrome display. |
|
||||
| 1.3M | 168 | 144 | Sharp | [Sharp][9d] | [Adafruit 3502][17m] | Ditto. |
|
||||
| Size | Width | Height | Tech | Driver | Description | Notes |
|
||||
|:------:|:-----:|:------:|:------|:---------------|:-----------------------------|:---------------------------------------------|
|
||||
| 0.96C | 94 | 64 | OLED | [SSD1331][1d] | [Adafruit 684][1m] | |
|
||||
| 1.12GS | 96 | 96 | OLED | [SSD1327][11d] | [Seeed 104030011][21m] | Obsolescent. |
|
||||
| 1.27C | 128 | 96 | OLED | [SSD1351][2d] | [Adafruit 1673][2m] | |
|
||||
| 1.5C | 128 | 128 | OLED | [SSD1351][2d] | [Adafruit 1431][3m] | |
|
||||
| 1.44C | 128 | 128 | TFT | [ST7735R][4d] | [Adafruit 2088][5m] | |
|
||||
| 1.5C | 160 | 128 | TFT | [ST7735R][4d] | [Adafruit 358][6m] | |
|
||||
| 1.3C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 4313][7m] | |
|
||||
| 1.5GS | 128 | 128 | OLED | [SSD1327][11d] | [Waveshare 13992][20m] | |
|
||||
| 2.0C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare Pico LCD 2][18m] | For Pi Pico. |
|
||||
| 1.54C | 240 | 240 | TFT | [ST7789][5d] | [Adafruit 3787][8m] | |
|
||||
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [T-Display][9m] | ESP32 with attached display. |
|
||||
| 2.8C | 320 | 240 | TFT | [ST7789][5d] | [Waveshare pico 2.8][10m] | Display for Pi Pico. |
|
||||
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Waveshare pico 1.14][11m] | For Pi Pico. Buttons good for micro-gui. |
|
||||
| 1.14C | 240 | 135 | TFT | [ST7789][5d] | [Pimoroni pico 1.14][23m] | For Pi Pico. Buttons good for micro-gui. |
|
||||
| 3.2C | 320 | 240 | TFT | [ILI9341][6d] | [Adafruit 1743][12m] | Big display. eBay equivalents work here. |
|
||||
| 3.5C | 480 | 320 | TFT | [ILI9486][12d] | [Waveshare Rpi 3.5 LCD][22m] | Pi HAT. Many pixels. Needs plenty of RAM. |
|
||||
| 3.5C | 480 | 320 | TFT | [ILI9486][12d] | [Adafruit 3.5 LCD][24m] | 3.5" HX8357D display, notes as above. |
|
||||
| 3.5C | 480 | 320 | TFT | [ILI9486][12d] | [Waveshere RPI 3.5 LCD][25m] | 3.5" ILI9488 display, notes as above. |
|
||||
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4262][13m] | Flexible ePaper display. |
|
||||
| 2.9M | 296 | 128 | eInk | [UC8151D][7d] | [Adafruit 4777][15m] | FeatherWing ePaper display. |
|
||||
| 2.9M | 296 | 128 | eInk | [SSD1680][15d] | [WeAct Studio ePaper][26m] | WeAct Studio ePaper display. |
|
||||
| 4.2M | 400 | 300 | eInk | [WS][10d] | [Waveshare pico 4.2][19m] | Pico, Pico W plug in. Other hosts via cable. |
|
||||
| 2.7M | 274 | 176 | eInk | [HAT][8d] | [Waveshare HAT][14m] | HAT designed for Raspberry Pi, repurposed. |
|
||||
| 2.7M | 400 | 240 | Sharp | [Sharp][9d] | [Adafruit 4694][16m] | Micropower monochrome display. |
|
||||
| 1.3M | 168 | 144 | Sharp | [Sharp][9d] | [Adafruit 3502][17m] | Ditto. |
|
||||
|
||||
## Displays using compatible drivers
|
||||
|
||||
|
@ -105,6 +106,7 @@ simple. See [this doc](./DRIVERS.md#7-writing-device-drivers) for details.
|
|||
[12d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md#34-driver-for-ili9486
|
||||
[13d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/drivers/sh1106/sh1106.py
|
||||
[14d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/drivers/ssd1306/ssd1306.py
|
||||
[15d]: https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md#54-weact-studio-ssd1680-eink-displays
|
||||
|
||||
[1m]: https://www.adafruit.com/product/684
|
||||
[2m]: https://www.adafruit.com/product/1673
|
||||
|
@ -131,4 +133,5 @@ simple. See [this doc](./DRIVERS.md#7-writing-device-drivers) for details.
|
|||
[23m]: https://shop.pimoroni.com/products/pico-display-pack?variant=32368664215635
|
||||
[24m]: https://www.adafruit.com/product/2050
|
||||
[25m]: https://www.waveshare.com/wiki/Pico-ResTouch-LCD-3.5
|
||||
[26m]: https://aliexpress.com/item/1005004644515880.html
|
||||
|
||||
|
|
14
DRIVERS.md
14
DRIVERS.md
|
@ -1374,6 +1374,20 @@ Color values of 0 (white) to 3 (black) can explicitly be specified.
|
|||
|
||||
###### [Contents](./DRIVERS.md#contents)
|
||||
|
||||
## 5.4 WeAct Studio SSD1680 eInk Displays
|
||||
|
||||
The driver supports the WeAct Studio SSD1680 2.9 inch 296*128 pixel
|
||||
[display](https://github.com/WeActStudio/WeActStudio.EpaperModule) that uses the
|
||||
[SSD1680 driver](https://github.com/WeActStudio/WeActStudio.EpaperModule/blob/master/Doc/SSD1680.pdf).
|
||||
|
||||
This display lacks many features when compared to the ones from Waveshare,
|
||||
two important examples are fast refresh and partial refresh. The big pro however is the price,
|
||||
it costs half the money of the Waveshare 2.9in alternative.
|
||||
|
||||
The driver is cross platform and supports landscape or portrait mode. To keep
|
||||
the buffer size down (to 4736 bytes) there is no greyscale support. It should
|
||||
be noted that WeAct Studio product page suggests to not update the display more frequently than every 180s.
|
||||
|
||||
# 6. EPD Asynchronous support
|
||||
|
||||
The following applies to nano-gui. Under micro-gui the update mechanism is
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
# Nanogui driver for WeAct Studio 2.9" Black and White ePaper display.
|
||||
# This driver can be used with the 2.13" EPD from WeAct Studio or with
|
||||
# other displays with the same driver however, on my tests changing the resolution
|
||||
# may rise exception, but I manage to successfully use this driver with the smaller
|
||||
# display without changing the resolution.
|
||||
# [Display](https://github.com/WeActStudio/WeActStudio.EpaperModule)
|
||||
|
||||
# EPD is subclassed from framebuf.FrameBuffer for use with Writer class and nanogui.
|
||||
|
||||
# Released under the MIT license see LICENSE
|
||||
|
||||
# Based on the following sources:
|
||||
# https://github.com/peterhinch/micropython-nano-gui/blob/master/drivers/epaper/epd29.py
|
||||
# https://github.com/hfwang132/ssd1680-micropython-drivers
|
||||
|
||||
# You can run a demo for this driver by executing the demo script "epd29_sync.py"
|
||||
|
||||
import framebuf
|
||||
import uasyncio as asyncio
|
||||
from micropython import const
|
||||
from time import sleep_ms, sleep_us, ticks_ms, ticks_us, ticks_diff
|
||||
from gui.drivers.boolpalette import BoolPalette
|
||||
from machine import lightsleep, Pin
|
||||
|
||||
|
||||
class TimeoutError(Exception):
|
||||
def __init__(self, msg):
|
||||
super().__init__(msg)
|
||||
|
||||
|
||||
class EPD(framebuf.FrameBuffer):
|
||||
# A monochrome approach should be used for coding this. The rgb method ensures
|
||||
# nothing breaks if users specify colors.
|
||||
@staticmethod
|
||||
def rgb(r, g, b):
|
||||
return int((r > 127) or (g > 127) or (b > 127))
|
||||
|
||||
# Discard asyn: autodetect
|
||||
def __init__(self, spi, cs, dc, rst_pin, busy, landscape=True):
|
||||
self._spi = spi
|
||||
self._cs = cs # Pins
|
||||
self._dc = dc
|
||||
self._rst = Pin(rst_pin, Pin.OUT, value=1)
|
||||
self._rst_pin = rst_pin
|
||||
self._busy = busy # Pin High if Busy
|
||||
self._lsc = landscape
|
||||
# ._as_busy is set immediately on start of task. Cleared
|
||||
# when busy pin is physically 0.
|
||||
self._as_busy = False
|
||||
self.updated = asyncio.Event()
|
||||
self.complete = asyncio.Event()
|
||||
# Public bound variables required by nanogui.
|
||||
# Dimensions in pixels as seen by nanogui (landscape mode).
|
||||
self.width = 296 if landscape else 128
|
||||
self.height = 128 if landscape else 296
|
||||
# Other public bound variable.
|
||||
# Special mode enables demos written for generic displays to run.
|
||||
self.demo_mode = False
|
||||
|
||||
self._buffer = bytearray(self.height * self.width // 8)
|
||||
self._mvb = memoryview(self._buffer)
|
||||
mode = framebuf.MONO_VLSB if landscape else framebuf.MONO_HLSB
|
||||
self.palette = BoolPalette(mode)
|
||||
super().__init__(self._buffer, self.width, self.height, mode)
|
||||
self.init()
|
||||
|
||||
def _command(self, command, data=None):
|
||||
self._dc(0)
|
||||
self._spi.write(command)
|
||||
self._dc(1)
|
||||
if data is not None:
|
||||
self._data(data)
|
||||
|
||||
def _data(self, data, buf1=bytearray(1)):
|
||||
for b in data:
|
||||
buf1[0] = b
|
||||
self._spi.write(buf1)
|
||||
|
||||
def hw_reset(self):
|
||||
self._rst(1)
|
||||
sleep_ms(200)
|
||||
self._rst(0)
|
||||
sleep_ms(200)
|
||||
self._rst(1)
|
||||
self.wait_until_ready()
|
||||
# print("hardware reset successful")
|
||||
|
||||
def init(self):
|
||||
# Hardware reset
|
||||
self.hw_reset()
|
||||
|
||||
self._dc(1)
|
||||
self._cs(0)
|
||||
|
||||
# Initialisation
|
||||
cmd = self._command
|
||||
|
||||
# Software Reset
|
||||
# print("software resetting...")
|
||||
# cmd(b'\x12')
|
||||
# self.wait_until_ready()
|
||||
# print("software reset successful")
|
||||
|
||||
# deriver output control
|
||||
cmd(b'\x01', b'\x27\x01\x01')
|
||||
# data entry mode
|
||||
cmd(b'\x11', b'\x01')
|
||||
# set ram-x addr start/end pos
|
||||
cmd(b'\x44', b'\x00\x0F')
|
||||
# set ram-y addr start/end pos
|
||||
cmd(b'\x45', b'\x27\x01\x00\x00')
|
||||
# border waveform
|
||||
cmd(b'\x3c', b'\x05')
|
||||
# display update control
|
||||
cmd(b'\x21', b'\x00\x80')
|
||||
# set ram-x addr cnt to 0
|
||||
cmd(b'\x4e', b'\x00')
|
||||
# set ram-y addr cnt to 0x127
|
||||
cmd(b'\x4F', b'\x27\x01')
|
||||
|
||||
# set to use internal temperature sensor
|
||||
cmd(b'\x18', b'\x80')
|
||||
|
||||
'''
|
||||
# read from internal temperature sensor
|
||||
self._dc(0)
|
||||
self._spi.write(b'\x1B')
|
||||
print(self._spi.read(2))
|
||||
self._dc(1)
|
||||
print(self._spi.read(2))
|
||||
'''
|
||||
|
||||
self.wait_until_ready()
|
||||
# print('Init Done.')
|
||||
|
||||
# For use in synchronous code: blocking wait on ready state.
|
||||
def wait_until_ready(self):
|
||||
sleep_ms(50)
|
||||
while not self.ready():
|
||||
sleep_ms(100)
|
||||
|
||||
# Return immediate status. Pin state: 1 == busy.
|
||||
def ready(self):
|
||||
return not (self._as_busy or (self._busy() == 1))
|
||||
|
||||
# draw the current frame memory.
|
||||
def show(self, buf1=bytearray(1),
|
||||
fast_refresh=False, # USELESS for this driver, doesn't work well at all
|
||||
deepsleep_after_refresh=False,
|
||||
lightsleep_while_waiting_for_refresh=False):
|
||||
if not self.ready():
|
||||
# Hardware reset to exit deep sleep mode
|
||||
self.hw_reset()
|
||||
|
||||
mvb = self._mvb
|
||||
cmd = self._command
|
||||
dat = self._data
|
||||
|
||||
cmd(b'\x24')
|
||||
if self._lsc: # Landscape mode
|
||||
wid = self.width
|
||||
tbc = self.height // 8 # Vertical bytes per column
|
||||
iidx = wid * (tbc - 1) # Initial index
|
||||
idx = iidx # Index into framebuf
|
||||
vbc = 0 # Current vertical byte count
|
||||
hpc = 0 # Horizontal pixel count
|
||||
for _ in range(len(mvb)):
|
||||
buf1[0] = ~mvb[idx]
|
||||
dat(buf1)
|
||||
idx -= wid
|
||||
vbc += 1
|
||||
vbc %= tbc
|
||||
if not vbc:
|
||||
hpc += 1
|
||||
idx = iidx + hpc
|
||||
else:
|
||||
for b in mvb:
|
||||
buf1[0] = ~b
|
||||
dat(buf1)
|
||||
|
||||
if fast_refresh:
|
||||
cmd(b'\x22', b'\xFF')
|
||||
else:
|
||||
cmd(b'\x22', b'\xF7')
|
||||
sleep_us(20)
|
||||
cmd(b'\x20') # DISPLAY_REFRESH
|
||||
|
||||
if lightsleep_while_waiting_for_refresh:
|
||||
# set Pin hold=True is needed before entering lightsleep and after you must revert it back to hold=False
|
||||
# without this, entering lightsleep results in a low state on the reset pin, and this resets the driver
|
||||
self._rst = Pin(self._rst_pin, Pin.OUT, value=1, hold=True)
|
||||
lightsleep(3000) # can be used to lowering consumption on ESP32
|
||||
self._rst = Pin(self._rst_pin, Pin.OUT, value=1, hold=False)
|
||||
|
||||
self.wait_until_ready()
|
||||
if deepsleep_after_refresh:
|
||||
cmd(b'\x10', b'\x01')
|
||||
else:
|
||||
cmd(b'\x10', b'\x00')
|
|
@ -0,0 +1,22 @@
|
|||
# WIRING
|
||||
# 15 BUSY
|
||||
# 4 DC
|
||||
# 2 Rst
|
||||
# 5 CS
|
||||
# 23 SDA
|
||||
# 18 SCL
|
||||
|
||||
from machine import Pin, SPI
|
||||
import gc
|
||||
|
||||
# *** Choose your color display driver here ***
|
||||
from drivers.epaper.epd29_ssd1680 import EPD as SSD
|
||||
|
||||
dc = Pin(4, Pin.OUT, value=0)
|
||||
rst_pin = 2
|
||||
cs = Pin(5, Pin.OUT, value=1)
|
||||
busy = Pin(15, Pin.IN)
|
||||
|
||||
spi = SPI(1, baudrate=10000000, sck=Pin(18), mosi=Pin(23))
|
||||
gc.collect() # Precaution before instantiating framebuf
|
||||
ssd = SSD(spi, cs, dc, rst_pin, busy, landscape=True)
|
Ładowanie…
Reference in New Issue