Já que não rolou usar o display com o CircuitPython (por enquanto, espero), resolvi tentar com o MicroPython. Obtive melhores resultados, mas tem algumas limitações a serem superadas.
![]() |
| E temos uma imagem no display! |
MicroPython é o projeto original que implementou uma grande parte do Python 3 em microcontroladores. CircuitPython é um fork do MicroPython, capitaneado principalmente pela Adfruit. Ele mantem a parte da linguagem Python mas tem mudanças nas classes de interface com os recursos do microcontrolador.
No lugar do displayio do CircuitPython, a base para interface com displays gráficos no MicroPython é o framebuf. Como o nome sugere, esta classe foca na manipulação de um buffer onde é mantida a imagem da tela. Um driver para um display é uma classe derivada de framebuf que (no mínimo):
- aloca o buffer de tela com o tamanho e formato apropriado na iniciação e o passa para a iniciação da classe framebuf (junto com as dimensões e o formato de armazenamento dos pontos)
- tem um método show() que envia para o display o conteúdo do buffer de tela
# MH-ET-LIVE 1.54 e-paper display driver
# Based on Waveshare epd1in54_V2.py by Waveshare Team
from micropython import const
from time import sleep
import framebuf
# Screen size (fixed by now)
WIDTH = const(200)
HEIGHT = const(200)
# Commands
DRIVER_OUTPUT_CONTROL = const(0x01)
SET_GATE_VOLTAGE = const(0x03)
SET_SOURCE_VOLTAGE = const(0x04)
DEEP_SLEEP_MODE = const(0x10)
DATA_ENTRY_MODE = const(0x11)
SWRESET = const(0x12)
UNDOC_1 = const(0x18)
MASTER_ACTIVATION = const(0x20)
DISPLAY_UPDATE_CONTROL_2 = const(0x22)
WRITE_RAM_BLACK = const(0x24)
VCOM_VOLTAGE = const(0x2C)
WRITE_LUT_REGISTER = const(0x32)
BORDER_WAVEFORM = const(0x3C)
DRIVE_OUTPUT_CONTROL = const(0x3F)
SET_RAM_X_ADDRESS = const(0x44)
SET_RAM_Y_ADDRESS = const(0x45)
SET_RAM_X_CURSOR = const(0x4E)
SET_RAM_Y_CURSOR = const(0x4F)
# LUT
_LUT = (
b"\x80\x48\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b"\x40\x48\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b"\x80\x48\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b"\x40\x48\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b"\x0a\x00\x00\x00\x00\x00\x00"
b"\x08\x01\x00\x08\x01\x00\x02"
b"\x0a\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x00\x00\x00"
b"\x22\x22\x22\x22\x22\x22\x00\x00\x00"
)
class MHET_EPaper(framebuf.FrameBuffer):
def __init__(self, spi, dc_pin, reset_pin, cs_pin, busy_pin):
self.spi = spi
self.rate = 4000000
self.width = WIDTH
self.height = HEIGHT
self.dc_pin = dc_pin
self.reset_pin = reset_pin
self.cs_pin = cs_pin
self.busy_pin = busy_pin
self.buffer = bytearray((self.width * self.height + 7) >> 3)
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_HLSB)
# Wait for command execution
def wait_ready(self):
while self.busy_pin() == 1:
sleep(0.001)
# Hardware reset the controller
def reset(self):
self.reset_pin(1)
sleep(0.2)
self.reset_pin(0)
sleep(0.005)
self.reset_pin(1)
sleep(0.2)
# Send a command to the controller
def send_cmd(self, cmd):
self.spi.init(baudrate=self.rate)
self.dc_pin(0)
self.cs_pin(0)
self.spi.write(bytearray([cmd]))
self.cs_pin(1)
# Send data to the controller
def send_data(self, buf):
self.spi.init(baudrate=self.rate)
self.dc_pin(1)
self.cs_pin(0)
self.spi.write(buf)
self.cs_pin(1)
# Turn on the display
def poweron(self):
self.send_cmd(DISPLAY_UPDATE_CONTROL_2)
self.send_data(bytearray([0xc7]))
self.send_cmd(MASTER_ACTIVATION)
self.wait_ready()
# Turn off the display
def poweroff(self):
self.send_cmd(DEEP_SLEEP_MODE)
self.send_data(bytearray([0x01]))
# Waveform setting
def set_lut(self):
#print ('Set LUT')
self.send_cmd( WRITE_LUT_REGISTER)
self.send_data(bytearray(_LUT))
self.send_cmd(DRIVE_OUTPUT_CONTROL)
self.send_data(bytearray([0x22]))
self.send_cmd(SET_GATE_VOLTAGE)
self.send_data(bytearray([0x17]))
self.send_cmd(SET_SOURCE_VOLTAGE)
self.send_data(bytearray([0x41, 0x00, 0x32]))
self.send_cmd(VCOM_VOLTAGE)
self.send_data(bytearray([0x20]))
#print ('LUT ok')
# initializes the display
def init_display(self):
self.reset()
self.wait_ready()
self.send_cmd(SWRESET)
self.wait_ready()
for (cmd, param) in (
(DRIVER_OUTPUT_CONTROL, (0xC7, 0x00, 0x01)),
(DATA_ENTRY_MODE, (0x01,)),
(SET_RAM_X_ADDRESS, (0, 24)),
(SET_RAM_Y_ADDRESS, (199, 0, 0, 0)),
(BORDER_WAVEFORM, (0x01,)),
(UNDOC_1, (0x80,)),
(DISPLAY_UPDATE_CONTROL_2, (0xB1,)),
(MASTER_ACTIVATION, ()),
(SET_RAM_X_CURSOR, (0,)),
(SET_RAM_Y_CURSOR, (199, 0)),
):
#print (cmd, param, len(param))
self.send_cmd(cmd)
if len(param) > 0:
self.send_data(bytearray(param))
self.wait_ready()
self.set_lut()
self.fill(1)
# Update the screen
# THRE MUST BE A MINIMUM OF 3 MINUTES (180 SECONDS) BETWEEN CALLS!!!
def show(self):
self.send_cmd(WRITE_RAM_BLACK)
self.send_data(self.buffer)
self.poweron()
- O desenho de elipses é recente e não está disponível na versão "estável".
- A escrita de texto é restrita a um fonte 8x8 que é inadequado para o display que estou usando

Nenhum comentário:
Postar um comentário