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