Olá pessoal! Já ouviram falar no display IPS LCD 0.96″ colorido? No artigo de hoje faremos uso de um display desse tipo exibindo imagens e textos coloridos. Vamos lá?

Introdução
In-Planne Switching ou comutação no plano (tradução livre) é a sigla IPS. Usada em telas LCD, moléculas de cristal líquido giram em plano horizontal. A imagem é definida em uma taxa de atualização de 200 Hz a 240 Hz, contra 60 Hz em telas tradicionais. Isto faz com que a imagem seja atualizada sem perdas.
Esta tecnologia é usada em TVs LCD, monitores, displays em smartphones e também há versões que podemos utilizar em plataformas como Arduino, STM32 e afins.
Existem displays IPS de diversos tamanhos, totalmente coloridos. São divididos em tamanho (em polegadas) ou por resolução. A conexão com Arduino e afins é dada através de comunicação SPI. Seguem alguns exemplos:

Importante ressaltar que alguns modelos também diferem no controlador de display, que pode ser: ST7735, ST7789 ou ILI9341. Neste experimento faremos uso da versão com ST7735 para aparecer mensagens e imagens.
Materiais necessários
- 1 Arduino Uno com cabo USB (ou outro de sua preferência)
- 1 protoboard 400 pontos ou maior
- 1 display IPS LCD 0.96” colorido
- Jumpers macho-macho
Montagem do circuito do display IPS LCD 0.96″ colorido
Faremos o circuito conforme mostrado na figura abaixo:

Onde:
Arduino | Display |
GND | GND |
5V ou 3.3V | VCC |
13 | SCL |
11 | SDA |
9 | RES |
8 | DC |
10 | CS |
Não usa | BLK |
OBS: O display pode ser 3.3V ou 5V. Ao carregar o programa veja como a sua versão se comporta. Nesta imagem o display está conectado ao pino de alimentação 5V.

Instalação de bibliotecas
Usaremos duas bibliotecas a serem instaladas, chamadas Adafruit_GFX.h e Adafruit_ST7735.h. Para a instalação, vá na IDE Arduino no menu Sketch => Incluir biblioteca => Gerenciar bibliotecas.
Na barra de busca do Gerenciador de biblioteca, procure por gfx e pressione Enter. Clique no botão Instalar e aguarde o carregamento. Depois faça o mesmo para a outra biblioteca digitando ST7735.

OBS: A opção para biblioteca contempla – CD3F794HR8 – os dois tipos de controladores principais para displays TFT/IPS.
Código
Este código é uma adaptação do original escrito por Limor Fried da Adafruit. Realiza testes gráficos com várias cores, além de testes de escrita.
/************************************************************************** Escrito por Limor Fried/Ladyada para Adafruit Industries. Modificado por Gedeane Kenshima Data: 04/07/2021 **************************************************************************/ #include <Adafruit_GFX.h> // Biblioteca gráfica Adafruit #include <Adafruit_ST7735.h> // Biblioteca específica para ST7735 #include <Adafruit_ST7789.h> // Biblioteca específica para ST7789 #include <SPI.h> // Biblioteca para comunicação SPI // Definição dos pinos SPI #define TFT_CS 10 #define TFT_RST 9 #define TFT_DC 8 // Pinos SDA em 11 e SCL em 13 // Criação do objeto tft para displays com ST7735: Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // Variável p com valor de pi float p = 3.1415926; void setup(void) { // Início da comunicação Serial com 9600 bits por segundo Serial.begin(9600); // Mensagem inicial exibida no Monitor Serial Serial.println(F("Ola! Teste para TFT ST77xx")); // Inicialização do display IPS LCD 0.96" 160x80: tft.initR(INITR_MINI160x80); Serial.println(F("Inicializado")); // Usa millis para contagem de tempo uint16_t time = millis(); // Preenche a tela com a cor preta tft.fillScreen(ST77XX_BLACK); // Realiza contagem de tempo atual time = millis() - time; // Exibe tempo atual em decimal Serial.println(time, DEC); // Aguarda 500 ms delay(500); // Gira tela para melhor exibição // Valores podem ser 0 (default), 1, 2 ou 3 tft.setRotation(3); // Preenche a tela com a cor preta tft.fillScreen(ST77XX_BLACK); // Escreve texto longo com letras em cor branca testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST77XX_WHITE); // Aguarda 2s delay(2000); // Chama função tftPrintTest tftPrintTest(); // Aguarda 4s delay(4000); // Gira tela para posição inicial tft.setRotation(0); // Desenha um pixel na tela em verde tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN); // Aguarda 500 ms delay(500); // Teste de linhas testlines(ST77XX_YELLOW); delay(1000); // Linhas otimizadas testfastlines(ST77XX_RED, ST77XX_BLUE); delay(1000); testdrawrects(ST77XX_GREEN); delay(1000); testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA); delay(1000); // Preenche a tela com a cor preta tft.fillScreen(ST77XX_BLACK); // Teste de círculos preenchidos em azul testfillcircles(10, ST77XX_BLUE); // Teste de círculos desenhados em branco testdrawcircles(10, ST77XX_RED); delay(1000); testroundrects(); delay(1000); testtriangles(); delay(1000); mediabuttons(); delay(1000); // Exibe mensagem de Fim no Monitor Serial Serial.println("Fim"); // Aguarda 1s delay(1000); } void loop() { // Inverte cores no display tft.invertDisplay(true); // Aguarda 500 ms delay(500); // Volta às cores originais no display tft.invertDisplay(false); // Aguarda 500 ms delay(500); } // Sub-rotina testlines void testlines(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, 0, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, 0, 0, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, tft.height()-1, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color); delay(0); } } // Sub-rotina testdrawtest com texto e cor como parâmetros void testdrawtext(char *text, uint16_t color) { tft.setCursor(0, 0); tft.setTextColor(color); tft.setTextWrap(true); tft.print(text); } // Sub-rotina testfastlines com color1 e color2 como parâmetros void testfastlines(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t y=0; y < tft.height(); y+=5) { tft.drawFastHLine(0, y, tft.width(), color1); } for (int16_t x=0; x < tft.width(); x+=5) { tft.drawFastVLine(x, 0, tft.height(), color2); } } void testdrawrects(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color); } } void testfillrects(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=tft.width()-1; x > 6; x-=6) { tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1); tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2); } } // Sub-rotina testfillcircles com radius (raio) e cor como parâmetros void testfillcircles(uint8_t radius, uint16_t color) { for (int16_t x=radius; x < tft.width(); x+=radius*2) { for (int16_t y=radius; y < tft.height(); y+=radius*2) { tft.fillCircle(x, y, radius, color); } } } // Sub-rotina testdrawcircles com radius (raio) e cor como parâmetros void testdrawcircles(uint8_t radius, uint16_t color) { for (int16_t x=0; x < tft.width()+radius; x+=radius*2) { for (int16_t y=0; y < tft.height()+radius; y+=radius*2) { tft.drawCircle(x, y, radius, color); } } } // Sub-rotina testtriangles void testtriangles() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 0xF800; int t; int w = tft.width()/2; int x = tft.height()-1; int y = 0; int z = tft.width(); for(t = 0 ; t <= 15; t++) { tft.drawTriangle(w, y, y, x, z, x, color); x-=4; y+=4; z-=4; color+=100; } } // Sub-rotina testroundrects void testroundrects() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 100; int i; int t; for(t = 0 ; t <= 4; t+=1) { int x = 0; int y = 0; int w = tft.width()-2; int h = tft.height()-2; for(i = 0 ; i <= 16; i+=1) { tft.drawRoundRect(x, y, w, h, 5, color); x+=2; y+=3; w-=4; h-=6; color+=1100; } color+=100; } } //Sub-rotina tftPrintTest void tftPrintTest() { tft.setTextWrap(false); tft.fillScreen(ST77XX_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST77XX_RED); tft.setTextSize(1); tft.println("Hello World!"); tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); tft.println("Hello World!"); tft.setTextColor(ST77XX_GREEN); tft.setTextSize(3); tft.println("Hello World!"); tft.setTextColor(ST77XX_BLUE); tft.setTextSize(4); tft.print(1234.567); delay(1500); tft.setCursor(0, 0); tft.fillScreen(ST77XX_BLACK); tft.setTextColor(ST77XX_WHITE); tft.setTextSize(0); tft.println("Hello World!"); tft.setTextSize(1); tft.setTextColor(ST77XX_GREEN); tft.print(p, 6); tft.println(" Want pi?"); tft.println(" "); tft.print(8675309, HEX); // print 8,675,309 out in HEX! tft.println(" Print HEX!"); tft.println(" "); tft.setTextColor(ST77XX_WHITE); tft.println("Sketch has been"); tft.println("running for: "); tft.setTextColor(ST77XX_MAGENTA); tft.print(millis() / 1000); tft.setTextColor(ST77XX_WHITE); tft.print(" seconds."); } //Sub-rotina mediabuttons void mediabuttons() { // play tft.fillScreen(ST77XX_BLACK); tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE); tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED); delay(500); // pause tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE); tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN); delay(500); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE); delay(50); // pause color tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN); }
Carregue o código para seu Arduino Uno. Caso tenha conectado VCC em 3.3V verifique as cores em seu display. Caso estejam com manchas ou foscas, troque o VCC de 3.3V para 5V. As imagens do display devem aparecer como mostrado a seguir.

Você pode utilizar os conceitos semelhantes do artigo sobre display OLED para converter e gerar imagens em seu display IPS. Veja no artigo Como criar imagens no display OLED.
Gostou de conhecer o display IPS LCD e como realizar os testes nele? Amplia muito as possibilidades de exibição de imagens coloridas ou textos personalizados.
Se você tiver dúvidas, sugestões ou experiências para compartilhar, fique a vontade para deixar um comentário abaixo. E para não perder nenhum conteúdo como este, não deixe de nos seguir no Instagram.
Olá, gostei do artigo e gostaria de saber como quais são os pinos para conectar no esp32 c3 supermini. Estou planejando em fazer um dispositivo bluetooth que é enviado uma imagem ao esp e ele mostra na tela.
Olá Lucas,
No caso do ESP32 C3 Supermini os pinos SDA e SCL são nos pinos 8 e 9 respectivamente. Os demais pinos você pode escolher entre os outros pinos do ESP32.
Abraços!
Vinícius – Equipe MakerHero
Olá, tudo bem? Me chamo Junior.
Gostei muito do artigo. E pretendo fazer uns testes usando esse display. Mas, possuo uma dúvida: esse display pode ser usado para exibição de vídeo (como se fosse uma microtv)? Só para clarear um pouco as ideias, a minha intenção seria montar um óculos para exibir jogos a partir de um console, como se fosse um óculos vr. Isso seria possível? Esse display suporta esse tipo de aplicação (mesmo usando outra plataforma que não seja o Arduino)?
Desde já, muito obrigado.
Parabéns pelo trabalho.
Olá Junior!
Acredito que seja possível sim, mas não com o Arduino. Seria necessária uma plataforma que consiga processar o sinal de vídeo e transformar na interface SPI que o display necessita.
Pelo que observei no datasheet, acredito que seria possível uma taxa da atualização de 30 a 40 FPS.
Abraços!
Vinícius – Equipe MakerHero
Olá Vinícius!
Maravilha, muito obrigado pela orientação. Ajudou muito.
Abraços, tudo de bom para toda a equipe MakerHero
Boas Festas.
Olá!
De nada!
Abraços e boas festas pra você também!
Vinícius – Equipe MakerHero