terça-feira, agosto 03, 2021

Usando Display LCD TTF de 2,4" com CircuitPython na Franzininho WiFi

Em um post anterior eu estudei a comunicação com este display, que é baseada em enviar de forma paralela oito bits de dados/comando. Para fins de teste, naquele post eu controlei um a um os sinais de dados. Mas isso é um gargalo, principalmente quando vamos programar em CircuitPython

Programando em C no Arduino, é fácil trabalhar num nível abaixo e acessar direto os registradores e atualizar os oito pinos de dados de uma vez. Nest post vamos ver a maneira "pythonica" de fazer isso.



O CircuitPython possui uma biblioteca nativa chamada displayio para interagir com displays gráficos. Especializações desta classe (chamadas de forma meio confusa de drivers) contém as sequências de iniciação para controladores específicos. O construtor da classe displayio recebe como parâmetro uma referência a um objeto DisplayBus,  que implementa a transferência de dados para o controlador do display. Exemplos de classes derivadas de DisplayBus são I2CDisplay, FourWire e ParallelBus, que implementam comunicação via I2C, SPI e de forma paralela. A implementação destas classes (principalmente ParallelBus) vai variar conforme a placa usada. Tipicamente, ParallelBus vai querer que os pinos de dados estejam mapeados em um mesmo registrador, o que limita os pinos que podem ser usados.

Vou usar aqui a Franzininho WiFi, que é baseado no ESP32-S2. A mesma forma de programação pode ser usada com outras placas que suportem suportem o CircuitPython e a classe ParallelBus. No ESP32-S2 é necessário que o bit zero de dados seja o pino IO8, o bit um o IO9 e assim por diante até o bit 7 ligado no IO15. Os demais sinais de controle podem ser conectados a qualquer pino de entrada ou saída, no meu teste usei as conexões abaixo:
  • RST: IO3
  • CS: IO4
  • RS: IO5
  • WR: IO6
  • RD: IO7
  • D0 a D7:  IO8 a IO15
  • GND: GND
  • 3V3: 3V3
Para um primeiro teste, já com o CircuitPython instalado na Franzininho, baixe as bibliotecas da Adafruit e instale adafruit_ili9341.mpy e adafruit_display_text/. no diretório lib da plaquinha.



O programa abaixo escreve "Olá Franzininho" no meio do display:
import board
import displayio
import terminalio
import adafruit_ili9341
from adafruit_display_text import label

displayio.release_displays()
display_bus = displayio.ParallelBus(data0=board.IO8,
                                    reset=board.IO3,
                                    chip_select=board.IO4,
                                    command=board.IO5,
                                    write=board.IO6,
                                    read=board.IO7)
display = adafruit_ili9341.ILI9341(display_bus, width=320, height=240)

text = "Olá, Franzininho"
font = terminalio.FONT
color = 0xFF0000
text_area = label.Label(font, text=text, color=color)
text_area.x = 100
text_area.y = 80
display.show(text_area)
Explicando o funcionamento:
  • release_displays() cancela displays que tenham sido criados, liberando os pinos associados.
  • displayio.ParallelBus cria o display bus, especificando os pinos usados (reparar que só data0 é especificado, é assumido que os demais são consecutivos)
  • display = adafruit_ili9341.ILI9341(display_bus, width=320, height=240) cria o objeto displayio que será usado para interagir com o display
  • label.Label cria uma área de texto que pode ser apresentada no display
  • display.show(text_area) apresenta a área de texto no display
O resultado é:


Usando outras classes e métodos podemos montar telas mais complexas:
import board
import displayio
import terminalio
import adafruit_ili9341
from adafruit_display_text import label
from adafruit_display_shapes.roundrect import RoundRect
from adafruit_display_shapes.rect import Rect
from random import randrange

# Inicia o display
displayio.release_displays()
display_bus = displayio.ParallelBus(data0=board.IO8,
                                    reset=board.IO3,
                                    chip_select=board.IO4,
                                    command=board.IO5,
                                    write=board.IO6,
                                    read=board.IO7)
display = adafruit_ili9341.ILI9341(display_bus, width=320, height=240)

# Cria um grupo
splash = displayio.Group()
display.show(splash)

# Constroi um fundo e acrescenta ao grupo
color_bitmap = displayio.Bitmap(320, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x3FFF5F
bg_sprite = displayio.TileGrid(color_bitmap, x=0, y=0, pixel_shader=color_palette)
splash.append(bg_sprite)

# Desenha um retângulo com bordas arredondadas
roundrect = RoundRect(80, 10, 161, 41, 10, fill=0x0000FF, outline=0x00, stroke=4)
splash.append(roundrect)

# Coloca um texto dentro do retângulo
text = "DQSoft"
font = terminalio.FONT
color = 0xFFFFFF
text_area = label.Label(font, text=text, color=color)
text_area.x = 140
text_area.y = 30
splash.append(text_area)

# Vamos fazer um gráfico de barras aleatórias
for x in range(20, 300, 20):
    y = randrange (30, 180)
    color1 = randrange (0, 180)
    color2 = randrange (0, 180)
    color3 = randrange (0, 180)
    interior = (color1 << 16)+(color2 << 8)+color3
    rect = Rect(x, 230-y, 16, y, fill=interior, outline=0, stroke=2)
    splash.append(rect)

O resultado deste segundo programa é:

 

Maiores detalhes sobre o uso de displays com o CircuitPython pode ser visto no site da Adafruit.

Nenhum comentário: