Menu com telas LCD ST7920 – Arduino

Menu com telas LCD ST7920 – Arduino

O display LCD ST7920  é um display gráfico que possui uma resolução de 128×64 é um display bastante atrativo visualmente para se implementar em um projeto, com ele é possível exibir imagens (monocromática), figuras geométricas, textos e números. Uma ótima alternativa como interface visual. Para facilitar o uso des incrível dispositivo gráfico, existe uma biblioteca disponível para a IDE do Arduíno chamada u8glib que facilita em muito o uso deste dispositivo desenvolvido pelo olikraus a documentação pode ser encontrada em sua própria wiki.

Informação Importante: Esta biblioteca foi descontinuada e o desenvolvedor olikraus não está fornecendo mais suporte a mesma, devido ele ter criado uma nova biblioteca chamada u8g2, que tambem funciona neste display e a programação é muito diferente. Porem esta biblioteca funciona normalmente na Arduino IDE 1.8.3, não encontrei nenhum bug 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.

Sobre o Display:

Temos um artigo em nosso portal que descreve alguns detalhes do display LCD ST7920. Entre no link acima e veja mais informações.

Sobre a Biblioteca:

A biblioteca u8glib foi desenvolvida pelo olikraus em 2012, atualizada até Novembro de 2016, a partir desta data ele está prestando suporte a nova biblioteca u8g2 que é a sucessora da u8glib. Porem esta biblioteca é muito util mesmo não tendo mais suporte, algumas funções que o desenvolvedor menciona são:

  • Suporte a Cursor de Mouse
  • Modo Retrato e Paisagem
  • Fontes espaçadas e proporcionais
  • Suporta diversos modelos de LCDs (SSD1325, ST7565, ST7920, UC1608, UC1610, UC1701, PCD8544, PCF8812, KS0108, LC7981, SBN1661, SSD1306, SH1106, T6963, LD7032 e muito mais)
  • Suporte as interfaces de comunicação: Software SPI, Hardware SPI, 8Bit paralelo

Para este projeto utilizamos a biblioteca u8glib versão 1.18.1, com a versão 1.8.3 da IDE Arduino, rodou sem nenhum problema, também já testei em versões anteriores e funcionou da mesma forma.

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…

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 Arduíno (Nano, Uno, Duemilanove, Mega e etc)
  • 1 Trimpot ou potenciômetro de 10KΩ
  • 4 Botões de pulsar (Normalmente Abertos)
  • Cabos de conexões
  • 1 Fonte DC de 5V ou o próprio USB do Arduino

A montagem deve ser a seguinte:

Eu montei em uma protoboard utilizando um Arduíno nano que facilita as ligações em protoboard, a esquerda abaixo do LCD está uma fonte reguladora só foi colocada por causa que estava utilizando uma fonte separada para alimentar o LCD e tirei a fonte e esqueci de tira esta placa reguladora, montado em protoboard o projeto e ficou assim:

Programação:

A programação fiz uma adaptação do código exemplo “Menu” da biblioteca onde adicionei algumas funções que possibilita a seleção e entrada de cada menu. A programação ficou a seguinte:

/*
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 09-08-2017, 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/u8glib
  
  Copyright (c) 2012, 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.  
  
*/

#include <U8glib.h>               //Faça o Download da biblioteca utilizado neste projeto em XProjetos.net

// NOTA IMPORTANTE: A lista completa de dispositivos suportado por esta biblioteca está disponível em: https://github.com/olikraus/u8glib/wiki

U8GLIB_ST7920_128X64_1X u8g(5, 4, 3 ,6); //Configura o LCD para os rescpectivos pinos Enable, RW, RS, RESET  

#define BOT_TEMP 0        //Valor temporário
 /*-----------------------------------------------------------------------------------
   *   Abaixo está os respectivos Botões para a navegação - XProjetos.net
   *   Só alterar o numero do respectivo pino de saída do Botão (Usar o GND nos botões)
   ------------------------------------------------------------------------------------*/

#define BOT_VOLTAR 8
#define BOT_AVANCAR 9
#define BOT_SELECIONAR 10
#define BOT_VOLTAR_MENU 11

uint8_t IHM_Botao_Voltar = 8;
uint8_t IHM_Botao_Avancar = 9;
uint8_t IHM_Botao_Selecionar = 10;
uint8_t IHM_Botao_VoltarMenu = 11;



uint8_t uiKeyCodeFirst = BOT_TEMP;
uint8_t uiKeyCodeSecond = BOT_TEMP;
uint8_t uiKeyCode = BOT_TEMP;


void IMH_Config(void) {
  // Configuração dos Botões de Comando 
  pinMode(IHM_Botao_Voltar, INPUT);               // Configura o pino como entrada
  digitalWrite(IHM_Botao_Voltar, HIGH);           // Habilita o resistor de pullup interno
  pinMode(IHM_Botao_Avancar, INPUT);              // Configura o pino como entrada
  digitalWrite(IHM_Botao_Avancar, HIGH);          // Habilita o resistor de pullup interno
  pinMode(IHM_Botao_Selecionar, INPUT);           // Configura o pino como entrada
  digitalWrite(IHM_Botao_Selecionar, HIGH);       // Habilita o resistor de pullup interno
  pinMode(IHM_Botao_VoltarMenu, INPUT);           // Configura o pino como entrada
  digitalWrite(IHM_Botao_VoltarMenu, HIGH);       // Habilita o resistor de pullup interno
}

void IMH_Debounce(void) {
   // Debounce dos botões                    
  uiKeyCodeSecond = uiKeyCodeFirst;
  if ( digitalRead(IHM_Botao_Voltar) == LOW )
    uiKeyCodeFirst = BOT_VOLTAR;
  else if ( digitalRead(IHM_Botao_Avancar) == LOW )
    uiKeyCodeFirst = BOT_AVANCAR;
  else if ( digitalRead(IHM_Botao_Selecionar) == LOW )
    uiKeyCodeFirst = BOT_SELECIONAR;
  else if ( digitalRead(IHM_Botao_VoltarMenu) == LOW )
    uiKeyCodeFirst = BOT_VOLTAR_MENU;
  else 
    uiKeyCodeFirst = BOT_TEMP;
  
  if ( uiKeyCodeSecond == uiKeyCodeFirst )
    uiKeyCode = uiKeyCodeFirst;
  else
    uiKeyCode = BOT_TEMP;
}


#define MENU_ITEMS 5                  //Conforme o numero de menus é necessário altera-lo
char *menu_strings[MENU_ITEMS] = { "Primeiro Menu", "Segundo Menu", "Terceiro Menu", "Quarto Menu", "XProjetos.net" };     //Os nomes dos menus que irão aparecer no Display

uint8_t menu_atualmente = 0;          //Verifica a tela atual ue está sendo exibida
uint8_t menu_chamada_menu = 0;        //Habilita que o menu seja redesenhado na tela
uint8_t last_key_code = BOT_TEMP;
int tela = 0;                         //Valor da tela que está sendo exibida atualmente


 /*-----------------------------------------------------------------------------------
   *   Abaixo segue as Subrotinas referente a cada tela do menu (Todas são exemplos) - XProjetos.net
   *   Basta criar um Void Tela() para sua tela
   ------------------------------------------------------------------------------------*/

void Tela1()                        //Tela 1 - Caracteres Ascii - Pag. 1  
{
  char s[2] = " ";  
  u8g.drawStr( 0, 0, "ASCII page 1");  
  for(int y = 0; y < 6; y++ ) 
  {  
    for(int x = 0; x < 16; x++ ) 
    {
      s[0] = y*16 + x + 32;  
      u8g.drawStr(x*7, y*10+10, s);  
    }  
  }  
}

void Tela2(void) {                  // Desenha um relogio estático na tela
    //u8g.drawRFrame(0,0,128,64,3);  
  u8g.drawStr( 3, 10, "Hor.: 15:00");  
  u8g.drawStr( 3, 25, "Temp: 45");  
  char s[2] = " ";  
  s[0] = 176;  
  u8g.drawStr(51, 25, s);  
  u8g.drawStr( 3, 40, "Umid: 25%"); 
  u8g.drawStr( 3, 65, "XProjetos.net");  
  u8g.drawCircle(95,32,28);  
  u8g.drawCircle(95,32,29);  
  u8g.drawLine(95, 9, 95, 4);  
  u8g.drawLine(123, 32, 118, 32);  
  u8g.drawLine(95, 55, 95, 60);  
  u8g.drawLine(67, 32, 72, 32);  
  u8g.drawLine(95, 32, 95, 12);  
  u8g.drawLine(95, 32, 100.8, 21.87 );  
  u8g.setFont(u8g_font_04b_03);  
  u8g.drawStr(89,43, "Tag");  
  u8g.drawStr(85,50, "XProjetos"); 
}

void DesenharMenu(void) {  // Abaixo está a subrotina de desenho do menu principal
  uint8_t i, h;
  u8g_uint_t w, d;

  u8g.setFont(u8g_font_6x13);
  u8g.setFontRefHeightText();
  u8g.setFontPosTop();
  //XProjetos.net
  h = u8g.getFontAscent()-u8g.getFontDescent();
  w = u8g.getWidth();
  for( i = 0; i < MENU_ITEMS; i++ ) {
    d = (w-u8g.getStrWidth(menu_strings[i]))/2;
    u8g.setDefaultForegroundColor();
    if ( i == menu_atualmente ) {
      u8g.drawBox(10, i*h+1, 110, h);
      u8g.setDefaultBackgroundColor();
    }
    u8g.drawStr(d, i*h, menu_strings[i]);
  }
}

void AtualizarMenu(void) { // Função para troca de linha do itens do menu
  if ( uiKeyCode != BOT_TEMP && last_key_code == uiKeyCode ) {
    return;
  }
  last_key_code = uiKeyCode;
  
  switch ( uiKeyCode ) {
    case BOT_AVANCAR:
      menu_atualmente++;
      if ( menu_atualmente >= MENU_ITEMS )
        menu_atualmente = 0;
      //menu_chamada_menu = 0;
      break;
    case BOT_VOLTAR:
      if ( menu_atualmente == 0 )
        menu_atualmente = MENU_ITEMS;
      menu_atualmente--;
      break;
  }
}


void setup() {
  // Se precisar girar o menu basta descomentar a linha abaixo
  //u8g.setRot180();
  
  IMH_Config();                    // Chama a rotina de Configuração das teclas juntamente com o Debounce
  menu_chamada_menu = 1;           // Força o inicio do menu no LCD

}

void loop() {  

if (menu_chamada_menu = 1 && tela == 0) {
    IMH_Debounce(); 
    u8g.firstPage();
    do  {
      DesenharMenu();
    } while(u8g.nextPage());
  }
  if(menu_chamada_menu = 1){
AtualizarMenu(); //update menu bar
  }

  /*-----------------------------------------------------------------------------------
   *                              PRIMEIRO ITEM DO MENU: 
   ------------------------------------------------------------------------------------*/
  if(menu_atualmente == 0 && digitalRead(IHM_Botao_Selecionar) == 0) // Verifica se o Item do menu está selecionado e se o botão SELECT foi precionado
  {
    tela = 1;                                    // Configura a tela
    menu_chamada_menu = 0;                       //Desabilita menu
  }
    if(tela==1) {                                // Verifica se está na tela
      u8g.firstPage();                           // Inicia a página da Tela
  do {  
   Tela1();                                      //Chama a subrotina da Tela
   if(digitalRead(IHM_Botao_VoltarMenu) == 0){   // Verifica se o botão BACK foi precionado
    menu_atualmente = 0;                         // Volta o cursor para a primeira posição do menu
    menu_chamada_menu = 1;                       // Habilita o Menu Principal
    tela = 0;                                    // Configura como a Primeira tela
  }
  } while(u8g.nextPage());                       // Finaliza a página da tela e vai à proxima tela
}
    /*-----------------------------------------------------------------------------------
   *                              SEGUNDO ITEM DO MENU: 
   ------------------------------------------------------------------------------------*/
  if(menu_atualmente == 1 && digitalRead(IHM_Botao_Selecionar) == 0) // Verifica se o Item do menu está selecionado e se o botão SELECT foi precionado
  {
    tela = 2;                                    // Configura a tela
    menu_chamada_menu = 0;                       //Desabilita menu
  }
    if(tela==2) {                                // Verifica se está na tela
      u8g.firstPage();                           // Inicia a página da Tela
  do {  
   Tela2();                                      //Chama a subrotina da Tela
   if(digitalRead(IHM_Botao_VoltarMenu) == 0){   // Verifica se o botão BACK foi precionado
    menu_atualmente = 0;                         // Volta o cursor para a primeira posição do menu
    menu_chamada_menu = 1;                       // Habilita o Menu Principal
    tela = 0;                                    // Configura como a Primeira tela
  }
  } while(u8g.nextPage());                       // Finaliza a página da tela e vai à proxima tela
  }
}

Basta copiar e colar no IDE do Arduíno e compilar. Por favor deixe seu comentário se você gostou, teve problemas, ou se desenvolver algo a mais e gostaria de compartilhar conosco, desta forma podemos fazer uma internet melhor e com conteúdo gratuito e livre.

Licença Creative Commons

O trabalho Menu com telas LCD ST7920 – Arduino de JailsonBR está licenciado com uma Licença Creative Commons – Atribuição 4.0 Internacional.
Baseado no trabalho disponível em https://github.com/olikraus/u8glib.

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.

9 comentários sobre “Menu com telas LCD ST7920 – Arduino

  1. boa tarde eu gostaria de usar esses menus para alterar valores de sensores de temperatura para acionar reles

  2. Jailson Parabéns pelo belo trabalho. Estava procurando a muito tempo esse projeto na internet sem sucesso. Que Deus te abençoe pelo trabalho.

  3. Cara, muito bom! Ajudou-me muito num projeto que estou fazendo! Parabéns!
    Vc tem alguma ideia de como fazer submenus dentro do menu principal? E também sabe como por um nome no topo do menu?

    1. Fiz td pra fazer um submenu mas toda vez q aperto o botão, ele vai pro submenu e volta rapidamente pro menu principal de novo. Estou fazendo um projeto e essa uma das últimas etapas do programa só falta isso e mais alguns detalhes.

Deixe um comentário para Jailson Oliveira Cancelar resposta

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