Menu com telas LCD ST7920 – ESP32

Menu com telas LCD ST7920 – ESP32

O LCD ST7920 é um display que tem um custo-benefício gigantesco se comparado com outros tipos de display e além disso possui uma ótima biblioteca compatível com ESP32 que é a biblioteca u8g2 que é a sucessora do u8glib.

Semelhante ao pôster do Menu com telas LCD ST7920 – Arduino em que utiliza o display gráfico porem a biblioteca é a u8g2 que é a biblioteca mais recente do olikraus e foi desenvolvida em 2016, e está tendo suporte e atualizações até o momento.

Se você gostar do projeto também temos o XPsys que é um sistema semelhante a este e utiliza a biblioteca u8g2, este sistema também é compatível com o arduino:

XPsys – Sistema de Tela com ST7920

Conheça o sistema que possui um menu de navegação com ícones e telas utilizando o ST7920.

Para esse menu é necessário 6 botões ou seja 6 pinos do ESP32 serão utilizados para a navegação do menu, caso você ache que este numero de botões sejam muito grandes basta fazer algumas modificações no código para diminui-los para isto leia a documentação em sua pagina. Cada botão pode ser configurado para executar um comando distinto dependendo o que você configura na programação de sua tela.

Você também pode baixar a biblioteca pelo site do XProjetos:

ícone

u8g2 – Biblioteca para Displays Gráficos 49,1MB 432 downloads

Esta é uma biblioteca desenvolvida pelo olikraus U8g2: Biblioteca para displays…

Você pode colocar muitos menus em sua programação, cheguei a testar 20 itens de menu e funcionou sem problemas, não sei qual é o limite de linhas para o menu e não consegui encontrar algo que informe em sua wiki, caso tenha duvidas de outras funcionalidades consulte a seção userInterfaceSelectionList.

Sobre o Display:

O display em si é um atrativo para integrá-lo em projetos onde espaço físico não seja problemas pois ele mede 7cm x 9,5cm e pesa por volta de umas 70g a 100g, o consumo de corrente muito pouco pois você consegue alimentá-lo com um USB de um computador. Seu valor atualmente (08/2017) gira em torno de R$55,00 a R$65,00 aqui no Brasil (Mercado Livre e também lojas físicas), no exterior(Aliexpress) está U$6,40 (R$20,00).

O display possui 20 pinos, e possui também interface de 4bits, 8 bits ou Serial que pode ser configurado a partir do pino 15, abaixo segue a descrição de cada pino do LCD:

Alguns fabricantes especificam o nome de cada pino no lado frontal ou no verso do display, dependendo da aplicação dificulta a visualização do nomes, o numero dos pinos seguem a sequencia sendo indicados pelos números 20 e 1, abaixo segue um exemplo de display que possui os nomes dos pino na parte frontal :

Também veja o datasheet para download do fabricante Sitronix que especifica profundamente as funções disponíveis neste modelo de LCD. Também existe o site do Arduino e Cia que explica os outros modos de transmissão dos dados (4bits e 8bits)

Esquema de ligação:

Para este projeto você irá necessitar de alguns componentes e que podem ser adaptados ao seu gosto e condições financeiras, lembrando de sempre utilizar componentes equivalentes.

  • 1 LCD ST7920
  • 1 ESP32
  • 1 LED de 3mm ou 5mm
  • 2 Trimpot ou potenciômetro de 10KΩ
  • 6 Botões de pulsar (Normalmente Abertos)
  • Cabos de conexões para protoboard
  • 2 Fontes DC uma de 5V e outra de 3,3V. (ou então utilize um regulador de 3,3V como o AMS1117 ou o LD1117-3.3 o GND deve ser o mesmo para as duas fontes)

A montagem deve ser a seguinte:

Atenção: O LCD deve ser alimentado com 5V porem o ESP32 deve ser alimentado com uma fonte de 3,3V, a comunicação entre o LCD e o ESP32 não necessita de resistores de divisor de tensão pois a corrente é limitada pelo LCD. INTERLIGUE os GND’s das duas fontes.

Ao montar no protoboard utilizei uma fonte que possui ambas as tensões reguladas tanto de 5V como 3,3V, com esse tipo de fonte deve se ter muito cuidado para não esquecer e alimentar seu ESP32 com 5V, isso pode danificá-lo. A montagem ficou a seguinte:

Montagem em Protoboard feita com o ST7920 e ESP32.

Galeria de Telas:

Programação:

A programação é semelhante ao arduino, porem acrescentei algumas funções a mais como leitura analógica de um potenciômetro e é mostrado na forma de uma barra dinâmica, também o controle do brilho de um LED em PWM porem com funções que são específicas para o ESP32, estas funções irei fazer um pôster separado explicando cada uma. A seguir segue a programação adaptada por mim do código original do Menu_list do olikrau

Basta copiar a programação e jogar na interface Arduíno IDE de programação e compilar, porem deve antes instalar os componentes para integrar o ESP32 a interface do Arduíno IDE:

/*
  Programa de seleção de Menu com telas, adaptado por JailsonBR do código original do olikraus.
   
  PORFAVOR NÃO REMOVA NENHUMA INFORMAÇÃO DESTE CABEÇARIO, ESTE É UM CÓDIGO OPENSOURCE SOB LICENÇA DO CRIADOR
   
  Codigo adaptado por JailsonBR do site XProjetos.net em 12-04-2019, o uso deste código é livre porem deve respeitar e mante o nome do criador
  e tambem de quem modificou o código o código está sob Licença Creative Commons Atribuição 4.0 Internacional. http://creativecommons.org/licenses/by/4.0/

  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)

  Copyright (c) 2016, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.
      
      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
      CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
      INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
      MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
      DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
      CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
      SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
      NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
      LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
      STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
      ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

  Copyright (c) 2019, XProjetos.net
*/

#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#define PinoAnalogico 34                                        //O compilador substituirá qualquer menção de PinoAnalogico ao valor 34 no momento da compilação.
#define PinoLED 15                                              //O compilador substituirá qualquer menção de PinoLED ao valor 15 no momento da compilação.


//PWM Setup para ESP32
int freq = 5000;                                                 //Frequencia para o PWM
int CanalLED = 0;
int resolution = 8;


U8G2_ST7920_128X64_1_SW_SPI u8g2(U8G2_R0, 18, 19, 21, 22);       //Enable, RW, RS, RESET  


byte menu_inicial = 1;                                           //Variável para armazenar a variável para chamar o menu principal
byte ValorPWM = 0;                                               //Variável para armazenar a variável para o PWM

int leituraADC = 0, AnaRead = 0;                                 //Variáveis para armazenar os valores analógicos

//Icones em XBMP para barra de icones (Gerados no GIMP)
static unsigned char bluetooth_bits[] = {
   0x10, 0x32, 0x54, 0x38, 0x38, 0x54, 0x32, 0x10 };

static unsigned char wifi_bits[] = {
   0x7e, 0x81, 0x3c, 0x42, 0x18, 0x00, 0x18, 0x18 };


//Lista do Menu Principal
const char *string_list =                                       //Lista de Menus, você pode adicionar mais itens se desejar
  "Barra de icones\n"
  "Leitura Analogica\n"
  "LED PWM\n"
  "XProjetos.net\n"
  "5. Item\n"
  "6. Item\n"
  "7. Item\n"
  "Final";

uint8_t current_selection = 1;                                 //Configura o primeiro item estar selecionado


/*******************************************************************
 *                       SETUP
 *****************************************************************/

void setup(void) {
  
  // MKR Zero Test Board
  u8g2.begin(/*Select=*/ 12, /*Right/Next=*/ 27, /*Left/Prev=*/ 25, /*Up=*/ 26, /*Down=*/ 14, /*Home/Cancel=*/ 13);  //Inicia os botões de navegação para o menu
  u8g2.setFont(u8g2_font_6x12_tr);               //Configura o tipo de Fonte
  
  pinMode(PinoAnalogico, INPUT);                     //Configura o pino PinoAnalogico para IO34 como entrada
  pinMode(PinoLED, OUTPUT);
  //------------------PWM ESP32--------------------                
  sigmaDeltaAttachPin(PinoLED,0);                //Inicializa o PWM e anexa o PinoLED para o canal 0
  sigmaDeltaSetup(CanalLED, freq);             //Configura a frequencia do canal 0 do PWM para 5000Hz
  sigmaDeltaWrite(CanalLED, 0);                //Inicia o PWM em zero (pode ser configurado de 0 a 255)
}


void loop(void) {  
  leituraADC = analogRead(PinoAnalogico);           //Leitura de porta analógica e armazenamento na variável
  u8g2.setCursor(0, 0);                         //Configura a posição do proximo item a ser escrito na tela
  u8g2.print(leituraADC);                       //Escreve o valor armazenado da porta analogica
  
  //=========================NAVEGACÃO============================
if ( menu_inicial == 1 ) {
  current_selection = u8g2.userInterfaceSelectionList( //Caso estiver no Menu Princinpal
    "Menu Principal",                                  //Titulo do Menu
    current_selection, 
    string_list
    );
}
  if ( current_selection == 0) {                       //Caso o botão voltar seja pressionado
    u8g2.userInterfaceMessage(                         // Exibir mensagem abaixo
	"Nada Selecionado.", 
	"",
	"",
	" ok ");
  } 
  //=====================FIM NAVEGACÃO============================

  
  //----------------TELA1 -  TELA DE EXEMPLO DE BARRA DE ICONES----------------- 
  if ( current_selection == 1 ) {
    menu_inicial = 0;
  u8g2.firstPage();
  do {
    int8_t event2 = u8g2.getMenuEvent();
    u8g2.drawRFrame(0,11,127,51,4);           //Desenha um quadro vazio com bordas  u8g2.drawRFrame(x,y,comprimento,altura,borda);
    u8g2.drawLine(0, 9, 127, 9);              //Desenha uma linha
    u8g2.drawXBM(0, 0, 8, 8, bluetooth_bits); //Desenha uma figura tipo XBM para o bluetooth
    u8g2.drawXBM(10, 0, 8, 8, wifi_bits);     //Desenha uma figura tipo XBM para o wifi  
    if (event2 == U8X8_MSG_GPIO_MENU_HOME) {  //Verifica se o botão de voltar/home foi pressionado.
        menu_inicial = 1;                     //Caso pressionado chama o menu principal
        current_selection = 0;
     }

  }while ( u8g2.nextPage() );                 //Condição para manter a tela
  current_selection = 1;                      //se caso current_selection estiver com o mesmo ID da tela a tela fica mantida (travada)
  }                                           // Fim Tela1

//----------------TELA2-----------------

  else if ( current_selection == 2 ) {      
    int8_t event2 = u8g2.getMenuEvent();
    menu_inicial = 0;
  u8g2.firstPage();
  do {
  leituraADC = analogRead(PinoAnalogico);     //Leitura de porta analógica e armazenamento na variável
  AnaRead = map(leituraADC, 0, 4095, 0, 120); //Faz uma equivalencia entre o maximo da porta analogica para a barra grafica
  u8g2.drawFrame(3,10,120,8);                 //Desenha um retangulo vazio para a barra gráfica
  u8g2.drawBox(3,10,AnaRead,8);               //Desenha um retangulo preenchido para a barra gráfica apartir do valor gerado do map
  u8g2.setCursor(0, 50);                      //Configura a posição do proximo item a ser escrito na tela
  u8g2.print(leituraADC);                     //Escreve o valor armazenado da porta analogica
  if (event2 == U8X8_MSG_GPIO_MENU_HOME) {    //Verifica se o botão de voltar/home foi pressionado.
        menu_inicial = 1;                     //Caso pressionado chama o menu principal
        current_selection = 0;
     } 
  }while ( u8g2.nextPage() );                 //Condição para manter a tela
  current_selection = 2;                      //se caso current_selection estiver com o mesmo ID da tela a tela fica mantida (travada)
  }                                           // Fim Tela2

//----------------TELA3-----------------

  else if ( current_selection == 3 ) {
    menu_inicial = 0;
  u8g2.firstPage();                           //buffer para exibição gráfica
  do {
  u8g2.drawFrame(1,10,126,8);                 //Desenha um retangulo vazio para a barra gráfica
  u8g2.drawBox(3,10,ValorPWM / 2,8);          //Desenha um retangulo preenchido para a barra gráfica apartir do valor gerado do ValorPWM
  sigmaDeltaWrite(0, ValorPWM);               //Valor dado para a variável ValorPWM é enviado ao canal 0 de PWM
  u8g2.setCursor(0, 50);                      //Configura a posição do proximo item a ser escrito na tela
  u8g2.print(ValorPWM);                       //Escreve o valor armazenado do PWM
  
  int8_t event2 = u8g2.getMenuEvent();
  if (event2 == U8X8_MSG_GPIO_MENU_NEXT || event2 == U8X8_MSG_GPIO_MENU_UP) {     //Verifica se o botão de subir/avançar foi pressionado.
        ValorPWM++;                                                               //Incrementa o ValorPWM aumentando o brilho do LED
  }
  if (event2 == U8X8_MSG_GPIO_MENU_PREV || event2 == U8X8_MSG_GPIO_MENU_DOWN) {  //Verifica se o botão de subir/avançar foi pressionado.
       ValorPWM--;                                                               //Incrementa o ValorPWM aumentando o brilho do LED
  }
    if (event2 == U8X8_MSG_GPIO_MENU_HOME) {  //Verifica se o botão de voltar/home foi pressionado.
        menu_inicial = 1;                     //Caso pressionado chama o menu principal
        current_selection = 0;
     } 
  }while ( u8g2.nextPage() );                 //Condição para manter a tela
  current_selection = 3;                      //se caso current_selection estiver com o mesmo ID da tela a tela fica mantida (travada)
  }                                           //Fim Tela3
  else {
    u8g2.userInterfaceMessage(                //Caso o menu não possua nada para se exibir
	"A tela não possui nada:",                  //Exibir mensagem abaixo
	u8x8_GetStringLineStart(current_selection-1, string_list ),
	"",
	"OK \n Cancelar");
  }
}
Licença CC 4.0

Creative Commons

O trabalho “Menu com telas LCD – ESP32” de JailsonBR está licenciado com uma Licença Creative Commons Atribuição 4.0 Internacional.

Jailson Oliveira

Sou Engenheiro Eletricista com Enfase em Eletrônica e Técnico em Eletrônica, gosto de estar praticando montagens de circuitos e também programar sistemas embarcados. Acredito que compartilhar informações gratuita gera mais informações novas por parte de outras pessoas.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *