Vamos fazer um contador com display LCD, contando cada pressionada em um botão. Usaremos um tradicional display LCD 16×2 que comunica via i2c com um microcontrolador ESP32-C6.
A ideia do projeto é demonstrar alguns conceitos diferentes, usados em projetos com microcontroladores. Falaremos sobre como ler botões ou sensores digitais com as portas do Arduino/ESP32. Falaremos também sobre como controlar um display LCD via protocolo i2c.
Também conversaremos um pouco sobre máquinas de estados, que é exatamente a forma como vamos controlar o código do projeto. O projeto vai contar com as seguintes entradas e saídas:
- Um botão push button para incrementar a contagem no display
- Um botão push button para zerar a contagem no display
- Um LED para indicar que o botão de incrementar foi pressionado
- Um display LCD para montar a contagem de pressionadas do botão e também um texto à sua escolha
Vai funcionar assim: haverá um contador na tela LCD, que começa em zero (0). A cada vez que você pressionar o botão de incremento, será somado um (1) ao valor mostrado na tela. Essa contagem não tem fim, pode ir até estourar a variável “counter”.
Em qualquer momento você pode pressionar o botão de zerar, que a contagem na tela voltará para zero (0). Há uma proteção para que caso o botão de incrementar fique pressionado, a contagem não aumenta. Ela só aumentar uma unidade por vez que o botão for pressionado.
O LED no pino D0 do ESP32-C6 é ligado e desligado alternadamente, toda vez que se pressiona o botão de incremento. São mostrados dois textos fixos no display LCD, na linha de cima “<- contador” e na linha de baixo “FritzenLab blog”. Na linha de cima, logo nos primeiros quatro espaços fica o contador incremental.
A preparação
Alguns passos são necessários para chegarmos no objetivo final do projeto. Nós vamos precisar do software IDE do Arduino, que você pode baixar em Arduino.cc. Precisaremos também de uma biblioteca dentro da IDE do Arduino, a LiquidCrystal_I2C de “Frank de Brabander”.
Para termos um ponto de partida sobre o display LCD com i2c, eu escolhi este tutorial do pessoal do LastMinuteEngineers. Recomendo a leitura. Vamos precisar também conhecer um pouco sobre debounce de entradas digitais, com este tutorial do meu outro blog (em Inglês).
Como conhecimento nunca é demais, dê uma olhada neste outro artigo sobre display LCD. Também vale a leitura. Sobre o microcontrolador escolhido, que foi o ESP32-C6. Eu apenas escolhi ele pois tenho vários em bancada, é bem pequeno e poderoso. Tem Wi-Fi mas não vamos usar hoje.

Você poderia ter escolhido literalmente qualquer outro microcontrolador compatível com Arduino, visto que a esmagadora maioria deles tem porta i2c disponível. Por exemplo o Arduino UNO, Arduino Leonardo, Digispark Attiny85, etc. Basta você estar confortável usando o microcontrolador, de resto eu te ensino por aqui mesmo.
Hardware
Como de costume aqui no blog, as minhas montagens são bem simples e diretas, poucos fios pra cá e pra lá na protoboard. Neste projeto não é diferente, temos um ESP32, um display LCD, um LED e dois botões push button.
O LED vai no pino D0 com um resistor série de 680 Ohm. Os dois botões push button vão nos pinos D1 (incrementar) e D2 (zerar), sem resistores. Isto porque o ESP32-C6 tem resistores de pull-up internos, economizando em hardware.
O display LCD i2c (compre aqui) é alimentado com 5V, seus dois pinos de comunicação (SDA e SCL) vão nos pinos D4 e D5 do ESP32-C6. O diagrama esquemático completo está abaixo, bem como uma foto da montagem.


Eu fiz a montagem em uma protoboard de 400 furos, pois minha placa ESP32 (que eu mesmo fiz) comporta tal diminuição de espaço.
Firmware/código
A única biblioteca que você precisa instalar na sua IDE do Arduino é a “LiquidCrystal_I2C”. Demais funções como ler entradas digitais e escrever em saídas digitais são nativas ao Arduino. Eu faço bom uso da função IF() para tomar decisões no código. Para ler o pressionar do botão, faço um IF() que verifica se o botão está pressionado e se o estado anterior era não pressionado.
O código completo está abaixo e também neste Github, pode acessar e copiar de lá. Uma das funções mais legais que implementei é o controle de atualização do display. Eu só atualizo o display quando o contador tiver um número novo, ou seja, o botão tiver sido pressionado. Caso contrário o display não é atualizado.
// with info from https://lastminuteengineers.com/i2c-lcd-arduino-tutorial/
// To figure i2c address, I used this: https://www.usinainfo.com.br/blog/como-descobrir-o-endereco-i2c-arduino/
// My 16x2 LCD display is at address 0x3D
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3D,16,2); // set the LCD address to 0x3D for a 16 chars and 2 line display
#define LED 2 // 2 for Xiao ESP32-C3 or D0 for Xiao ESP32-C6
#define BUTTON 3 // 3 for Xiao ESP32-C3 or D1 for Xiao ESP32-C6
#define RESET 4 // 4 for Xiao ESP32-C3 or D2 for Xiao ESP32-C6
long whenPressed= 0;
bool previousState= false;
bool lastState= false;
long lcdTimer= 0;
int counter= 0;
int currentCounter= -1;
void setup() {
Wire.begin(6, 7); // SDA = GPIO6, SCL = GPIO7
pinMode(LED, OUTPUT);
pinMode(BUTTON, INPUT_PULLUP);
pinMode(RESET, INPUT_PULLUP);
Serial.begin(115200);
lcd.init();
lcd.clear();
lcd.backlight(); // Make sure backlight is on
}
void loop() {
if(!digitalRead(BUTTON) && previousState == false){ // increments counter if the button is pressed and
//300ms have passed since the last press
previousState= true;
whenPressed= millis();
counter++;
if(lastState == true){ // alternates an LED ON and OFF for every button press
digitalWrite(LED, LOW);
lastState= false;
}else{
digitalWrite(LED, HIGH);
lastState= true;
}
}else if(!digitalRead(RESET)){ // if reset button was pressed, zero counter
counter= 0;
}
if((millis() - whenPressed >= 300) && digitalRead(BUTTON)){ // allows a new button press only after 300ms of the previous one
// there is also a protection to avoid incrementing the counter if the button is kept pressed
previousState= false;
}
//if(millis() - lcdTimer > 500){ // update display every 500ms
if(currentCounter != counter){ // update display every 500ms
lcdTimer= millis();
currentCounter= counter; // makes sure that the display is updated only when there is new information
lcd.clear();
lcd.setCursor(0,0); //Set cursor to character 2 on line 0
lcd.print(counter);
lcd.setCursor(4, 0); // Set cursor to character 4 on line 0
lcd.print(" <- contador");
lcd.setCursor(0, 1); // Set cursor to character 1 on line 1
lcd.print("FritzenLab blog");
}
}
O display LCD é atualizado a cada 500ms (0,5 segundos), também através de uma função IF(). A parte mais “simples do código é que eu faço o zeramento da contagem apenas lendo o botão de reset. Nada complexo, somente leio o botão e caso ele esteja pressionado, faço “counter= 0”.
Importante ressaltar que meu código é não bloqueante, o que significa que ele não usa a função delay(). Eu realmente faço tudo atráves do uso da função IF(). Isto garante que o código não vai ficar travado em lugar nenhum, esperando por algo acontecer.
Contador com display LCD
Após copiar o código acima para sua IDE do Arduino, clique no botão “upload” que está no canto superior esquerdo da tela. Sua placa Arduino já deve estar conectada ao computador via USB. Você deve também já ter selecionado a mesma no menu suspenso, na parte superior da tela.
Após alguns segundos seu código começará a ser executado, você verá um contador zerado (0) no display LCD. Pressione o botão push button de incremento e veja o número na tela sendo incrementado. Eu fiz dois vídeos sobre o funcionamento deste experimento, veja no início do artigo e logo aqui abaixo.






Pingback: ESP32 uso profissional - Access point AP - Fritzenlab eletrônica