Skip to Content

CrowPanel 2.8″ ESP32 Display : Guia de Configuração Fácil

CrowPanel 2.8″ ESP32 Display : Guia de Configuração Fácil

Neste tutorial vais aprender como começar a utilizar o CrowPanel 2.8″ ESP32 Display da ELECROW. Os displays CrowPanel são ótimos, pois já trazem praticamente tudo o que precisas integrado. Isto inclui o ecrã TFT touch, um ESP32, um slot para cartão TF, um conector de bateria com carregador, uma interface I2C e até uma interface para altifalante.

No entanto, dependendo da tua experiência, os primeiros passos podem ser um pouco desafiantes. Espero que este guia de configuração te ajude. Vou focar-me especificamente na versão de 2.8″, mas a informação também se aplica às versões de 2.4″ e 3.5″. Os outros ecrãs maiores da série CrowPanel, no entanto, usam drivers de display diferentes.

Vamos então começar.

Componentes Necessários

Os componentes necessários incluem obviamente o display e, se quiseres ligar algum hardware externo, alguns cabos, resistores, LEDs e uma breadboard vão ser úteis.

CrowPanel 2.8″ ESP32 Display

Cabo USB C

Dupont wire set

Conjunto de Cabos Dupont

Half_breadboard56a

Breadboard

Kit de Resistores & LEDs

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Características do CrowPanel 2.8″ ESP32 Display

O CrowPanel 2.8″ ESP32 Display da ELECROW é um ecrã tátil resistivo HMI com um display TFT de resolução 320*240. Utiliza o módulo ESP32-WROOM-32 como processador de controlo, que já traz WiFi e Bluetooth integrados.

Frente do CrowPanel 2.8″ ESP32 Display (source)

Além disso, a placa tem um slot para cartão TF, uma interface UART, uma interface I2C, uma interface para altifalante, um conector de bateria com capacidade de carregamento e uma pequena porta GPIO com dois pinos GPIO. Vê o pinout abaixo:

Pinout do CrowPanel 2.8″ ESP32 Display (source)

A tabela seguinte resume a que pinos GPIO estão atribuídas as três interfaces IO. Para outros pinos GPIO consulta o esquema elétrico no anexo deste artigo.

GPIO_DIO25; IO32
UARTRX(IO16); TX(IO17)
I2CSDA(IO22); SCL(IO21)

Podes alimentar a placa através da porta USB (5V, 2A) ou ligando uma bateria LiPo de 3.7V ao conector BAT. Se o cabo USB e a bateria estiverem ligados ao mesmo tempo, a placa carrega a bateria. A corrente máxima de carregamento é de 500mA.

A placa suporta vários ambientes de desenvolvimento como Arduino IDE, Espressif IDF, Lua RTOS e Micro Python, e é compatível com a biblioteca LVGL de gráficos. No entanto, neste tutorial vou focar-me no Arduino IDE e na biblioteca TFT_eSPI de gráficos.

Série de Displays CrowPanel ESP32

O CrowPanel 2.8″ ESP32 Display faz parte de uma família de displays que vai desde 2.4 polegadas até 7 polegadas. Para uma visão geral vê a tabela abaixo.

CrowPanel ESP32 Displays
CrowPanel ESP32 Displays (source)

Neste tutorial, vou descrever especificamente a configuração da versão de 2.8″. Mas os exemplos de código e o procedimento de configuração são basicamente os mesmos para o 2.4″ display e o 3.5″ display, já que usam o mesmo ou um driver de display semelhante (ILI9341, ILI9488). Vê as secções a amarelo na tabela acima.

No entanto, como estou a usar a biblioteca TFT_eSPI, os exemplos de código provavelmente não vão funcionar nos displays maiores (4.3″, 5″, 7″), pois os drivers desses displays não são suportados – pelo que sei. Corrijam-me se estiver enganado, pois nunca testei.

Antes de implementares gráficos mais avançados, sugiro que testes primeiro o upload e execução de um simples programa de blink. E é sobre isso a próxima secção.

Testar GPIO

O display vem com uma demo de UI que corre assim que ligas a placa. É um bom primeiro teste. Depois disso, queremos testar se conseguimos fazer upload e correr o nosso próprio código. O exemplo típico para isto é o programa Blink.

Como o display não tem LED integrado, vamos usar os dois pinos GPIO disponíveis na porta GPIO_D para controlar dois LEDs externos. O diagrama de ligações abaixo mostra como ligar os dois LEDs à porta. Podes usar o cabo fornecido com o display para isso.

Wiring for blinking two LEDs
Ligações para piscar dois LEDs

Os pinos na porta GPIO_D são: IO25; IO32, 3.3V, GND. Não precisamos da saída de 3.3V, apenas dos dois pinos GPIO e do GND. Ao montar o circuito, não te esqueças dos resistores de 220Ω para limitar a corrente nos LEDs e certifica-te que o GND está bem ligado.

Depois disso, podes fazer upload do seguinte código que faz piscar os dois LEDs alternadamente. Também imprime no Serial monitor, por isso, se houver algum problema nas ligações, pelo menos consegues verificar se o programa está a correr. Garante que a baud rate do Serial monitor está definida para 115200.

const int led1 = 25;
const int led2 = 32;

void setup() {
  Serial.begin(115200);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
}

void loop() {
  Serial.println("on");
  digitalWrite(led1, HIGH);
  digitalWrite(led2, LOW);
  delay(1000);

  Serial.println("off");
  digitalWrite(led1, LOW);
  digitalWrite(led2, HIGH);
  delay(1000);
}

Como o display usa um ESP32, vais precisar de ter o core do ESP32 instalado. Se tiveres dificuldades com isso, vê o nosso tutorial A Beginner’s Guide To ESP32 Programming, onde explicamos como fazer.

Nota que existem duas versões da placa de display. A versão antiga V1 obriga-te a manter o botão BOOT pressionado e depois carregar no botão RESET para entrar em modo de programação. A nova versão V2 já não precisa disso. Eu tenho a versão V2 e consegui fazer upload sem problemas ou necessidade de pressionar botões.

Configurar a biblioteca TFT_eSPI via User_Setup.h

Até agora tudo deve ter sido fácil. Agora vem a parte difícil. Se quiseres mostrar algo no display, vais precisar de usar uma biblioteca gráfica. A mais comum é provavelmente a biblioteca TFT_eSPI do Bodmer. Encontras-la no Library Manager e podes instalá-la normalmente por lá:

TFT_eSPI library in Library Manager
Biblioteca TFT_eSPI no Library Manager

A parte difícil é configurar os parâmetros certos para o display CrowPanel 2.8″ para que a biblioteca TFT_eSPI funcione. Para isso, tens de encontrar um ficheiro chamado User_Setup.h, que faz parte da biblioteca TFT_eSPI. Normalmente, no Windows estará num caminho semelhante a este

C:\Users\stefa\OneDrive\Documents\Arduino\libraries\TFT_eSPI

O caminho exato depende do teu nome de utilizador (no meu caso “stefa“) e do teu sistema operativo e se usas OneDrive ou não. Vais ter de procurar.

Se abrires o ficheiro User_Setup.h vais ver uma quantidade enorme de definições que têm de estar corretas para o display mostrar alguma coisa. Boa sorte com isso!

User_Setup.h
User_Setup.h

É surpreendentemente difícil encontrar a configuração certa e tenho de agradecer ao Ralph S Bacon e ao seu TFT 3.5″ Touch Screen & ESP32 built in – Elecrow review que me pouparam muito tempo de tentativa e erro. Aqui estão as definições de que precisas:

#define ILI9341_DRIVER
#define TFT_WIDTH  320
#define TFT_HEIGHT 240 

#define TFT_BACKLIGHT_ON HIGH
#define TFT_BL   27 
#define TFT_MISO 12
#define TFT_MOSI 13
#define TFT_SCLK 14
#define TFT_CS   15
#define TFT_DC    2 
#define TFT_RST  -1
#define TOUCH_CS 33

#define SPI_FREQUENCY        27000000
#define SPI_TOUCH_FREQUENCY   2500000
#define SPI_READ_FREQUENCY   16000000

#define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
#define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
#define SMOOTH_FONT

Segundo as especificações, o display de 2.8″ usa o driver ILI9341 e tem uma resolução de 320×240 pixels. Esta é a primeira parte das definições. Depois vem a atribuição dos pinos GPIO que controlam o display via SPI, e as definições de frequência do SPI. E por fim, as fontes disponíveis.

Tens de editar o ficheiro User_Setup.h, comentar tudo o resto (//) e garantir que só estas definições estão ativas. Sugiro que guardes o ficheiro original User_Setup.h com outro nome, por exemplo “User_Setup.h.bak” e simplesmente substituas tudo em User_Setup.h pelas definições acima.

Depois disso, deves conseguir correr qualquer um dos programas de exemplo que vêm com a biblioteca TFT_eSPI. O meu favorito é o programa Cellular_Automata:

Example programs of the TFT_eSPI library
Programas de exemplo da biblioteca TFT_eSPI

Definições para os Displays CrowPanel de 2.4″ e 3.5″

As definições para o display de 2.4″ são iguais às do display de 2.8″ acima, já que o de 2.4″ tem a mesma resolução (320×240) e driver de display (ILI9341). Para o display CrowPanel maior de 3.5″ só tens de ajustar o driver (ILI9488) e as definições de resolução (480×320) para corresponder às suas especificações:

#define ILI9488_DRIVER
#define TFT_WIDTH  480
#define TFT_HEIGHT 320 

Os displays CrowPanel de 4.3″, 5″ e 7″ usam drivers que não são suportados diretamente pela biblioteca TFT_eSPI. Portanto, pelo que sei, não podes usar esta biblioteca com esses displays, mas não cheguei a testar.

Configurar a biblioteca TFT_eSPI via tft_setup.h

Modificar as definições em User_Setup.h serve para experimentar os exemplos da biblioteca TFT_eSPI. Mas não é uma boa abordagem quando estás a escrever e a fazer upload do teu próprio código. A razão é que, sempre que escreves código para um display diferente ou reinstalas/atualizas a biblioteca TFT_eSPI, tens de mudar as definições em User_Setup novamente.

Felizmente, a biblioteca TFT_eSPI tem uma solução para isto. Em vez de alterares as definições em User_Setup.h, que afeta globalmente todos os projetos, podes adicionar um ficheiro chamado tft_setup.h ao teu projeto Arduino específico. Este ficheiro contém as mesmas definições descritas acima, mas só serão válidas para esse projeto. Ou seja, podes ter projetos diferentes com displays diferentes, sem ter de mudar User_Setup.h sempre que usas um display diferente.

Aqui está um exemplo de como funciona. Primeiro cria um novo projeto Arduino e guarda-o como “tft_test“, por exemplo. Isso vai criar uma pasta tft_test com um ficheiro tft_test.ino dentro:

Arduino Project Folder tft_test
Pasta do Projeto Arduino tft_test

Nesta pasta, cria agora um ficheiro chamado “tft_setup.h” – exatamente com este nome. A tua pasta de projeto deve ficar assim:

Pasta do Projeto Arduino com tft_setup.h

No teu Arduino IDE deves ver agora dois separadores; tft_test.ino e tft_setup.h que podes clicar para editar os ficheiros.

Arduino IDE with tft_test.ino and tft_setup.h tabs
Arduino IDE com separadores tft_test.ino and tft_setup.h

No ficheiro tft_setup.h copia todas as definições de display mostradas acima. O excerto seguinte é só um exemplo. Tens de copiar todas as definições.

#define ILI9341_DRIVER
#define TFT_WIDTH  320
#define TFT_HEIGHT 240 
..
#define LOAD_FONT8
#define LOAD_GFXFF  
#define SMOOTH_FONT

No ficheiro tft_test.ino copia o seguinte código. Este é um pequeno teste que usa a biblioteca TFT_eSPI para mostrar o texto “Makerguides” no centro do ecrã.

#include "tft_setup.h"
#include"TFT_eSPI.h"

TFT_eSPI tft = TFT_eSPI();

void setup(void) {
  tft.init();
  tft.fillScreen(TFT_BLACK);  
}

void loop() {
  tft.setCursor(50, 150, 2);  
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.setTextSize(2);
  tft.println("Makerguides");
  delay(5000);
}

Nota que tft_setup.h está incluído no topo do programa. O código em si é fácil de perceber. Criamos um objeto TFT_eSPI e inicializamo-lo na função setup(). Na função loop, definimos o cursor e a fonte (2), a cor e o tamanho do texto, e finalmente imprimimos a string “Makerguides” no display TFT.

Se compilares e fizeres upload deste programa, deves ver o seguinte no teu display:

Text "Makerguides" shown on display
Texto “Makerguides” mostrado no display

Se chegaste até aqui, parabéns! O pior já passou. Nas próximas secções vais aprender como ler dados do touch para calibrar o ecrã tátil e como construir uma interface de utilizador simples.

Calibrar o Ecrã Tátil

O CrowPanel 2.8″ Display vem com um ecrã tátil resistivo que precisas de calibrar primeiro, antes de o usares com a biblioteca TFT_eSPI. Alguns exemplos de código da biblioteca TFT_eSPI já têm o código de calibração integrado, mas é chato ter isso em todos os projetos.

Extrair parâmetros de calibração

Por isso, adaptei o seguinte programa a partir dos exemplos, que extrai os parâmetros de calibração relevantes:

#include "tft_setup.h"
#include "TFT_eSPI.h"

TFT_eSPI tft = TFT_eSPI();

void setup() {
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(0);
}

void loop() {
  uint16_t cal[5];

  tft.fillScreen(TFT_BLACK);
  tft.setCursor(20, 0);
  tft.setTextFont(2);
  tft.setTextSize(1);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.print("Touch corners ... ");
  tft.calibrateTouch(cal, TFT_MAGENTA, TFT_BLACK, 15);
  tft.println("done.");

  Serial.printf("cal: {%d, %d, %d, %d, %d}\n",
                cal[0], cal[1], cal[2], cal[3], cal[4]);
  delay(10000);
}

Quando o executares, ele pede-te para tocares nos quatro cantos do ecrã e depois imprime os 5 parâmetros de calibração (coordenadas dos cantos e orientação do ecrã) no Serial.monitor. O teu display durante a calibração deve ficar assim:

Calibration of touch screen
Calibração do ecrã tátil

E no Serial.monitor deves ver algo assim impresso, quando a calibração terminar:

  cal: {286, 3478, 196, 3536, 2}

A calibração repete-se a cada 10 segundos, por isso podes tentar várias vezes para obter os parâmetros mais precisos. Copia-os para algum lado, pois vais precisar deles no próximo passo.

Ler coordenadas do touch

Nesta secção vamos implementar um pequeno programa para ler a coordenada onde o display é tocado. Vê o código seguinte:

#include "tft_setup.h"
#include "TFT_eSPI.h"

TFT_eSPI tft = TFT_eSPI();
uint16_t cal[5] = { 286, 3478, 196, 3536, 2 };

void setup() {
  tft.begin();
  tft.setRotation(0);
  tft.setTextSize(2);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.fillScreen(TFT_BLACK);
  tft.setTouch(cal);
}

void loop() {
  uint16_t x = 0, y = 0;

  if (tft.getTouch(&x, &y)) {
    tft.setCursor(50, 150);
    tft.printf("x=%d, y=%d    ", x, y);
  }

  delay(100);
}

Primeiro, incluímos as bibliotecas como habitual e criamos o objeto do ecrã. A linha seguinte é importante. Aqui definimos e guardamos o parâmetro de calibração que extraímos antes:

uint16_t cal[5] = { 286, 3478, 196, 3536, 2 };

Depois disso, na função setup definimos os parâmetros típicos do display como rotação do ecrã, tamanho e cor do texto. No fim vem a linha mais importante, onde realmente definimos os parâmetros de calibração:

  tft.setTouch(cal);

O loop principal é simples. A cada 100ms chamamos tft.getTouch e verificamos se foi detetado um toque. Se for o caso, mostramos as coordenadas do toque no ecrã. O teu ecrã deve ficar assim:

Reading and displaying touch coordinates
Ler e mostrar coordenadas do touch

E com isto já temos tudo para construir uma Interface de Utilizador. As próximas secções mostram um exemplo simples disso.

Construir uma Interface de Utilizador

Nesta secção vamos construir uma Interface de Utilizador (UI) simples com dois botões que nos vão permitir controlar os dois LEDs que ligámos antes à porta GPIO_D. A Interface de Utilizador vai ficar assim:

UI with two Buttons to control the LEDs
UI com dois botões para controlar os LEDs

No entanto, antes de podermos implementar esta UI precisamos de instalar mais uma biblioteca. A biblioteca TFT_eWidget é uma pequena extensão da biblioteca TFT_eSPI que fornece elementos de UI como botões, medidores ou gráficos. Pode ser instalada normalmente através do Library Manager:

TFT_eWidget library in Library Manager
Biblioteca TFT_eWidget no Library Manager

Depois de instalada, temos tudo o que precisamos. Vê o código completo da UI primeiro, antes de discutirmos os detalhes:

#include "tft_setup.h"
#include "TFT_eSPI.h"
#include "TFT_eWidget.h"

TFT_eSPI tft = TFT_eSPI();
uint16_t cal[5] = { 286, 3478, 196, 3536, 2 };

const int led1 = 25;
const int led2 = 32;

ButtonWidget btn1 = ButtonWidget(&tft);
ButtonWidget btn2 = ButtonWidget(&tft);
ButtonWidget* btns[] = { &btn1, &btn2 };

void btn1_pressed(void) {
  if (btn1.justPressed()) {
    bool state = !btn1.getState();
    btn1.drawSmoothButton(state, 2, TFT_WHITE, state ? "ON" : "OFF");
    digitalWrite(led1, state ? HIGH : LOW);
  }
}

void btn2_pressed(void) {
  if (btn2.justPressed()) {
    bool state = !btn2.getState();
    btn2.drawSmoothButton(state, 2, TFT_WHITE, state ? "ON" : "OFF");
    digitalWrite(led2, state ? HIGH : LOW);
  }
}

void initButtons() {
  uint16_t w = 100;
  uint16_t h = 50;
  uint16_t x = (tft.width() - w) / 2;
  uint16_t y = tft.height() / 2 - h - 10;

  btn1.initButtonUL(x, y, w, h, TFT_WHITE, TFT_BLACK, TFT_YELLOW, "LED1", 2);
  btn1.setPressAction(btn1_pressed);
  btn1.drawSmoothButton(false, 2, TFT_BLACK);

  y = tft.height() / 2 + 10;
  btn2.initButtonUL(x, y, w, h, TFT_WHITE, TFT_BLACK, TFT_GREEN, "LED2", 2);
  btn2.setPressAction(btn2_pressed);
  btn2.drawSmoothButton(false, 2, TFT_BLACK);
}

void handleButtons() {
  uint8_t nBtns = sizeof(btns) / sizeof(btns[0]);
  uint16_t x = 0, y = 0;
  bool touched = tft.getTouch(&x, &y);
  for (uint8_t b = 0; b < nBtns; b++) {
    if (touched) {
      if (btns[b]->contains(x, y)) {
        btns[b]->press(true);
        btns[b]->pressAction();
      }
    } else {
      btns[b]->press(false);
      btns[b]->releaseAction();
    }
  }
}

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);

  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
  tft.setTouch(cal);
  
  initButtons();2
}

void loop() {
  handleButtons();
  delay(50);
}

A UI vai ter os seguintes cinco estados ou ecrãs: os dois botões inicializados e depois em estado ligado ou desligado.

Different screens of the UI
Diferentes ecrãs da UI

Vamos ver mais de perto como isto é feito.

Bibliotecas

Primeiro, instalamos as três bibliotecas necessárias. Lembra-te que “tft_setup.h” é o ficheiro que contém as definições para o display TFT e tem de fazer parte do projeto Arduino que contém o código acima.

#include "tft_setup.h"
#include "TFT_eSPI.h"
#include "TFT_eWidget.h"

No entanto, se tiveres as definições corretas do display em User_Setup.h, não precisas de incluir o ficheiro tft_setup.h.

Constantes e Objetos

De seguida, criamos o objeto do display via TFT_eSPI tft e uma constante cal com os parâmetros de calibração. Depois definimos os pinos GPIO para os dois LEDs. A seguir, criamos os dois objetos botão btn1 e btn2.

TFT_eSPI tft = TFT_eSPI();
uint16_t cal[5] = { 286, 3478, 196, 3536, 2 };

const int led1 = 25;
const int led2 = 32;

ButtonWidget btn1 = ButtonWidget(&tft);
ButtonWidget btn2 = ButtonWidget(&tft);
ButtonWidget* btns[] = { &btn1, &btn2 };

Guardamos os dois botões num array btns, pois isso vai simplificar o tratamento dos eventos. Mais sobre isso à frente.

Gestores de Pressão dos Botões

As funções btn1_pressed() e btn2_pressed() tratam os toques em cada botão LED. Quando um botão é pressionado, o estado do LED correspondente é alternado e a aparência do botão é atualizada no ecrã. Abaixo está apenas o código para btn1 mas o código para btn2 é basicamente igual, só muda o LED que é acionado.

void btn1_pressed(void) {
  if (btn1.justPressed()) {
    bool state = !btn1.getState();
    btn1.drawSmoothButton(state, 2, TFT_WHITE, state ? "ON" : "OFF");
    digitalWrite(led1, state ? HIGH : LOW);
  }
}

Inicialização dos Botões

A função initButtons() define a posição, aparência e ações dos dois botões no ecrã TFT. Cada botão é inicializado com propriedades específicas e a sua ação de pressão. Fazemos o botão do LED amarelo, amarelo (TFT_YELLOW) e o do LED verde, verde (TFT_GREEN).

void initButtons() {
  ...
  btn1.initButtonUL(x, y, w, h, TFT_WHITE, TFT_BLACK, TFT_YELLOW, "LED1", 2);
  btn1.setPressAction(btn1_pressed);
  btn1.drawSmoothButton(false, 2, TFT_BLACK);

  ...
  btn2.initButtonUL(x, y, w, h, TFT_WHITE, TFT_BLACK, TFT_GREEN, "LED2", 2);
  btn2.setPressAction(btn2_pressed);
  btn2.drawSmoothButton(false, 2, TFT_BLACK);
}

Gestão dos Botões

Na função handleButtons(), verificamos o input do touch no ecrã TFT via tft.getTouch(). Iteramos por todos os botões e chamamos a pressAction() ou a releaseAction() com base nas coordenadas do toque.

void handleButtons() {
  ...
  bool touched = tft.getTouch(&x, &y);
  for (uint8_t b = 0; b < nBtns; b++) {
    if (touched) {
      if (btns[b]->contains(x, y)) {
        btns[b]->press(true);
        btns[b]->pressAction();
      }
    } else {
      btns[b]->press(false);
      btns[b]->releaseAction();
    }
  }
}

Os botões que criámos não têm ação de release associada, pois aqui não é necessário. Mas para manter o código genérico, ainda chamamos releaseAction(). Isto tem a vantagem de o código funcionar sem alterações, caso queiras usar ações de release no futuro.

Função Setup

Na função setup(), configuramos os pinos dos LEDs como outputs, inicializamos o ecrã TFT, definimos a rotação, preenchemos o ecrã de preto, definimos a calibração do touch e criamos os botões.

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);

  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
  tft.setTouch(cal);
  
  initButtons();
}

Função Loop

A função loop() verifica continuamente as interações com os botões chamando handleButtons() e introduz um pequeno delay para evitar pressões rápidas nos botões.

void loop() {
  handleButtons();
  delay(50);
}

Nota que ao chamar delay() bloqueias todas as outras ações. Em alternativa, podes fazer algo assim para evitar o bloqueio:

void loop() {
  static uint32_t lastTime = millis();
  if (millis() - lastTime >= 50) {
    handleButtons();
    lastTime = millis();
  }
}

E pronto, aqui tens uma UI simples para controlar dois botões a partir de um CrowPanel 2.8″ ESP32 Display.

O exemplo de código acima é derivado do exemplo Button_demo.ino da biblioteca TFT_eWidget. Para mais informações e exemplos adicionais vê lá.

Conclusão

Este tutorial forneceu um guia de configuração detalhado para o CrowPanel 2.8″ ESP32 Display. Com poucas ou nenhumas alterações, este guia também se aplica aos displays de 2.4″ e 3.5″.

As placas CrowPanel ESP32 Display trazem praticamente tudo o que precisas para um projeto que envolva um display. Inclui um ecrã TFT touch, um ESP32, slot para cartão TF, conector de bateria com carregador, interface para altifalante e interface I2C.

No entanto, isto também significa que o número de pinos GPIO livres é limitado a apenas dois. Mas como existe uma interface I2C, podes usar um expansor de GPIO para adicionar mais pinos. Vê o nosso tutorial Using GPIO Expander MCP23017 With Arduino.

Trabalhar com displays é muitas vezes complicado, pois precisas do driver e das definições corretas. Neste guia de configuração aprendeste como configurar a biblioteca TFT_eSPI.h para controlar o CrowPanel 2.8″ Display. Usámos ainda a biblioteca de extensão TFT_eWidget para implementar uma UI simples com dois botões para controlar dois LEDs. Vê o tutorial Digital Clock with CrowPanel 3.5″ ESP32 Display onde estendemos o código de exemplo deste tutorial para construir um Display de Relógio Digital.

Se precisares de UIs mais avançadas, a biblioteca LVGL é uma melhor escolha, pois tem mais widgets e um software GUI Builder. No entanto, também é muito mais complexa de configurar e usar. Para mais informações, vê os tutoriais no site da ELECROW. Há código de exemplo Arduino para LVGL, mas também exemplos para ESP-IDF, ESPHome, PlatformIO e MicroPython.

Se quiseres usar LVGL, vê também os CrowPanel ESP32 Display Video Tutorials que explicam como usar o Squareline Studio GUI builder. Nota que existe uma versão gratuita, embora limitada (Personal plan) deste GUI builder.

Há muito para explorar! Diverte-te ; )

Links

Aqui ficam alguns links que achei úteis ao escrever este guia.

Esquemas Elétricos

Extraí os seguintes esquemas da placa a partir do link CrowPanel 2.8″-ESP32 Display Schematics. Parece que alguns exemplos de código usam pinos errados ou desatualizados e, neste caso, os esquemas ajudam a esclarecer as coisas.

Schematic USB Type-C
Esquema USB Type-C
Schematic USB
Esquema USB
Schematic Battery port and charger
Esquema do conector de bateria e carregador
Schematic Power
Esquema de alimentação
Schematic ESP32-WROOM-32-N4
Esquema ESP32-WROOM-32-N4
Schematic LCD Connector
Esquema do conector LCD
Schematic Speaker
Esquema do altifalante
Schematic GPIO_D
Esquema da porta GPIO_D
Schematic I2C
Esquema da porta I2C
Schematic UART
Esquema da porta UART
Schematic TF Card
Esquema do cartão TF
Schematic XPT2046
Esquema XPT2046