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:
u8g2 – Biblioteca para Displays Gráficos 49,1MB 467 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:
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"); } }