Arduino e Vídeo Composto em sua TV, Biblioteca TVout.

20-inch-TV

Que o Arduino pode ser utilizado para uma infinidade de coisas já sabemos, mas que tal gerar sinais de vídeo? O Arduino consegue? A resposta é sim, e isso é feito utilizando-se a biblioteca TVout escrita por Myles Metzer, que torna fácil mostrar caracteres, e nem tão fácil assim, figuras. A página da biblioteca, que contém tutorias e informações está disponível aqui.

Utilizando a biblioteca TVout é possível gerar sinais PAL ou NTSC, lembre-se que o padrão no Brasil é o PAL,  à resolução de 128×96 pixels  em preto e branco, não é nehum Full HD com milhões de cores, porém  é mais do que suficiente para entreter qualquer hobista, além disso, a conexão é entre Arduino e TV é muito simples e rápida de se fazer.

Essa biblioteca é usada no hackvision , que é uma placa vídeo game baseada em Arduino, e no video game shield.

Material Necessário:

1 Placa Arduino(Mega, UNO, Nano… tanto faz).

1 Resistor de 1kΩ(marrom,preto, vermelho).

1 Resistor de 470Ω(amarelo,violeta, marrom).

1 Conector RCA fêmea(retirei o meu de sucata, porém ao invés disso, um cabo RCA pode ser cortado e usado ).

Protoboard.

Jumpers.

Sim, para mostrar vídeo em sua TV usando um Arduino é necessário apenas isso, componentes que podem ser encontrados em  qualquer loja de eletrônica.

Montagem

A montagem, como dito é muito simples. O esquemático pode ser visto na figura abaixo:

 

Screen Shot 06-25-14 at 10.06 AM

Na figura não está muito claro,por causa do design do conector, mas os resistores devem ser ligados ao pino no centro do conector enquanto a “casca” externa do conector deve ser conectada ao terra (ground) do Arduino.

As conexões podem variar dependendo  da placa Arduino utilizada,  nos modelos Uno, Nano, Decimila e Duemilanove  baseados no microcontrolador Atmega328 as conexões são como na figura acima. As imagens abaixo foram retiradas do site da  biblioteca e mostram a ligação para cada Modelo.

5225072558_5f5f760037

Como pode ser visto na figura abaixo, as conexões mudam para o Arduino Mega que possui um microcontrolador diferente, o Atmega1280 ou 2560 e para o Sanguino, que é uma placa baseada em Arduino e usa o Atmega644 ou 1284,  e é utilizada no projeto RepRap que visa impressoras 3D caseiras e replicantes.

Screen Shot 06-22-14 at 03.40 PM

Download e instalação da biblioteca

Primeiro é necessário baixar a biblioteca TVout no site da mesma ou aqui. Depois de baixar a biblioteca instale a na IDE do Arduino, extraindo os arquivos baixados na pasta “libraries” onde estiver instalado sua IDE do Arduino.

Screen Shot 06-22-14 at 03.58 PM
Arquivos baixados no site da biblioteca TVout.
Screen Shot 06-22-14 at 04.00 PM
Os Arquivos baixados foram movidos para a pasta libraries do Arduino.

Depois de terminada a instalação, estamos prontos para utilizar as funções disponíveis na biblioteca e mostrar algo em uma TV.

Código

O código a seguir mostra alguns bitmapss na TV, você pode criar suas próprias imagens para mostrar na tela, os arquivos met.h e invader.h foram criados por mim e devem ser baixados aqui, caso você queira adicioná-los ao seu código.

O resolução utilizada no código é 120×96 pixels, sendo o ponto 0,0  o canto superior esquerdo da televisão, você pode exibir o texto ou uma imagem em um ponto específico, se orientando a partir desse ponto.

#include <TVout.h>
#include <fontALL.h>
#include "met.h"
#include "invader.h"

TVout TV;
void setup() {
  TV.begin(PAL,120,96);
  TV.select_font(font6x8);
  TV.println(0,40,"Arduino e TV com a\nbiblioteca TVout\n");
  TV.delay(2500);
  TV.clear_screen();
  TV.println(0,40,"Desenhando Imagens:");
  TV.delay(1500);
  TV.clear_screen();
  TV.bitmap(18,0,met);
  TV.delay(10000);
  
  for(int i=0;i<90;i++){
  TV.clear_screen();
  TV.bitmap(i,0,invader);
  TV.delay(100);
  }
  for(int i=90;i>0;i--){
  TV.clear_screen();
  TV.bitmap(i,0,invader);
  TV.delay(100);
  }
 
  TV.clear_screen();
  TV.print(9,44,"Dragao sem Chama");
  TV.delay(2000); 
}

void loop() {
}

Baixe o código e os arquivos .h aqui.

Me perdoem pela qualidade ruim do vídeo, foi que deu  pra conseguir.

*ATENÇÃO*  O vídeo contém padrões com luzes piscantes, então se você possui algum problema de saúde relacionado a esses padrões, recomendo que não assista.

Como mostrar seus próprios bitmaps

Para mostrar suas imagens bitmap você deve:

1- Em um programa de edição de imagens( o bom e velho paint serve), redimensione a imagem que se quer exibir para um tamanho menor que a resolução de 128×90 pixels. Salve a imagem como Bitmap monocromático. Abaixo um exemplo:

2- Baixe o programa Image2Code, ele serve para transformar as imagens bitmap em código.

3- Abra o Image2Code e selecione a imagem que você editou e transformou em bitmap, depois selecione a terceira opção da esquerda para a direita.

Screen Shot 06-24-14 at 11.07 PM

A opção “Invert Image”, se ativada, trocará as cores da sua imagem, então vai depender do que você quer mostrar, por exemplo, o space invader no vídeo não foi invertido já que ele é “branco no preto”. Caso a imagem estivesse sido invertida, ia ficar algo “preto no preto”, então pense um pouco antes para saber se sua imagem precisa ter as cores invertidas.

4- Deixe a opção C Array Writer e clique em “Convert”. Um arquivo do bloco de notas será aberto como na imagem:

Screen Shot 06-24-14 at 11.13 PM

5- Apague:

  • Os ‘{‘ e ‘}’, use a ferramenta substituir, em editar. Substitua-os(opção ‘Substituir tudo’) por nada ‘ ‘(deixe como está ou coloque um espaço).
  • A última vírgula do arquivo.

Screen Shot 06-24-14 at 11.17 PM

6- Agora crie um arquivo cpp, pode ser no bloco de notas, com o seguinte código, substituindo os  ‘link’ pelo nome que desejar, porém é melhor, para evitar bagunça, colocar o nome da imagem.

#include "link.h"
PROGMEM const unsigned char link[] = {
90,90,
0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x03,0xFF,0xC0,0x07,0xFF,0xFC,0x00,0x00,0x00,0x00,
0x00,0x00,0x03,0xFF,0xC0,0x07,0xFF,0xFC,0x00,0x00,0x00,0x00,
0x00,0x00,0x03,0xFF,0xC0,0x07,0xFF,0xFC,0x00,0x00,0x00,0x00,
0x00,0x00,0x03,0xFF,0xC0,0x07,0xFF,0xFC,0x00,0x00,0x00,0x00,
0x00,0x00,0x03,0xFF,0xC0,0x07,0xFF,0xFC,0x00,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xC0,0x00,0x00,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xC0,0x00,0x00,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xC0,0x00,0x00,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xC0,0x00,0x00,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xC0,0x00,0x00,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xF0,0x3F,0xFF,0xFF,0x03,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xF0,0x3F,0xFF,0xFF,0x03,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xF0,0x3F,0xFF,0xFF,0x03,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xF0,0x3F,0xFF,0xFF,0x03,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xF0,0x3F,0xFF,0xFF,0x03,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xF0,0x3F,0xFF,0xFF,0x03,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x7E,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x00,0x7F,0xF0,0x3E,0x00,0x1F,0x03,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xF0,0x3E,0x00,0x1F,0x03,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xF0,0x3E,0x00,0x1F,0x03,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xF0,0x3E,0x00,0x1F,0x03,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xF0,0x3E,0x00,0x1F,0x03,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xF0,0x3E,0x00,0x1F,0x03,0xFF,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xFE,0x00,0x00,
0x03,0xE0,0x7F,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xFE,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x00,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x00,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x00,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x00,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x00,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x00,0x00,0x1F,0x00,0x1F,0x80,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x1F,0xFF,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,
0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00
};

Salve como “nomedaimagem.cpp” selecionando a opção “todos os arquivos”.

Screen Shot 06-24-14 at 11.28 PM

 

7- Novamente no boloco de notas, crie um arquivo com o seguinte conteúdo, substituindo ‘LINK’ e ‘link’ pelo nome que você colocou no arquivo anterior.

# include 
# ifndef LINK_H
# define LINK_H

extern const unsigned char link[];
#endif

Screen Shot 06-24-14 at 11.32 PM

E salve como “nomedaimagem.h”, lembrando de selecionar a opção “todos os arquivos”.

Screen Shot 06-24-14 at 11.30 PM

8 – Por fim, coloque esses arquivos na pasta do seu código e use-os como:

TV.bitmap(x,y,Bitmap);

 

Onde x e y são as coordenadas onde se quer inserir a imagem, e ‘link’ deve ser substituído pelo nome que você deu aos seus arquivos.

Exemplo:

TV.bitmap(20,0,link);

Qualquer dúvida, deixe nos comentários.

É isso pessoal! Idéias? que tal implementar algum tipo de jogo? Visor de gráficos? muita coisa bacana pode ser feita com esse esquema. Até outro post o/.

 

Robson Couto

Recentemente graduado Engenheiro Eletricista. Gosto de dedicar meu tempo a aprender sobre computadores, eletrônica, programação e engenharia reversa. Documento meus projetos no Dragão quando possível.

21 thoughts to “Arduino e Vídeo Composto em sua TV, Biblioteca TVout.”

  1. cara ñ tá dando certo …:( ve o q pode ser.os erros são estes:

    tv2.ino: In function ‘void setup()’:
    tv2.ino:9:12: error: ‘PAL’ was not declared in this scope
    tv2.ino:10:25: error: invalid conversion from ‘const unsigned char*’ to ‘uint8_t {aka unsigned char}’ [-fpermissive]
    In file included from tv2.ino:1:0:
    C:\Users\Mauricio\Documents\Arduino\libraries\TVout/TVout.h:103:7: error: initializing argument 1 of ‘void TVout::select_font(uint8_t)’ [-fpermissive]
    void select_font(uint8_t f);
    ^
    tv2.ino:11:6: error: ‘class TVout’ has no member named ‘println’
    tv2.ino:14:6: error: ‘class TVout’ has no member named ‘println’

  2. Robson! percebi que mudei o nome do arquivo…..sem querer adicionei uma letra “t” no final (não me pergunte como!!!) Agora deu certinho,muito legal; vlw pelo Post mano!!!

  3. Fala aew galera, eu ainda não testei Pq no momento estou sem pc mas planejo fazer um game bem da hora, um rpg com a visão de 45 graus estilo the legend of zelda se alguém quiser ajudar ou compartilhar conhecimentos me envie um email wattafukbr@gmail.com.

  4. Galera, eu gostaria de inserir um valor de inclinação medida por um acelerômetro no canto inferior da tela mas mixando a imagem de uma câmera de forma que eu apenas acrescente a informação que quero na imagem da câmera sacaram? É possível fazer isso?

    1. Infelizmente com essa biblitoeca não é possivel Cleiton, pra isso é necessário escrever valores analogicos no sinal da tv, o atmega sozinho não faz isso, são necessarios um conversor adc e outra biblioteca

    1. Olá Pedro. Pode ser que mude a cor ou o brilho da imagem. Mas eu não recomendo mudar os resistores sem antes ter certeza do que está fazendo. Esses resistores são super comuns e podem ser encontrados em qualquer loja de eletrônica.

  5. Tem como você mostrar como é feita a conexão do rca com os resistores. Vi outros projetos,mas não estou entendendo como é feita a soldagem e não sei qual é o rca utilizado (poderia mandar uma foto)?

    1. OI Kyra
      Desculpa, o cabo rca tem dois fios. Você tem que descobrir qual dos dois é o do sinal e qual é o GND, geralemente o GND parece uma malha (ou trança) e o outro tem a capinha de borracha.
      O GND é super importante e deve ser conectado, caso você use um conector RCA em vez de cortar um cabo, o GND é a parte mais externa do conector enquanto o sinal fica no centro.
      O cabo que eu usei era igual a esse, eu cortei na metade:
      https://cdn.sparkfun.com/assets/f/c/9/7/4/5113df13ce395f0f7e000000.jpg

      Qualquer dúvida só perguntar aqui novamente.

  6. Oi Robson,
    Parabéns, excelente matéria.

    Em 2019 estava procurando sobre como gerar imagens a partir do Arduino, e o seu artigo/vídeo foi o primeiro que encontrei, falando sobre a biblioteca TVOut e a montagem do respectivo hardware.
    Hoje consigo desenvolver meus próprios jogos de videogame utilizando a TVOut e outras bibliotecas.

    Obrigado.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *