Shield LCD e Teclado da DFRobots – Drivers para a família TM4C129X da TI

Shield LCD e Teclado da DFRobots

Este artigo tem por objetivo mostrar a implementação de um driver para comunicação entre um Shield LCD e Teclado da DFRobots (veja imagem de destaque do artigo) e uma placa Connected Launchpad.

Esse shield da DFRobots é interessante pois possui um display LCD compatível com Hitach 44780 conectado através de uma interface de 4 bits, o qual já foi extensamente explorado pelos ótimos artigos do Daniel Madeira e do Henrique Puhlmann. Um outro elemento existente nesta placa é um teclado de 5 teclas construído através de uma rede resistiva.

shield-LCD-image00
Figura 1 – Imagem ilustrativa do módulo LCD Keypad Shield For Arduino.
Fonte: https://www.dfrobot.com/

Muitas vezes temos alguns shields Arduino em casa e não os usamos pois achamos que não vale a pena ou que é complicado usá-los em nossos projetos. Este artigo também vem para desmitificar isso: podemos usar esses shields em qualquer tipo de projeto, para prototipagem rápida e testes de viabilidade de produtos/projetos.

Objetivos

Neste artigo temos dois objetivos:

  1. Implementar um driver para teclado resistivo e;
  2. Implementar um driver para o display LCD 44780.

Conexões do Shield LCD e Teclado da DFRobots

O primeiro aspecto que tive que enfrentar foi saber qual a tensão que eu alimentaria o módulo LCD/Teclado de tal forma que conseguisse alimentar o display e operar o teclado. Conforme está descrito no datasheet do módulo LCD, a sua tensão de trabalho está entre 4,5V e 5,5V. Alimentando o módulo com 5V não nos traz problema pois, conforme podemos ver no datasheet do controlador LCD, se este estiver operando com uma tensão de 5V, a tensão mínima para que o controlador entenda um nível alto é de 2,2V e como não é necessário ler a CGRAM ou a DDRAM do controlador, o TM4C1294 conseguirá controlá-lo.

As conexões utilizadas no decorrer do artigo são as apresentadas abaixo:

Shield LCD e Teclado da DFRobots: Representação das interconexões entre a Connected Launchpad e o shield LCD+Teclado
Figura 2 – Representação das interconexões entre a Connected Launchpad e o shield LCD+Teclado

Outro problema que enfrentamos foi a tensão de trabalho da entrada AD do TM4C1294 conectado ao teclado resistivo. Analisando o circuito do teclado concluí-se que a máxima tensão gerada por ele é de 5V, que excede as especificações do canal analógico do TM4C1294. Para permitir o uso deste shield em nossa Connected Launchpad houve a necessidade de alterar o circuito do teclado, inserindo um resistor RX, de 1K5 Ω, entre o resistor R6 e o terra, como mostrado na figura a seguir:

Shield LCD e Teclado da DFRobots: Inserção do resistor RX à rede resistiva do teclado para operação deste com a Connected Launchpad
Figura 3 – Inserção do resistor RX à rede resistiva do teclado para operação deste com a Connected Launchpad

Driver para Teclado Resistivo

Inicialmente tive que definir os valores que seriam mensurados pelo conversor Digital/Analógico do TM4C1294 para realizar a correta interpretação de cada tecla pressionada. Através de algumas contas e ajustes realizando medidas, obtivemos os valores abaixo:

#define KB_AN_RIGHTKEY_UPPER_LIMIT          (100)
#define KB_AN_RIGHTKEY_LOWER_LIMIT          (0)
#define KB_AN_UPKEY_UPPER_LIMIT             (620+100)
#define KB_AN_UPKEY_LOWER_LIMIT             (620-100)
#define KB_AN_DOWNKEY_UPPER_LIMIT           (1570+100)
#define KB_AN_DOWNKEY_LOWER_LIMIT           (1570-100)
#define KB_AN_LEFTKEY_UPPER_LIMIT           (2500+100)
#define KB_AN_LEFTKEY_LOWER_LIMIT           (2500-100)
#define KB_AN_SELKEY_UPPER_LIMIT            (3380+100)
#define KB_AN_SELKEY_LOWER_LIMIT            (3380-100)
#define KB_AN_NONE_UPPER_LIMIT              (4095)   
#define KB_AN_NONE_LOWER_LIMIT              (4095-100)

O processo de leitura do teclado foi implementado utilizando soft timers, onde implementamos uma pequena máquina de estados que gerencia a operação do conversor A/D de tal forma que ele não realiza a conversão em um único passo.

uint32_t ReadKbAnTask( void* pParam )
{
	static BYTE bKbAnState = 0;
	static uint32_t dwADCValue = 0;
    
	switch( bKbAnState )
	{
      	  case 0:
    	  {    	ADCIntClear(KB_AN_ADC_BASE, KB_AN_ADC_SEQUENCE);
        	ADCProcessorTrigger(KB_AN_ADC_BASE, KB_AN_ADC_SEQUENCE);
       	 
        	bKbAnState = 1;
    	  }
    	  break;
       	 
    	  case 1:
    	  {    	bKbAnState = 1;
        	if ( ADCIntStatus(KB_AN_ADC_BASE, KB_AN_ADC_SEQUENCE, false) )
        	{
            	  bKbAnState = 2;
        	}            	 
    	  }
    	  break;
   	 
    	  case 2:
    	  {    	ADCSequenceDataGet(KB_AN_ADC_BASE, KB_AN_ADC_SEQUENCE, &dwADCValue);
        	bKbAnState = 3;
    	  }
    	  break;
   	 
    	  case 3:
    	  {    	dwAnalogKbValue = dwADCValue;
        	bKbAnState = 0;
    	  }
    	  break;
   	 
    	  default:
        	bKbAnState = 0;
          break;
 	 
	  }
    	  return 0;
}

E a leitura da tecla é realizada através da função KbAnReadKey abaixo:

uint8_t KbAnReadKey( KB_AN key )
{
	uint8_t bRetKb=0;
    
	switch( key )
	{
    	  case KB_AN_RIGHT :
    	  case KB_AN_UP	:
    	  case KB_AN_DOWN  :
    	  case KB_AN_LEFT  :
    	  case KB_AN_SELECT:
    	  {
        	if ( (dwAnalogKbValue > kbAnLimits[key].wLowerLimit) && 
                     (dwAnalogKbValue <= kbAnLimits[key].wUpperLimit))
        	{
            	  bRetKb = 1;
        	}
    	  }
    	  break;
   	 
    	  default:
    	  {
            bRetKb = 0;
    	  }
    	  break;
	}
    
	return bRetKb;
}

Driver para display LCD 44780

Implementamos um driver com interface 4-bits para o controlador de display LCD 44780. Procurei manter a mesma interface da biblioteca LiquidCrystal Library, permitindo que seja bem simples de um usuário de Arduino portar o seu código para utilizar este driver.

Aplicação de exemplo

Com os drivers para o teclado e para o LCD desenvolvemos uma pequena aplicação que controla um LED da Connected Launchpad baseado na tecla que foi pressionada e, concomitantemente, realiza a atualização de um contador no display LCD. A seguir estou colocando o código fonte da função main(), que realiza a inicialização do teclado e do display e algumas outras tarefas.

int main()
{   
	uint32_t dwTimerHandle;
    
	SetSystemClock();  /* configure the system clock                	*/    
    
	TTimerCfgTimeOut( 500 );  /* initialize the ttimer engine       	*/
    
	BrdLedsInit();  /* initialize the board leds engine             	*/
	BrdKeyInit();   /* initialize the board keys engine             	*/
	KbAnInit(); 	/* initialize the DFRobot analog keyboard engine	*/
	Lcd44780Init( 2, 16 );
    
	Lcd44780BackLightOn();
    
	Lcd44780SetCursor( 0, 0 );
	Lcd44780Write( "***EMBARCADOS***" );
    
	BrdLedsSetState( USR_LED0, 0 );
	BrdLedsSetState( USR_LED1, 0 );
	BrdLedsSetState( USR_LED2, 0 );
	BrdLedsSetState( USR_LED3, 0 );
    
	TTimerRegisterCallBack( 10*TTIMER_1MS_INTERVAL, TimerPeriodic, TaskReadKbAn, NULL, &dwTimerHandle );
	TTimerStart( dwTimerHandle );

	TTimerRegisterCallBack( TTIMER_1SEC_INTERVAL/3, TimerPeriodic, UsrPrintText, NULL, &dwTimerHandle );
	TTimerStart( dwTimerHandle );
    
	for( ;; );
}

E a seguir apresentamos as funções para exemplificar o uso das funções do teclado e do LCD:

uint32_t UsrPrintText( void* lpParam )
{
	typedef enum
	{
    	  TSPLASHSCREEN,
    	  TCLEAN,
    	  TUPDATEBUFFER,
    	  TPOSCURSOR,
    	  TWRITELCD,
	} TUSRPRINT;
    
	static TUSRPRINT stPrintText = TSPLASHSCREEN;
	static uint16_t wCounter = 0;
	static char cDispOut[7] = {0};
    
	switch( stPrintText )
	{
    	  case  TSPLASHSCREEN:
    	  {
        	    stPrintText = TCLEAN;
        	    break;
    	  }
   	 
    	  case  TCLEAN:
    	  {
        	    Lcd44780Clear();
        	    stPrintText = TUPDATEBUFFER;
        	    break;
    	  }
   	 
    	  case  TUPDATEBUFFER:
    	  {
        	    memset( cDispOut, 0, sizeof( cDispOut ));
        	    sprintf( cDispOut, "%06d", wCounter );
        	    stPrintText = TPOSCURSOR;
        	    break;
    	  }
   	 
    	  case TPOSCURSOR:
    	  {
        	    uint8_t s = (Lcd44780GetCol() - sizeof(cDispOut)) >> 1;
        	    Lcd44780SetCursor( Lcd44780GetCurLin() , s );
        	    stPrintText = TWRITELCD;
        	    break;
    	  }
   	 
    	  case  TWRITELCD:
    	  {
        	    Lcd44780Write( cDispOut );
        	    wCounter++;
        	    stPrintText = TUPDATEBUFFER;
        	    break;
    	  }
	}
	return 0;
}

/******************************************************************************/

uint32_t TaskReadKbAn( void* lpParam )
{
	static uint32_t dwUsrLed3TimeHandle;
	static uint8_t  bTaskReadKbAnInit = 0;
	KB_AN xPressKey = KB_AN_NONE;
	const uint32_t bLedTimeTbl[] =
	{
    	  [KB_AN_RIGHT ] = 1*TTIMER_1SEC_INTERVAL,
    	  [KB_AN_UP	] = 2*TTIMER_1SEC_INTERVAL,
    	  [KB_AN_DOWN  ] = 3*TTIMER_1SEC_INTERVAL,
    	  [KB_AN_LEFT  ] = 4*TTIMER_1SEC_INTERVAL,
    	  [KB_AN_SELECT] = 5*TTIMER_1SEC_INTERVAL,
	};
    
	static KB_AN xKb = KB_AN_RIGHT;
    
	if ( !bTaskReadKbAnInit )
	{
    	  if (!TTimerRegisterCallBack( 0, TimerOneShot, UsrLed2Off, NULL, &dwUsrLed3TimeHandle))
    	  {
        	    bTaskReadKbAnInit = 1;
    	  }
	}
	else
	{
    	  if ( KbAnReadKey( xKb) )
    	  {
        	    xPressKey = xKb;
    	  }
   	 
    	  if ( xPressKey != KB_AN_NONE )
    	  {
        	    BrdLedsSetState( USR_LED2, 1 );
        	    TTimerSetTime( dwUsrLed3TimeHandle, bLedTimeTbl[xKb] );
        	    TTimerStart( dwUsrLed3TimeHandle );
    	  }
    	  xKb++;
   	 
    	  if ( xKb == KB_AN_NONE )
    	  {
        	    xKb = KB_AN_RIGHT;
    	  }
	}
	return 0;
}

A figura abaixo ilustra a aplicação de exemplo funcionando no ambiente final.

Shield LCD e Teclado da DFRobots: Exemplo rodando na Connected Launchpad.
Figura 4 – Exemplo rodando na Connected Launchpad.

Os códigos fontes dos drivers e do exemplo podem ser encontradas projeto criado no github.

Conclusão

Como apresentado no início deste artigo, apresentamos drivers para o teclado resistivo e display LCD compatíveis com o controlador 44780. Também foi demonstrado o uso desses drivers em uma aplicação de exemplo utilizando a placa de avaliação Connected Launchpad da Texas Instruments.

Convido os leitores para que teçam os seus comentários, apontem erros e dêem sugestões de drivers que possamos implementar para outras shields e outras placas de desenvolvimento. Com isso poderemos montar um conjunto de bibliotecas para uso em vários projetos.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
6 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Rafael Dias
Rafael Dias
15/02/2016 08:23

Claro que tem coisas que não estão 100%. Por exemplo, como o tempo para escrita no display é um pouco demorado, o mais certo é retirar a escrita no display do contexto da ISR (onde as rotinas do soft-timer executam) e jogar para o user space.

Custódio Barcellos
Custódio Barcellos
10/02/2016 09:29

Legal o artigo bem didático e o código limpo e claro! Parabéns e obrigado por compartilhar!

Rafael Dias
Rafael Dias
Reply to  Custódio Barcellos
15/02/2016 08:17

de nada. Se tiver sugestão de dispositivos, é só mandar que damos um jeito.

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
09/02/2016 09:16

Excelente Rafael. Parabéns!

Se tiver algum shield ou módulo com interface I2C e SPI seria bacana um driver.

Abraços

Rafael Dias
Rafael Dias
Reply to  Fabio_Souza_Embarcados
09/02/2016 09:54

Opa!

Estou começando um driver para um BMP180
https://www.adafruit.com/products/1603

E também está na fila um driver para um display desses https://playground.arduino.cc/Main/MAX72XXHardware

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Rafael Dias
09/02/2016 11:11

Muito bacana. Vai ser top!

Home » Hardware » Placas de desenvolvimento » Shield LCD e Teclado da DFRobots – Drivers para a família TM4C129X da TI

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: