Exibir Fotos JPEG e Vídeo RGB565 em Display TFT SPI 2.8" com Arduino Nano
Componentes e Materiais
| Arduino Nano R3 | 1 |
| Display TFT SPI 2.8" 320x240 (com touchscreen) | 1 |
| Cartão microSD (>1GB) | 1 |
| Shield TFT (breakout) para Arduino Nano | 1 |
Sobre o Projeto
Introdução
Olá! Neste artigo, vou mostrar como visualizar fotos no formato *.jpg e reproduzir vídeos no formato RGB565 na tela de um display TFT SPI (320x240, 2.8").
Primeiro, uma pequena demonstração em vídeo:
Hardware
Componentes necessários:
- Arduino Nano R3
- Display TFT SPI (320x240) com touchscreen
- Cartão microSD >1GB
- Shield TFT para Arduino Nano
A montagem de todas as peças segue a ordem mostrada no vídeo (ou consulte o artigo anterior: TFT Shield for Arduino Nano - Start).
Software
Preparação do Cartão microSD
O cartão microSD deve ser formatado em FAT32. As imagens podem ser gravadas diretamente no cartão (sem nenhum processamento). É desejável que o tamanho das imagens não exceda 2560x1920 pixels.
Conversão de Vídeo para RGB565
Para reproduzir vídeos no formato RGB565, os arquivos devem ser preparados previamente. Use o ffmpeg (ffmpeg.org) para conversão. Baixe e instale no seu computador. Em seguida, utilize o comando de exemplo abaixo para gerar um vídeo compatível com esta demonstração:
ffmpeg -i video.avi -s 320x240 -pix_fmt rgb565 video.rgb
Bibliotecas e Sketch
Baixe e instale a biblioteca necessária para trabalhar com o shield TFT para Arduino Nano: YATFT.
Carregue o seguinte sketch no Arduino Nano:
/******************************************************************************
* SOFTWARE E DOCUMENTAÇÃO FORNECIDOS "COMO ESTÃO" SEM GARANTIA DE QUALQUER
* TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, SEM LIMITAÇÃO, QUALQUER GARANTIA
* DE COMERCIALIZAÇÃO, TÍTULO, NÃO VIOLAÇÃO E ADEQUAÇÃO PARA UM FIM
* ESPECÍFICO. EM NENHUM CASO O AUTOR OU SEUS LICENCIADORES SERÃO RESPONSÁVEIS
* OU OBRIGADOS SOB CONTRATO, NEGLIGÊNCIA, RESPONSABILIDADE ESTRITA,
* CONTRIBUIÇÃO, VIOLAÇÃO DE GARANTIA, OU OUTRA TEORIA JURÍDICA EQUITATIVA
* POR QUAISQUER DANOS DIRETOS OU INDIRETOS OU DESPESAS, INCLUINDO, MAS NÃO
* LIMITADO A QUAISQUER DANOS INCIDENTAIS, ESPECIAIS, INDIRETOS, PUNITIVOS
* OU CONSEQUENCIAIS, LUCROS PERDIDOS OU DADOS PERDIDOS, CUSTO DE AQUISIÇÃO
* DE BENS, TECNOLOGIA, SERVIÇOS SUBSTITUTOS, OU QUAISQUER REIVINDICAÇÕES
* DE TERCEIROS (INCLUINDO, MAS NÃO LIMITADO A QUALQUER DEFESA DELES), OU
* OUTROS CUSTOS SEMELHANTES.
*******************************************************************************/
#include <YATFT2.h> // Biblioteca específica do hardware
#include <SPI.h>
#include <XPT2046_Touchscreen.h>
#include <util/yasdc.h>
YATFT tft(0);
SDC sdc;
#define CS_PIN A0 // MOSI=11, MISO=12, SCK=13
XPT2046_Touchscreen ts(CS_PIN);
/* Se estiver usando o shield, todas as linhas de controle e dados são fixas,
e uma declaração mais simples pode ser usada opcionalmente: */
uint16_t frame = 0;
uint32_t total_time = 0;
bool f_first = true;
uint8_t mode = 0;
/*************************************************************************************************/
void setup(void) {
Serial.begin(115200);
Serial.println(F("Exemplo Photo And Video Play!"));
tft.begin(0x4391, -8); // Inicializa o display
tft.SetColor(BLACK);
tft.ClearDevice(); // Limpa a tela
ts.begin(); // Inicializa Touchscreen
SPI.end();
Serial.print(F("FS Init... "));
uint8_t state = sdc.FSInit();
if (state == 0) Serial.println(F("falhou."));
else Serial.println(F("sucesso."));
sdc.currentFileType = DEMO_FILE_TYPE_RGB;
total_time = millis() + 500;
}
void loop(void) {
if (total_time < millis()) {
total_time = millis() + 2000;
if (f_first == true) {
if (-1 != sdc.FindFirst("*.*", ATTR_ARCHIVE, &sdc.nextFile))
f_first = false; // Limpa flag
else
total_time = 0;
} else {
// Processamento de arquivos JPEG
if (sdc.GetFileType(sdc.nextFile.filename) == DEMO_FILE_TYPE_JPEG) {
if (sdc.currentFileType != DEMO_FILE_TYPE_JPEG) {
// Define modo YUV para exibir JPEG
tft.SetColor(0x007F); // Preto em YUV
tft.ClearDevice();
tft.SetYUV(); // Troca mostra leve piscar verde
sdc.currentFileType = DEMO_FILE_TYPE_JPEG;
}
Serial.print(" JPEGPutImage:");
Serial.println(sdc.nextFile.filename);
FSFILE * jpeg_file;
JPEG_DECODE jpeg_decode;
jpeg_file = sdc.FSfopen(sdc.nextFile.filename, "r");
if (!jpeg_file) {
Serial.println(F("Falha ao abrir!"));
return (FALSE);
}
jpeg_decode.stream = (void *)jpeg_file;
sdc.JPEGReadFromSD(&jpeg_decode, 0, 0, GetMaxX()+1, GetMaxY()+1);
uint8_t err = sdc.FSfclose(jpeg_file);
if (err) {
Serial.println(F("Falha ao fechar!"));
return err;
}
frame++;
frame &= 0xF;
total_time = millis() + 2000;
}
// Processamento de arquivos RGB (vídeo)
else if (sdc.GetFileType(sdc.nextFile.filename) == DEMO_FILE_TYPE_RGB) {
if (sdc.currentFileType != DEMO_FILE_TYPE_RGB) {
// Define modo RGB
tft.SetColor(BLACK); // Preto em RGB é verde escuro em YUV
tft.ClearDevice();
tft.SetRGB(); // Troca mostra leve piscar verde
sdc.currentFileType = DEMO_FILE_TYPE_RGB;
}
Serial.print(F("Reproduzindo vídeo RGB: "));
Serial.println(sdc.nextFile.filename);
FSFILE * pFile = sdc.FSfopen(sdc.nextFile.filename, "rb");
if (!pFile) {
Serial.println(F("Falha ao abrir!"));
return (FALSE);
}
tft.SetColor(BLACK);
tft.ClearDevice();
sdc.RGBReadFromSD(pFile, &ScanTouch);
mode = 0;
tft.SetColor(BLACK);
tft.ClearDevice();
sdc.FSfclose(pFile);
total_time = millis() + 1000;
}
if (-1 == sdc.FindNext(&sdc.nextFile)) {
f_first = true; // Define flag
}
}
}
}
uint8_t ScanTouch(void) {
uint16_t x, y;
// Touch
// Quando o pino SS é definido como OUTPUT, pode ser usado como
// porta de saída de propósito geral (não influencia operações SPI).
SPI.begin();
if (ts.touched()) {
TS_Point p = ts.getPoint();
delay(3); // Delay para filtragem
SPI.end();
// Calcula coordenadas x, y a partir do código ADC
if (p.x < 450) p.x = 450;
if (p.y < 500) p.y = 500;
x = (uint16_t)(320L - ((uint32_t)p.x - 450L) * 10L / 106L);
y = (uint16_t)(240L - ((uint32_t)p.y - 500L) * 10L / 140L);
// Botão Stop
if (x < 130 && y > 100 && y < 140) {
mode = 1;
Serial.println(F("mode = 1"));
}
// Botão Pause
else if (x > 140 && x < 180 && y > 100 && y < 140) {
mode = 2;
// Desenha botões
tft.SetColor(BRIGHTRED);
tft.DrawFillCirc(GetMaxX()/4, GetMaxY()/2, 50);
tft.SetColor(BRIGHTYELLOW);
tft.DrawFillRect(GetMaxX()/4-30, GetMaxY()/2-30, GetMaxX()/4+30, GetMaxY()/2+30);
tft.SetColor(BRIGHTRED);
tft.DrawFillCirc(GetMaxX()/4*3, GetMaxY()/2, 50);
tft.SetColor(BRIGHTYELLOW);
for (uint8_t i = 0; i < 60; i++) {
tft.DrawLine(210+i, 90+i/2, 210+i, 150-i/2);
}
Serial.println(F("mode = 2"));
}
// Botão Play
else if (x > 190 && y > 100 && y < 140) {
mode = 0;
Serial.println(F("mode = 0"));
}
return mode;
}
SPI.end();
return mode;
}
Tentei fazer um artigo curto e descrever os pontos principais. Não há nada difícil neste projeto. Mas se tiver dúvidas, pergunte à vontade! ;-) Tentarei adicionar mais artigos.
Obrigado pela atenção!
Continua...
Artigos Anteriores:
- Unique TFT Shield for Arduino Uno - Start
- Unique TFT Shield for Arduino Uno - OV7670 Cam Live View
- Unique TFT Shield for Arduino Uno - Arduino Bluetooth Camera (ABC)
- TFT Shield for Arduino Nano - Start
Atualização 01.04.2021:
Olá novamente! Há uma biblioteca atualizada para uma série de telas, que atualmente consiste em dois shields e duas breakout boards. O sketch é compilado dependendo da versão selecionada (de 1 a 4) e do tipo de microcontrolador (MegaAVR ou ESP-32). Foram adicionadas fotos e exemplos. Mais informações podem ser encontradas em https://github.com/Ekaburg/EkaTFT.
Código
PhotoAndVideoPlay.ino
O código completo está disponível no repositório GitHub da biblioteca YATFT.
Esquemáticos
Biblioteca TFT Shield para Arduino Nano
https://github.com/YATFT/YATFT
Processo de manufatura
- Transformando Manufatura com Mobilidade: Soluções de Dados, Voz, Vídeo e Localização
- Novo Conversor HDMI‑APIX3 Capacita Testes de Vídeo Automotivo e ADAS
- DATA MODUL Lança Display TFT Ultra-Slim 23,1" com Controle Smart Wi-Fi
- Leitura de Sensores Analógicos com Raspberry Pi e Zabbix: Guia Passo a Passo
- Como Instalar Display TFT 3.5″ Kuman no RetroPie – Guia Passo a Passo
- K 2019 Apresenta Máquinas de Reciclagem de Ponta e Inovações em Embalagens Sustentáveis
- Entendendo Designações DN e PN em Flanges: Guia Completo
- Display 3D Holográfico de Campo de Luz: Visão Clara e sem Distorção para Realidade Aumentada
- Guia Profissional de Animação de Bitmap no Shield TFT Touchscreen ILI9341 2,4″ com Arduino
- Dominando Acabamentos de Injeção: Normas SPI e VDI Explicadas