O display 16×2 LCD é barato e relativamente fácil de usar. Entretanto, em alguns casos, os caracteres desenhados podem parecer pequenos, ainda mais se vistos de longe. Sendo assim, neste post, mostrarei um código que desenha os caracteres maiores.
Se você quiser aprender a utilizar o display 16×2, veja este post.
Informações básicas
O que é o projeto
Normalmente, cada caractere no display 16×2 ocupa 1 linha e 1 coluna. E a ideia deste projeto é desenhá-los ocupando 2 linhas e 3 colunas igual mostra a imagem abaixo:
No tópico adiante, explicarei como isso será feito. Mas preciso deixar claro que a concepção original não é minha. Na realidade, o que fiz foi estruturar o código de uma forma mais otimizada (na minha visão) e criar funções para facilitar o seu uso. O projeto que utilizei como referência pode ser visto neste link.
Criação dos caracteres grandes
Dentro de cada quadrado do display 16×2, existem outros quadradinhos (pixels) formando 5 colunas e 8 linhas. E é possível criar nossos próprios símbolos personalizados desenhando nestes 5×8 pixels. Neste post, ensino a criar estes símbolos customizados.
A criação dos símbolos consiste em escrever na memória do display qual é o desenho do símbolo que queremos. E o display consegue armazenar no máximo 8 símbolos. Ou seja, fica bem complicado criar uma fonte grande para as 26 letras do alfabeto e os 10 digitos (0 a 9). Portanto, teremos que reaproveitar muitos símbolos.
Por sorte, o autor (mpilchfamily) do post de onde tirei a referência, encontrou um conjunto de 8 símbolos que permitem escrever todo o alfabeto e todos os digitos. Veja estes símbolos abaixo:
Com isto em mente, desenvolvi um código com três funções facilitadoras que veremos adiante.
Obs: Como no post de referência só havia o desenho de algumas letras, acabei improvisando as demais e acho que o resultado ficou satisfatório. Além das letras e dígitos, implementei alguns caracteres especiais, como a exclamação e o ponto.
Como usar a fonte grande no display 16x2
Circuito
Vou utilizar um shield de display 16×2, mas, se você for usar o display diretamente, abaixo está um exemplo de como ligá-lo ao Arduino.
Alteração no código
Dependendo de como você ligou o display, você precisa alterar as linhas 8 a 13 do código:
#define DISPLAY_RS 8
#define DISPLAY_EN 9
#define DISPLAY_D4 4
#define DISPLAY_D5 5
#define DISPLAY_D6 6
#define DISPLAY_D7 7
Basta alterar o número no final do “#define” para corresponder ao número do pino que você ligou cada entrada do display. A correspondência acima se refere ao shield. No caso da ligação que mostrei anteriormente, o certo seria:
#define DISPLAY_RS 12
#define DISPLAY_EN 11
#define DISPLAY_D4 5
#define DISPLAY_D5 4
#define DISPLAY_D6 3
#define DISPLAY_D7 2
Comandos disponíveis
Adiante estão listados os comandos que criei para facilitar o uso da fonte grande.
- display_init();
- Deve ser chamado no “void setup” para iniciar o display e criar os símbolos.
- display_special_print(texto, cursor);
- Imprime no display um texto utilizando a fonte grande.
- O primeiro parâmetro é o texto desejado e o segundo indica a coluna que você quer escrever o texto (0 a 15).
- Exemplo: display_special_print(“teste”, 2);
- display_special_scroll(texto, delay);
- Imprime um texto grande no display que “anda” da direta para a esquerda.
- O primeiro parâmetro é o texto desejado e o segundo é o tempo (em milissegundos) entre cada movimento do texto.
- Exemplo: display_special_scroll(“Texto deslocando”, 400);
Caracteres disponíveis
As 26 letras do alfabeto e os 10 dígitos (0 a 9) podem ser usados sem problemas. Além deles, alguns símbolos também estão disponíveis, são eles:
! ” # $ % & ‘ ( ) * + , – . /
No caso, estes símbolos ocupam 2 linhas e 1 coluna ao contrário das letras e números.
As letras com acento não estão disponíveis e nem o ç.
Código completo
Abaixo está o código completo com as funções desenvolvidas. E já coloquei no “void setup” a função de inicialização, além da função de “andar” com o texto no “void loop” para exemplificar.
O ideal seria cria uma biblioteca com estas funções, mas pra facilitar o uso, resolvi colocar tudo em um código só.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | // ----- Bibliotecas ----- #include <LiquidCrystal.h> #include <avr/pgmspace.h> // ----- Definições ----- // Pinos do display #define DISPLAY_RS 8 #define DISPLAY_EN 9 #define DISPLAY_D4 4 #define DISPLAY_D5 5 #define DISPLAY_D6 6 #define DISPLAY_D7 7 // ----- Variáveis globais ----- LiquidCrystal lcd(DISPLAY_RS, DISPLAY_EN, DISPLAY_D4, DISPLAY_D5, DISPLAY_D6, DISPLAY_D7); // Símbolos const uint8_t display_fonte_desenhos[][8] PROGMEM = { // Formato 0 {0b00111, 0b01111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111}, // Formato 1 {0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111}, // Formato 2 {0b11100, 0b11110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111}, // Formato 3 {0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000}, // Formato 4 {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b01111, 0b00111}, // Formato 5 {0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111}, // Formato 6 {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11110, 0b11100}, // Formato 7 {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111}, }; // Valores iguais a 8 serão espaços nulos e 255 serão caracteres totalmente preenchidos // Índice dos desenhos de cada letra organizadas alfabeticamente const uint8_t display_fonte_letras[26][6] = {{0,1,2,4,3,6}, // A {255,1,2,255,1,6}, // B {0,3,3,4,7,7}, // C {255,3,2,255,7,6}, // D {0,1,1,4,1,1}, // E {0,1,1,4,8,8}, // F {0,3,3,4,7,2}, // G {0,8,2,4,3,6}, // H {3,255,3,7,255,7}, // I {3,3,255,4,7,255}, // J {0,7,6,4,3,2}, // K {255,8,8,4,7,7}, // L {2,7,0,255,8,255}, // M {2,7,7,255,8,255}, // N {255,3,255,255,7,255}, // O {0,1,2,255,8,8}, // P {0,3,2,4,7,1}, // Q {0,1,2,4,8,2}, // R {0,1,1,7,5,6}, // S {3,255,3,8,255,8}, // T {255,8,255,4,7,6}, // U {2,8,0,4,7,6}, // V {2,7,0,255,255,255}, // W {2,7,0,6,3,4}, // X {2,7,0,8,255,8}, // Y {3,1,2,4,5,7}, // Z }; // Índice dos desenhos de cada número organizados em ordem crescente const uint8_t display_fonte_numeros[10][6] = {{0,3,2,4,7,6}, // 0 {8,3,2,8,8,255},// 1 {1,1,2,4,5,5}, // 2 {1,1,2,1,1,6}, // 3 {0,7,2,8,8,6}, // 4 {255,1,1,5,5,6},// 5 {0,1,1,4,5,6}, // 6 {3,3,2,8,8,6}, // 7 {0,1,2,4,5,6}, // 8 {0,1,2,7,7,6} // 9 }; // Índice dos desenhos dos símbolos especiais organizados segundo a tabela ASCII const uint8_t display_fonte_especiais[16][6] = {{8,8}, // ESPAÇO {255,5}, // ! {2,8}, // " {35,8}, // # {36,36}, // $ {37,8}, // % {38,8}, // & {2,8}, // ' {0,4}, // ( {2,6}, // ) {42,8}, // * {43,8}, // + {8,6}, // , {7,3}, // - {8,7}, // . {47,8}, // / }; // ----- Protótipo das funções ----- void display_init(); void display_special_print(char * text, uint8_t cursor); void display_special_scroll(char * text, uint16_t delay_ms); void setup() { display_init(); } void loop() { display_special_scroll("Mundo Projetado", 400); } /* * Inicializa o display e cria os símbolos */ void display_init() { uint8_t i, j; uint8_t simb[8]; lcd.begin(16, 2); // Cria os símbolos for(i = 0; i < 8; i++) { for(j = 0; j < 8; j++) { simb[j] = pgm_read_byte_near(display_fonte_desenhos[i] + j); } lcd.createChar(i, simb); } } /* * Imprime um conjunto de caracteres utilizando uma fonte 2x3 * Parâmetros: * text - Conjunto de caracteres * cursor - Coluna onde o texto deve ser impresso (0 a 15) */ void display_special_print(char * text, uint8_t cursor) { uint8_t i, j, carac, idx; // Percorre por todos os pontos for(i = 0; *(text+i) != 0; i++) { // Lê o caractere carac = *(text+i); // Se o cursor chegou ao fim, sai do for if(cursor > 15) { break; } // ----- Identifica o tipo do caractere ----- // Número if(carac >= 48 && carac < 58) { carac -= 48; // Aqui 'carac' vale de 0 a 9 (indice em ordem crescente) for(j = 0; j < 6; j++) { idx = display_fonte_numeros[carac][j]; if(j < 3) { lcd.setCursor(cursor + j, 0); } else { lcd.setCursor(cursor + j%3, 1); } // Índice 8 é um espaço vazio if(idx == 8) { lcd.print(" "); } else { lcd.write(idx); } } cursor += 3; } // Caracteres especiais else if(carac >= 32 && carac < 48) { carac -= 32; // Aqui 'carac' vale de 0 a 15 for(j = 0; j < 2; j++) { idx = display_fonte_especiais[carac][j]; lcd.setCursor(cursor, j); // Índice 8 é um espaço vazio if(idx == 8) { lcd.print(" "); } else { lcd.write(idx); } } cursor += 1; } // Letra: else { // Letras minúsculas if(carac >= 97 && carac < 123) { carac -= 97; } // Letras maiusculas else if(carac >= 65 && carac < 91) { carac -= 65; } // Aqui 'carac' vale de 0 a 25 (indice em ordem alfabetica) for(j = 0; j < 6; j++) { idx = display_fonte_letras[carac][j]; if(j < 3) { lcd.setCursor(cursor + j, 0); } else { lcd.setCursor(cursor + j%3, 1); } // Índice 8 é um espaço vazio if(idx == 8) { lcd.print(" "); } else { lcd.write(idx); } } cursor += 3; } } } /* * Cria um texto que se desloca da direta pra esquerda * Parâmetros: * text - Conjunto de caracteres * delay_ms - Delay do deslocamento */ void display_special_scroll(char * text, uint16_t delay_ms) { uint8_t len, i; uint8_t cursor = 12; // Calcula o tamanho completo do texto (tamanho max de 254) for(len = 0; len < 254; len++) { if(*(text+len) == 0) { break; } } // Aqui len = tamanho do texto for(i = 0; i < len + 4; i++) { lcd.clear(); if(cursor > 0) { display_special_print(text, cursor); cursor -= 3; } else { display_special_print(text+i-4, 0); } delay(delay_ms); } lcd.clear(); } |
Resultado
Veja o código anterior em funcionamento: