Arduino – Como realizar um scroll no LCD 16×2, deixando uma linha fixa
Um leitor do site enviou uma pergunta hoje, sobre como realizar um scroll no LCD 16×2 ligado ao Arduino, mas apenas em uma linha. A outra ficaria estática.
A pergunta é aparentemente simples mas, ao pesquisar o assunto, vi que realizar o scroll em apenas uma linha envolve questões como mexer diretamente na memória do LCD e alterar (ou criar) bibliotecas.
Ao invés de usar uma biblioteca nova, por que não fazer isso utilizando a LiquidCrystal?
Essa é uma das bibliotecas mais básicas e utilizadas com Arduino, e já vem pré-instalada na sua IDE.
Como fazer o scroll no LCD 16×2 em apenas uma linha do display
Encontrei um colega lá da India (http://nishantarora.in/) que criou um programinha exatamente para isso.
Infelizmente resolvia apenas parte do problema: a linha inferior permanecia estática, mas a linha superior realizava o scroll uma única vez.
O que eu fiz foi alterar o código para que o scroll não só fosse realizado de forma ininterrupta, como também aceitasse qualquer tamanho de string que fosse colocada no programa. O resultado você pode ver no vídeo abaixo:
O circuito utilizado é o mesmo mostrado no post Display LCD Winstar WH1602A. O modelo do LCD é o WH1602A mas o programa funciona sem problemas em outros modelos de display 16×2, como o HD44780, que eu abordei neste artigo.
Além do LCD, usei como componente adicional um potenciômetro de 10 K para ajuste do contraste:
Abaixo, o programa utilizado para testes e mostrado no vídeo acima:
// Programa : Scroll LCD 16x2 apenas em uma linha // Alteracoes e adaptacoes : Arduino e Cia // // Baseado no programa original de Nishant Arora #include <LiquidCrystal.h> //Inicializacao do display LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Configuracoes LCD 16x2 int screenWidth = 16; int screenHeight = 2; //String para as 2 linhas //line1 = Scroll linha superior String line1 = "Arduino e Cia, dicas, projetos e tutoriais: www.arduinoecia.com.br"; //line2 = Linha inferior - estatica String line2 = " Arduino e Cia"; // just some reference flags int stringStart, stringStop = 0; int scrollCursor = screenWidth; int tamanho =0; void setup() { //Inicializacao do display lcd.begin(screenWidth,screenHeight); } void loop() { lcd.setCursor(scrollCursor, 0); lcd.print(line1.substring(stringStart,stringStop)); lcd.setCursor(0, 1); lcd.print(line2); //Quanto menor o valor do delay, mais rapido o scroll delay(250); scroll_sup(); //Chama a rotina que executa o scroll //Verifica o tamanho da string tamanho = line1.length(); if (stringStart == tamanho) { stringStart = 0; stringStop = 0; } } void scroll_sup() { lcd.clear(); if(stringStart == 0 && scrollCursor > 0) { scrollCursor--; stringStop++; } else if (stringStart == stringStop){ stringStart = stringStop = 0; scrollCursor = screenWidth; } else if (stringStop == line1.length() && scrollCursor == 0) { stringStart++; } else { stringStart++; stringStop++; } }
Basicamente o que o programa faz é calcular a posição do cursor, imprimir a string line1 na linha superior e a string line2 na linha inferior. Depois ele apaga a tela, calcula a nova posição do cursor e imprime novamente as duas strings.
E o procedimento vai se repetindo até que toda a string line1 seja mostrada na linha superior. Quando isso acontece, todo o processo é reiniciado.
Este é um código que pode ser melhorado, especialmente para retirar o efeito “piscar” da tela, causado pelo uso do comando lcd.clear(), mas que serve de base para o seu projeto. 🙂
Gostou? Confira outros posts com display LCD 16×2 aqui mesmo no Arduino e Cia!
Muito obrigado! Ajudou bastante!
E parabéns pelo blog…
Abraço e obrigado ! 🙂
Arduino e Cia, pela sua experiência, q venho acompanho de seus tutoriais pelo teu blog, lhe peço encarecidamente q vc de atenção neste problema q eu estou tendo a pelo menos 2Mêses e meio, e já procurei recursos na net p/ resolver, como: função Millis, Timer, etc, mais sem sucesso, com as fontes q consegui não deu para entender, então resolvi recorrer a vc. É o seguinte:
Programei alguns comandos, para acionar alguns led´s pela Serial, Juntamente com um Display lcd 1602 para mostrar informações:
Temperatura, Acionamentos de leds ex: "led1 esta ligado", "led2 esta desligado", etc…
O problema é q, a soma dos delay´s q declarei p/ fixar cada informação no LCD por 2segundos, esta gerando uma resposta muito demorada dos comandos, por exemplo: quando jogo o comando '1' na Serial p/ acionar um led, o mesmo led esta sendo acionado após uns 16segundos, eu ter dado o comando. Gostaria muito mais muito mesmo, que vc me ajudasse, me passe o teu e-mail, para eu te passar o código, desde já lhe agradeço..
Boa noite Marcos,
Sem problemas, não posso prometer nada, mas vamos ver no que posso te ajudar. rs
Por favor utilize o formulário de contato no lado direito da página do site, ok ?
Aguardo sua mensagem. Abraço !
Procurei por isso a muito tempo!!! Muito obrigado e parabéns!!!
Bom dia Willian,
Bom poder ajudar. Abraço e obrigado !
muito bom o site!
Mas como eu faço para inserir outros códigos de leitura? Por exemplo, quero que passe meu nome na linha de cima e na linha de baixo quero ler uma distância por um sensor ultra som em tempo real.
Estou tentando aqui e até consegui, mas as mensagens passam piscando.
Oi Wendel,
Esse efeito de piscar acontece por causa do comando lcd.clear que eu usei no programa… uma alternativa é você retirar esse comando e usar o lcd.print pra imprimir caracteres em branco em cima da segunda linha.
Abraço !
desenvolvi um projeto aqui mas está dando erro;
#include
#define echoPin 13 //Pino 13 recebe o pulso do echo
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo
#include
#include
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int distancia =0;
//Configuracoes LCD 16×2
int screenWidth = 16;
int screenHeight = 2;
//String para as 2 linhas
//line1 = Scroll linha superior
String line1 = "Wendel Areas Pelicioni";
//line2 = Linha inferior – estatica
String line2 = distancia;
// just some reference flags
int stringStart, stringStop = 0;
int scrollCursor = screenWidth;
int tamanho =0;
void setup()
{
//Inicializacao do display
lcd.begin(screenWidth,screenHeight);
pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)
pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)
}
void loop()
{
lcd.setCursor(scrollCursor, 0);
lcd.print(line1.substring(stringStart,stringStop));
lcd.setCursor(0, 1);
lcd.print(line2);
//Quanto menor o valor do delay, mais rapido o scroll
delay(500);
scroll_sup(); //Chama a rotina que executa o scroll
//Verifica o tamanho da string
tamanho = line1.length();
if (stringStart == tamanho)
{
stringStart = 0;
stringStop = 0;
}
//seta o pino 12 com um pulso baixo "LOW" ou desligado ou ainda 0
digitalWrite(trigPin, LOW);
// delay de 2 microssegundos
delayMicroseconds(2);
//seta o pino 12 com pulso alto "HIGH" ou ligado ou ainda 1
digitalWrite(trigPin, HIGH);
//delay de 10 microssegundos
delayMicroseconds(10);
//seta o pino 12 com pulso baixo novamente
digitalWrite(trigPin, LOW);
//pulseInt lê o tempo entre a chamada e o pino entrar em high
float duration = pulseIn(echoPin,HIGH);
//Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado
//porque é o tempo de ida e volta do ultrassom
float distancia = duration /29 / 2 ;
}
void scroll_sup()
{
lcd.clear();
if(stringStart == 0 && scrollCursor > 0)
{
scrollCursor–;
stringStop++;
} else if (stringStart == stringStop){
stringStart = stringStop = 0;
scrollCursor = screenWidth;
} else if (stringStop == line1.length() && scrollCursor == 0) {
stringStart++;
} else {
stringStart++;
stringStop++;
}
}
Faltou incluir a biblioteca do ultrassônico?
Perfeito para uma aplicação que estou desenvolvendo. Obrigada!
Valeu Raquel !
Abraço.
Poderia explicar como funciona esse scroll_sup()?
ooo dúvida cruel…
boa tarde: poderia me ajudar?
os caracteres não aparecem.
modelo do lcd é qc1602A v.2
obriado.
Seus tutoriais são otimos muito bem detalhados e de fácil compreensão e de todos, é o primeiro que eu não consegui êxito vlw
Oi Marcos,
Obrigado! Bom, olhei a pinagem do seu display, e aparentemente é "padrão"… vc tentou fazer um teste simples, de escrever algo na tela ?
Abraço!
Para quem tem o Arduino Uno com a Lcd Keypad Shield Button instalada em cima dele basta alterar o código na linha 9 conforme abaixo:
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
Como faço para rolar apenas uma vez(depois que a frase que está rodando passar pela linha) e depois escrever novas coisas no display ?
DEU CERT0! COMO O MEU DISPLAY É UM SHIELD, APENAS TROQUEI A LINHA 9, POSTADA PELO JONATHAN
Aqui vos deixo a funçao que uso para fazer scrool apenas numa linha
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa/funçao : rodaTexto
// roda o texto apenas numa linha à escolha do programador
// projectado para funcionar em qualquer LCD
// usa apenas variaveis locais, no caso da largura do LCD optou-se por definir esse valor
// dentro da funçao, no entanto é preferivel incluir mais uma variavel na chamada para definir
// esse valor ou entao usar uma variavel publica e de preferencia static….
///////// funçao desenhada por Akintal para o dominio publico
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include
//Inicializacao do display
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup()
{
//Inicializacao do display
lcd.begin(16,2);
}
void loop()
{
lcd.setCursor(2, 0); //posiciona o cursor para a colocaçao do texto fixo
lcd.print("Arduino & Cia"); //texto exemplo
delay(1000); //implementar o atraso pela funçao "Millis", ou então colocar a chamada
//numa parte do programa que já tenha o atraso pretendido
//Quanto menor o valor do delay, mais rapido o scroll
rodaTexto(1,"Carrega num botao para aceder aos menus do programa"); //Chama a rotina que executa o scroll
}
/////////////////////////////////////////////////////////////////////////
//Função para rolagem do texto apresentado no LCD numa unica linha
//argumentos: rolaTexto( numero_da_linha, texto_a_apresentar);
//exemplo:rodaTexto(1,"Carrega num botao para aceder aos menus do programa");
//////////////////////////////////////////////////////////////////////////
void rodaTexto(int linha,String texto){
static int posicao; //para RELEMBRAR a ultima posicao do ponteiro
int larguraLcd=16; //define a quantidade de caracteres possiveis numa linha
texto=" "+texto; //Acrescenta uns espaços no inicio do texto para separar o fim do inicio
int tamanhoTexto= texto.length(); //guarda o tamanho do texto a apresentar
int resto = tamanhoTexto-posicao; //regista o que falta mostrar…
///////////////////////////////////////////////////////////////////////
lcd.setCursor(0,linha); //posiciona o cursor na linha pretendida
if (resto < larguraLcd){ //se o texto já nao preenche a totalidade do espaço disponivel no LCD
lcd.print(texto.substring(posicao,tamanhoTexto)); //mostra a parte final do texto…
lcd.print(texto.substring(0,larguraLcd)); //e completa o resto da linha do LCD com parte do inicio do texto
}
else{
lcd.print(texto.substring(posicao,posicao+larguraLcd)); //mostra o texto normalmente…..
}
posicao++; //incrementa a posiçao do ponteiro
if (posicao >= tamanhoTexto) {posicao=0;} //chegou ao fim? reposiciona o ponteiro no inicio e repete todo o processo
}
Dei uma simplificada, esta funcionando…
// Programa : Display LCD 16×2 e modulo I2C
// Autor : Tales C. Dantas
#include
#include
int pos = 0;
// Inicializa o display no endereco 0x27
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE);
void setup()
{
lcd.begin (16,2);
}
void loop()
{
lcd.setBacklight(HIGH);
lcd.setCursor(0,0);
lcd.print("Hello World !!");
lcd.setCursor(0,1);
// scroll
String texto = "Arduino – Como realizar um scroll no LCD 16×2, deixando uma linha fixa";
lcd.print(texto.substring(pos,pos+16));
delay(250);
pos++;
if (pos > texto.length()-16){
delay(1000);
pos = 0;
}
}
OBRIGADO! Era exatamente o que eu procurava. Vou executar o programa. Valeu!!!
Opa! Agradeço a visita! 🙂
Abraço!
Adilson
Muito obrigado….parabéns.
Valeu João!
Abraço.
Adilson
Primeiramente, obrigado pelo tutorial. É muito legal trabalhar com esses Displays.
Outrossim, é possível usar esses displays sem usar Potenciômetro para o contraste da tela. É somente usar um pino PWM do Arduino para o controle.
Oi Daniel,
Perfeito. Obrigado! 🙂
Adilson
Teria algum comando ou método para inverter ou rotacionar 180 graus o texto no display?
Oi Fernando,
Desconheço, mas acho que essa discussão aqui pode te dar algumas dicas: https://forum.arduino.cc/index.php?topic=159524.0
Abraço!
Adilson