Skip to content

Insper-Mecat-LSM/Tutorial_Imagens_TFT_ILI9341

Repository files navigation

Tutorial_Imagens_TFT_ILI9341

Tutorial para a inserção de curvas, imagens e animações no display tft de controlador ILI9341 utilizando biblioteca Adafruit GFX e MCUFRIEND

Agora que você já seguiu os passos para obtenção das bibliotecas necessárias para funcionamento do display e conheceu algumas funções básicas como a criação de linhas, retângulos, círculos e triângulos, é hora de explorarmos algumas ideias envolvendo imagens, animações e o traçado de curvas que a biblioteca permite.

Uma das estratégias mais comuns para simular movimentação de elementos sobre a tela é a dinâmica entre aceso e apagado. Um bom exemplo dessa estratégia são os jogos antigos no estilo Snake em que, à medida que o objeto avança e novos elementos são adicionados à frente, para manter o comprimento, o último elemento do conjunto é sobreposto por uma camada de mesma cor daquela de fundo, dando a impressão de que o objeto se move pela tela.

O código abaixo mostra a implementação dessa ideia. À medida que a variável é aumentada, um novo retângulo é exibido ligeiramente à frente e o imediatamente anterior é coberto por outro com a mesma cor de fundo.

// Bibliotecas
#include "Arduino.h"
#include "mbed.h"
#include <MCUFRIEND_kbv.h>

MCUFRIEND_kbv tft;

// Orientação do Display
uint8_t Orientation = 1; // Paisagem

// Tabela de Cores
#define BLACK 0x0000
#define BLUE 0x001F

// Variáveis
int y = 0;

// Função para desenhar Snake
void snake() {
  //Desenha o retângulo azul.
  tft.fillRoundRect(150, 140 - y, 10, 60, 0, BLUE);
  //'Apaga' com retângulo preto. Note que ele está deslocado de 60 px, que é o comprimento do retângulo azul.
  tft.fillRoundRect(150, 200 - y, 10, 40, 0, BLACK);
}

void setup(void) {
  tft.reset();
  tft.begin();
  tft.setRotation(Orientation);
  tft.fillScreen(BLACK); // Fundo do Display
}

void loop() {
  // Desenha, incrementa o valor de 'y' e espera 15 ms.
  snake();
  y++;
  wait_ms(15);
}

Nesse caso a movimentação ocorre em uma única direção. Perceba que um retângulo preto é criado logo atrás do retângulo em azul. Experimente alterar a cor de fundo do display para WHITE e veja o que está acontecendo.

Curvas

Curvas podem ser desenhadas com o auxílio de funções matemáticas. Portanto elipses, hipérboles, parábolas, catenárias, senoides etc. podem ter seus pontos calculados por expressões matemáticas e, a cada iteração, um novo pixel é desenhado na tela. Vejamos o exemplo.

//Bibliotecas
#include "mbed.h"
#include "Arduino.h"
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <math.h>

//Orientação do Display
uint8_t Orientation = 1; //Paisagem

//Tabela de Cores
#define BLACK   0x0000
#define GREEN   0x07E0
#define YELLOW  0xFFE0

//Variáveis
int x,y=0;
int x_0 = 5;
int y_0 = 100;
int A = 40;

int a = 5;
int b = 4;

//Criando funções
void seno (){
    //y =y0+ A*seno(6*x*0.0174533[grau para radiano])
    tft.drawPixel(x_0+x, y_0+A*sin(6*x*0.0174533), GREEN);
}

void cosseno (){
    //y =y0+ A*cosseno(6*x*0.0174533[grau para radiano])
    tft.drawPixel(x_0+x, y_0+A*cos(6*x*0.0174533), YELLOW);
}


void setup(void)
{
    tft.reset();
    tft.begin();
    tft.setRotation(Orientation);
    tft.fillScreen(BLACK);  // Fundo do Display

    //y = A*sin(x*0.0174533);

}

void loop() 
{
seno();
//cosseno();
x++;

wait_ms(5);
}

Caso deseje alterar a espessura da curva, busque criar offsets redesenhando a mesma curva alguns pixels para cima ou para baixo e verifique o resultado. Altere os parâmetros dentro da função para variar o período. O que acontece caso troque de drawPixel() para fillRoundRect() ? Reduza os retângulos de tamanho e aumente o raio de arredondamento. Se quiser traçar uma linha entre os pontos calculados, utilize a função drawLine().

Note que essa mesma funcionalidade pode traçar o estado de algum pino, gerando um gráfico no tempo ou associado a qualquer outra variável de interesse.

Imagens

A importação de imagens através da função drawBitmap() não ocorre de forma direta para o microcontrolador. Antes, é preciso convertê-la em uma matriz que possui os hexadecimais correspondentes a cada pixel da imagem. O autor obteve sucesso ao utilizar o site: http://www.rinkydinkelectronics.com/t_imageconverter565.php.

Nele, basta importar uma imagem nos formatos .png, .jpg ou .gif com as dimensões desejadas (lembre-se que seu display possui resolução de 320x240) e clicar em Make file. A seguir basta realizar download do arquivo .c. Para extrair a matriz gerada pelo site, abra o arquivo com o bloco de notas e copie tudo que estiver dentro das chaves de PROGMEN, segue código.

#include "mbed.h"
#include "Arduino.h"
#include <MCUFRIEND_kbv.h>

//#include "logo.h" //Descomente esta linha para utilizar o arquivo .h

MCUFRIEND_kbv tft;

//Orientação do Display
uint8_t Orientation = 1; //Paisagem

//Cores
#define BLACK   0x0000
#define WHITE   0xFFFF

void setup(void)
{
    tft.reset();
    tft.begin();
    tft.setRotation(Orientation);
    tft.fillScreen(WHITE);  // Fundo do Display
    
    //Cole os hexadecimais dentro das chaves abaixo. 
    //Caso use o arquivo .h, delete a linha abaixo e crie o arquivo .h
    const uint16_t  PROGMEM logo[] = {};
  
    //Parâmetros da função: posições x,y da imagem, array 'logo' e as dimensões da imagem
    tft.drawRGBBitmap(0,45, logo, 320, 129);//Insper    
}


void loop()
{   
    
}

Procure substituir os hexadecimais existentes, ajustando os parâmetros necessários (dimensões) e verifique se a imagem é carregada corretamente. Note que eventuais imperfeições deverão ser corrigidas diretamente na matriz que foi gerada pelo site, substituindo o hexadecimal pelo desejado.

Para remover essa grande quantidade de hexadecimais do main, podemos criar um arquivo .h e o referenciar no main, como foi feito no código acima, bastando descomentar a linha que referencia o .h e remover a linha que cria a logo[]. Portanto crie um arquivo logo.h dentro da pasta do seu projeto e o redija dessa forma:

//Arquivo .h 
#include "mbed.h"
#ifndef logo_h
#define logo_h

//Cole os hexadecimais dentro das chaves abaixo
const uint16_t  PROGMEM logo[] = {};

#endif

Animações

Para animações, a mesma ideia de sobreposição pode ser usada. A diferença é que ao invés de utilizarmos formas ou bitmaps estáticos, sobrescreveremos imagens ligeiramente diferentes, dando a ideia de animação. O autor recomenda a utilização de ‘sprites’, assim como você pode ter utilizado em DeSoft. Salve-os em um arquivo ‘.h’ e use-os sequencialmente, intercalados por uma forma (retângulo, triângulo, círculo) de mesma dimensão do sprite. Caso deseje movimentá-lo pela tela, siga a mesma ideia da seção 1 do ‘Snake’. Vamos ao exemplo:

#include "mbed.h"
#include "Arduino.h"
#include <MCUFRIEND_kbv.h>

#include "sprites.h"

MCUFRIEND_kbv tft;

//Orientação do Display
uint8_t Orientation = 1; //Paisagem

//Cores
#define BLACK   0x0000
#define WHITE   0xFFFF

int x=0;

void espera(){
    wait_ms(50);
}

void setup(void)
{
    tft.reset();
    tft.begin();
    tft.setRotation(Orientation);
    tft.fillScreen(BLACK);  // Fundo do Display

    
}

void loop()
{   
    tft.drawRGBBitmap(80+x,100, frame_0, 40, 40);//Frame 0/12
    espera();
    x+=2;
    tft.drawRGBBitmap(80+x,100, frame_1, 40, 40);//Frame 1/12
    espera();
    x+=2;
    tft.drawRGBBitmap(80+x,100, frame_2, 40, 40);//Frame 2/12
    espera();
    x+=2; 
    tft.drawRGBBitmap(80+x,100, frame_3, 40, 40);//Frame 3/12   
    espera();
    x+=2;
    tft.drawRGBBitmap(80+x,100, frame_4, 40, 40);//Frame 4/12  
    espera();
    x+=2;
    tft.drawRGBBitmap(80+x,100, frame_5, 40, 40);//Frame 5/12 
    espera();
    x+=2; 
    tft.drawRGBBitmap(80+x,100, frame_6, 40, 40);//Frame 6/12   
    espera();
    x+=2;
    tft.drawRGBBitmap(80+x,100, frame_7, 40, 40);//Frame 7/12  
    espera();
    x+=2; 
    tft.drawRGBBitmap(80+x,100, frame_8, 40, 40);//Frame 8/12  
    espera();
    x+=2; 
    tft.drawRGBBitmap(80+x,100, frame_9, 40, 40);//Frame 9/12   
    espera();
    x+=2;
    tft.drawRGBBitmap(80+x,100, frame_10, 40, 40);//Frame 10/12   
    espera();
    x+=2;
    tft.drawRGBBitmap(80+x,100, frame_11, 40, 40);//Frame 11/12
    espera(); 
    x+=2;   

}

Infelizmente a biblioteca não possui a opção de múltiplas camadas, de modo que não se torna tão trivial sobrescrever as imagens sem danificar a imagem de fundo.

Atenção: Para altas taxas de atualização da tela, recomenda-se utilizar imagens pequenas, 40x40 pixels por exemplo, para que a imagem seja rapidamente desenhada. Sempre tenha em mente o propósito do embarcado: imagens grandes consomem bastante memória e não são impressas na tela de forma instantânea aos olhos.

Se desejar realizar animações em que haja rotação da forma ou da imagem, busque por matriz de rotação. A eletiva de Visão de Máquina trará ferramental que auxiliará nessa tarefa.

About

Tutorial para a inserção de curvas, imagens e animações no display tft de controlador ILI9341 utilizando biblioteca Adafruit GFX e MCUFRIEND

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published