LusoRobótica - Robótica em Português

Sistemas específicos => PIC => Tópico iniciado por: nunosilvarocha em 30 de Setembro de 2014, 11:14

Título: PIC_VGA
Enviado por: nunosilvarocha em 30 de Setembro de 2014, 11:14
Preciso mostrar as corres RGB e a mistura delas num ecrã por VGA.

A ideia é ligar a ficha VGA a um Pic 18f4550 e conseguir reproduzir as cores numa resolução 800x600.
Já procurei no google, existem projetos muito parecidos, mas não é bem o que quero.

Depois quero poder mudar a cor através do USART.

Seria bom conseguir ainda mostrar as cores RGB e a sua mistura numa imagem composta por listas/barras de cores.

Alguém já fez algo semelhante?
Título: Re: PIC_VGA
Enviado por: senso em 30 de Setembro de 2014, 11:24
Com AVR's conheço alguns projectos desses, mas penso que nenhum é capaz de gerar VGA com uma resolução de 800x600, se é para meter um ecrã cheio de cores e pouco mais, para quê tanta resolução?
Título: Re: PIC_VGA
Enviado por: nunosilvarocha em 30 de Setembro de 2014, 11:27
Com AVR's conheço alguns projectos desses, mas penso que nenhum é capaz de gerar VGA com uma resolução de 800x600, se é para meter um ecrã cheio de cores e pouco mais, para quê tanta resolução?

Também já vi alguns projetos com AVR, mas não estou muito à vontade com AVR
Que resolução aconselhas? Não conheces nenhum protejo do género com PIC?
Título: Re: PIC_VGA
Enviado por: senso em 30 de Setembro de 2014, 11:40
Em PIC provavelmente terás de saltar para um dsPIC ou PIC24, um 18f é provavelmente demasiado lento.
Título: Re: PIC_VGA
Enviado por: msr em 30 de Setembro de 2014, 11:41
Com AVR ou PIC é irrelevante, usas naturalmente o que te for mais familiar.
O que precisas de saber é como gerar os sinais VGA e depois implementar isso no microcontrolador:
http://lmgtfy.com/?q=generate+vga+signals (http://lmgtfy.com/?q=generate+vga+signals)

Mais fácil e educativo do que ires olhar para código já feito :)
Título: Re: PIC_VGA
Enviado por: senso em 30 de Setembro de 2014, 11:44
Tipicamente é tudo em assembly, dado que tens de ser cycle accurate, a imprecisão de tempo de chamada a uma interrupção é fatal, nos AVR's dependendo de onde estás saltar para uma ISR demora 3 ou 4 ciclos, basta isso para te chatear a gerar VGA ou video composto.
É simplesmente uma questão de instruções por segundo, dado que o PIC corre no máximo a 48Mhz, e que internamente divide o clock por 4 devido á sua arquitectura, diria ser lento demais.
Título: Re: PIC_VGA
Enviado por: nunosilvarocha em 30 de Setembro de 2014, 12:58
Com AVR ou PIC é irrelevante, usas naturalmente o que te for mais familiar.
O que precisas de saber é como gerar os sinais VGA e depois implementar isso no microcontrolador:
http://lmgtfy.com/?q=generate+vga+signals (http://lmgtfy.com/?q=generate+vga+signals)

Mais fácil e educativo do que ires olhar para código já feito :)

Esse link de 'ajuda' eu já utilizei.
Neste momento estou com dificuldades do vertical front porch, pois estão a aparecer umas falhas no lado esquerdo do ecrã e a cor não aparece totalmente perfeita.

Por isso estava a tentar encontrar algum exemplo para solucionar o meu problema.
Título: Re: PIC_VGA
Enviado por: jm_araujo em 30 de Setembro de 2014, 14:45
Se é do lado esquerdo onde começa o varrimento, deves estar com jitter na geração do sync.
Como disse o senso, tens de ser preciso ao ciclo e só com assembly é que te safas.
Quanto às cores não estarem corretas, confirma se os níveis estão corretos nos sinais RGB.

Título: Re: PIC_VGA
Enviado por: senso em 30 de Setembro de 2014, 16:52
Como é que estás a gerar a as cores, dac r-2r discreta?
Não esperes muito mais que 6-7 bits de resolução efectiva.
Título: Re: PIC_VGA
Enviado por: beirao em 30 de Setembro de 2014, 20:58
Eu ja fiz isso mas foi numa FPGA, numa cadeira de licenciatura, ha uns tres anos...

Pelo que me lembro, o varrimento VGA é a 25MHz, certo? Se fores para um PIC, utiliza um que vá até 64MHz. Tipicamente os das séries "K" podes utilizar um cristal de 16Mhz e depois fazes PPL para os 64MHz (18F46k22 por exemplo)
Título: Re: PIC_VGA
Enviado por: Tech_JA em 01 de Outubro de 2014, 07:15
encontrei este projecto na net, pode ser que ajude para a geração dos sincronismos:
http://tinyvga.com/pic-vga (http://tinyvga.com/pic-vga)
Título: Re: PIC_VGA
Enviado por: jm_araujo em 01 de Outubro de 2014, 10:07
Eu ja fiz isso mas foi numa FPGA, numa cadeira de licenciatura, ha uns tres anos...

Pelo que me lembro, o varrimento VGA é a 25MHz, certo? Se fores para um PIC, utiliza um que vá até 64MHz. Tipicamente os das séries "K" podes utilizar um cristal de 16Mhz e depois fazes PPL para os 64MHz (18F46k22 por exemplo)

25Mhz é o pixel clock (1/duração do pixel). Isso é um exagero se só quer gerar barras (que tem vários pixeis de largura). Se usar barras de 25 pixeis de largura , pode baixar o pixel clock para 1MHZ e ainda consegue desenhar 25 barras.
Tens exemplos de pessoal a gerar VGA com a velhinha PIC 16f84 a 4MHz (4 ciclos por instrução, 8 para  jumps): http://tinyvga.com/pic-vga (http://tinyvga.com/pic-vga), mas quase não sobram instruções para pôr um led a piscar, pelo que algo mais recente com um clock maior não é má ideia ;)
Título: Re: PIC_VGA
Enviado por: senso em 01 de Outubro de 2014, 15:17
E tens o outro extremo:
http://www.linusakesson.net/scene/craft/ (http://www.linusakesson.net/scene/craft/)

Avr a gerar som e video VGA, demoscene porn  ;D
Título: Re: PIC_VGA
Enviado por: jm_araujo em 01 de Outubro de 2014, 16:11
Muito doido... mas vindo da demoscene não é de admirar. Esses gajos são gurus da otimização.
Houve uma altura que seguia e as demos de 4k(bytes) eram alucinantes (https://www.youtube.com/watch?v=G1Q9LtnnE4w (https://www.youtube.com/watch?v=G1Q9LtnnE4w) , 3D todo feito em SW, as graficas 3D ainda estavam a começar) , e hoje fazem-se coisas doidas com 256bytes e tamanhos do género: https://www.youtube.com/watch?v=R35UuntQQF8 (https://www.youtube.com/watch?v=R35UuntQQF8)
http://www.theverge.com/2013/12/1/5162414/p01-demo-fits-minecraft-flyby-into-256-bytes-of-data (http://www.theverge.com/2013/12/1/5162414/p01-demo-fits-minecraft-flyby-into-256-bytes-of-data)

E há quem comece a olhar para os 16 bytes  :o
http://countercomplex.blogspot.com/2011/06/16-byte-frontier-extreme-results-from.html?_sm_au_=i5FsvZLqLnS44SRs (http://countercomplex.blogspot.com/2011/06/16-byte-frontier-extreme-results-from.html?_sm_au_=i5FsvZLqLnS44SRs)
Título: Re: PIC_VGA
Enviado por: dropes em 02 de Outubro de 2014, 00:19
Conheço o projecto Uzebox à uns anos e o atmega644 funciona a 8bits com som e imagem, de vez em quando lá aparece um jogo novo.
Também existem uns vídeos pelo youtube com essa "consola"
http://belogic.com/uzebox/index.asp (http://belogic.com/uzebox/index.asp)
Título: Re: PIC_VGA
Enviado por: nunosilvarocha em 14 de Outubro de 2014, 21:17
Encontrei um protejo com o Attiny que quase já soluciona o meu problema nesta fase inicial.
Agora estou com outro problema.
No MPlab com Hitech, quando executo algo do tipo:
Código: [Seleccione]
if (a==1)
    RD1=1;
else
     RD2=1;

O que está a acontecer é que liga o bit 1 ou 2 e desliga o resto dos bits do PORTD.
O que está a acontecer? Como altero apenas um bit sem ter que me preocupar com os restantes?
Título: Re: PIC_VGA
Enviado por: senso em 14 de Outubro de 2014, 23:21
Não tens de usar PORTD.lat ou algo do género?
Título: Re: PIC_VGA
Enviado por: beirao em 14 de Outubro de 2014, 23:24
No hitech não sei que nunca usei, mas no c18 ou xc8 é LATDbits.LATD1 =1.

Assim de repente, pesquisando no google, alguns exemplos têm como tu tens. se ninguém daqui te ajudar, mete o código todo que pode ser de outra coisa
Título: Re: PIC_VGA
Enviado por: nunosilvarocha em 21 de Outubro de 2014, 10:01
Cá está o codigo.
O que está a acontecer é que na função 'main' quando entramos no ciclo 'if' ao fazer 'RA=0' desliga o 'PORTA' todo.

Código: [Seleccione]
#include <htc.h>


__CONFIG(1, INTCLKO);           // Configuração do oscilador como interno
//CPUDIV1-CPU sem divisão de frequência
__CONFIG(2, WDTDIS); //WatchDog desactivado
__CONFIG(3, MCLRDIS); //Pino de reset desactivado
__CONFIG(4, DEBUGEN&LVPDIS);    //DEBUGEN-debug activado
//LVPDIS-Low-Voltage programming disabled
//(necessário para debugging)

void USARTInit();
void USARTescreverByte(char);
void USARTescreverString(const char *);
void USARTescreverLine(const char *);
void USARTescreverInt(int ,unsigned char);
unsigned char USARTlerByte();

void on_off();
void resolution();
void intervalo();

char data;

void main(void)
{
    OSCCON = 0b11001111; //Configuração do oscilador
// 0,1 - Define como oscilador interno
// 2 - Define como oscilador interno estável
// 3 - Define como oscilador interno estável
// a funcionar como clock
// 4,5,6 - Define a frequencia do oscilador para 1MHz
                                        // 7 - Abilita o modo IDLE

//Inicializa Porto A como saida de dados
TRISA=0;
    PORTA=0b00000011;
        //Inicializa Porto C como saida de dados
TRISC=0;
    PORTC=0;

        TRISB=0;
    PORTB=0XFF;
       
        unsigned s=1;
//Inicializar a USART
    USARTInit();
        USARTescreverLine("Escolha a resolucao");
        resolution();
        USARTescreverLine("Ligar o sistema");
        on_off();


    while(1)
    {
            data=USARTlerByte();

            if (data=='0')
            {
                RA0=0;
                intervalo ();
                RA0=1;
            }
            if (data=='1')
            {
                RA1=0;
                intervalo ();
                RA1=1;
            }
            if (data=='9')
            {
                on_off();
            }



       }
}

void on_off()
{
    unsigned int a=0;
   
    while(!a)
    {
        USARTescreverLine("ON(1)|OFF(0)");
        data=USARTlerByte();
        if (data=='1')
        {
            RA2=1;
            USARTescreverLine("Sistema_ON");
            a=1;
        }
        else if (data=='0')
        {
            RA2=0;
            USARTescreverLine("Sistema_OFF");
            a=1;
        }
           
    }
}
void resolution()
{
    unsigned int s=0;
    while(!s)
    {
        data=USARTlerByte();
        if (data=='1')
        {
            PORTB=0b00111111;
            s=1;
        }
        if (data=='2')
        {
            PORTB=0b01011111;
            s=1;
        }
        if (data=='3')
        {
            PORTB=0b01101111;
            s=1;
        }
        if (data=='4')
        {
            PORTB=0b01110111;
            s=1;
        }
        if (data=='5')
        {
            PORTB=0b01111011;
            s=1;
        }
        if (data=='6')
        {
            PORTB=0b10111111;
            s=1;
        }
        if (data=='7')
        {
            PORTB=0b11011111;
            s=1;
        }
        if (data=='8')
        {
            PORTB=0b11111111;
            s=1;
        }
    }
    USARTescreverLine("Resolucao escolhida");
}

void intervalo ()
{
    unsigned int i=0, a=0;
    for(i=0; i<500; i++)
    {
        a++;
    }

}

void USARTInit()
{
//Baud Rate = 9600 Bits por Second
//Gerador de taxa de transmissão SPBRG
SPBRG=25;

//TXSTA REG
TXEN=1;
BRGH=1;

//RCSTA
SPEN=1;
CREN=1; //Habilita Receiver (RX)

//BAUDCON
BRG16=1;

}

void USARTescreverByte(char ch)
{
//Espera até receber alguma coisa
while(!TXIF);

//Lê caracter
TXREG=ch;
}

void USARTescreverString(const char *str)
{
while((*str)!='\0')
{
//Espera até receber alguma coisa
while(!TXIF);

//Lê caracter
TXREG=(*str);

//incrementa para ler o proximo
str++;
}
}



void USARTescreverLine(const char *ln)
{
USARTescreverString(ln);
USARTescreverString("\r\n");
}

void USARTescreverInt(int val,unsigned char field_length)
{
if(val<0)
{
USARTescreverByte('-'); //Write '-' sign for negative numbers.
val=(val*(-1)); //Make it positive.
}

//Convert Number To String and pump over Tx Channel.
char str[5]={'0','0','0','0'};
int i=4,j=0;
while(val)
{
str[i]=val%10;
val=val/10;
i--;
}
if(field_length>5)
while(str[j]==0) j++;
else
j=5-field_length;

for(i=j;i<5;i++)
{
USARTescreverByte('0'+str[i]);
}
}


unsigned char USARTlerByte()
{
while(!RCIF); //Wait for a byte

return RCREG;
}
Título: Re: PIC_VGA
Enviado por: jmiguelff em 21 de Outubro de 2014, 14:35
O que é o RA??

Tu estas a fazer operações de bits em binário tipo "PORTA=0b00000011;", podes usar a mesma filosofia para trocar um só bit de PORTA.
Título: Re: PIC_VGA
Enviado por: Sérgio_Sena em 21 de Outubro de 2014, 17:22
Cá está o codigo.
O que está a acontecer é que na função 'main' quando entramos no ciclo 'if' ao fazer 'RA=0' desliga o 'PORTA' todo.

Código: [Seleccione]
#include <htc.h>


__CONFIG(1, INTCLKO);           // Configuração do oscilador como interno
//CPUDIV1-CPU sem divisão de frequência
__CONFIG(2, WDTDIS); //WatchDog desactivado
__CONFIG(3, MCLRDIS); //Pino de reset desactivado
__CONFIG(4, DEBUGEN&LVPDIS);    //DEBUGEN-debug activado
//LVPDIS-Low-Voltage programming disabled
//(necessário para debugging)

void USARTInit();
void USARTescreverByte(char);
void USARTescreverString(const char *);
void USARTescreverLine(const char *);
void USARTescreverInt(int ,unsigned char);
unsigned char USARTlerByte();

void on_off();
void resolution();
void intervalo();

char data;

void main(void)
{
    OSCCON = 0b11001111; //Configuração do oscilador
// 0,1 - Define como oscilador interno
// 2 - Define como oscilador interno estável
// 3 - Define como oscilador interno estável
// a funcionar como clock
// 4,5,6 - Define a frequencia do oscilador para 1MHz
                                        // 7 - Abilita o modo IDLE

//Inicializa Porto A como saida de dados
TRISA=0;
    PORTA=0b00000011;
        //Inicializa Porto C como saida de dados
TRISC=0;
    PORTC=0;

        TRISB=0;
    PORTB=0XFF;
       
        unsigned s=1;
//Inicializar a USART
    USARTInit();
        USARTescreverLine("Escolha a resolucao");
        resolution();
        USARTescreverLine("Ligar o sistema");
        on_off();


    while(1)
    {
            data=USARTlerByte();

            if (data=='0')
            {
                RA0=0;
                intervalo ();
                RA0=1;
            }
            if (data=='1')
            {
                RA1=0;
                intervalo ();
                RA1=1;
            }
            if (data=='9')
            {
                on_off();
            }



       }
}

void on_off()
{
    unsigned int a=0;
   
    while(!a)
    {
        USARTescreverLine("ON(1)|OFF(0)");
        data=USARTlerByte();
        if (data=='1')
        {
            RA2=1;
            USARTescreverLine("Sistema_ON");
            a=1;
        }
        else if (data=='0')
        {
            RA2=0;
            USARTescreverLine("Sistema_OFF");
            a=1;
        }
           
    }
}
void resolution()
{
    unsigned int s=0;
    while(!s)
    {
        data=USARTlerByte();
        if (data=='1')
        {
            PORTB=0b00111111;
            s=1;
        }
        if (data=='2')
        {
            PORTB=0b01011111;
            s=1;
        }
        if (data=='3')
        {
            PORTB=0b01101111;
            s=1;
        }
        if (data=='4')
        {
            PORTB=0b01110111;
            s=1;
        }
        if (data=='5')
        {
            PORTB=0b01111011;
            s=1;
        }
        if (data=='6')
        {
            PORTB=0b10111111;
            s=1;
        }
        if (data=='7')
        {
            PORTB=0b11011111;
            s=1;
        }
        if (data=='8')
        {
            PORTB=0b11111111;
            s=1;
        }
    }
    USARTescreverLine("Resolucao escolhida");
}

void intervalo ()
{
    unsigned int i=0, a=0;
    for(i=0; i<500; i++)
    {
        a++;
    }

}

void USARTInit()
{
//Baud Rate = 9600 Bits por Second
//Gerador de taxa de transmissão SPBRG
SPBRG=25;

//TXSTA REG
TXEN=1;
BRGH=1;

//RCSTA
SPEN=1;
CREN=1; //Habilita Receiver (RX)

//BAUDCON
BRG16=1;

}

void USARTescreverByte(char ch)
{
//Espera até receber alguma coisa
while(!TXIF);

//Lê caracter
TXREG=ch;
}

void USARTescreverString(const char *str)
{
while((*str)!='\0')
{
//Espera até receber alguma coisa
while(!TXIF);

//Lê caracter
TXREG=(*str);

//incrementa para ler o proximo
str++;
}
}



void USARTescreverLine(const char *ln)
{
USARTescreverString(ln);
USARTescreverString("\r\n");
}

void USARTescreverInt(int val,unsigned char field_length)
{
if(val<0)
{
USARTescreverByte('-'); //Write '-' sign for negative numbers.
val=(val*(-1)); //Make it positive.
}

//Convert Number To String and pump over Tx Channel.
char str[5]={'0','0','0','0'};
int i=4,j=0;
while(val)
{
str[i]=val%10;
val=val/10;
i--;
}
if(field_length>5)
while(str[j]==0) j++;
else
j=5-field_length;

for(i=j;i<5;i++)
{
USARTescreverByte('0'+str[i]);
}
}


unsigned char USARTlerByte()
{
while(!RCIF); //Wait for a byte

return RCREG;
}



Uma melhor modificacao de portas ao nivel do BIT, eh fazer da seguinte forma ::

RA0=0  ->    LATA &= 0b11111110
RA0=1  ->    LATA |= 0b00000001

ou se se quiser insistir em usar RA0=x, entao usar LATAbits.LATA0=x   (confirmar no ficheiro de Inlcude como estao as definicoes...)

Ha outras maneiras de o fazer, claro.

Título: Re: PIC_VGA
Enviado por: beirao em 21 de Outubro de 2014, 23:55
As vezes a malta usa o PORTAbits.RA0 mas não é nada aconselhável; o registo PORTx é para ler o estado, não para escrever. A questão é que se mexermos no registo PORTx em vez do LATx tipicamente o estado altera, mas nalguns uC dá barraca. Fica a nota!
Título: Re: PIC_VGA
Enviado por: nunosilvarocha em 22 de Outubro de 2014, 17:22
Problema resolvido.
Código: [Seleccione]
LATx=1;
LATx=0;

Obrigado a todos.