Mostrar mensagens com a etiqueta PIC - MCU. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta PIC - MCU. Mostrar todas as mensagens

Este foi a engenhoca da semana, embora pouco mais de meio dia tenha demorado a montar.
Tudo, à excepção do balde do lixo, foi feito com material de que dispunha à mão de antigos projectos.
No segundo video é possível ver em pormenor e mais detalhe como tudo funciona.
Basicamente pode ser dividido em 3 partes: o sensor ultrasónico de distância, o servo (15kg.cm) e por fim um pequeno MCU (PIC12F510).
Quanto ao processo de funcionamento é super básico. A cada 50mS é feita uma leitura do sensor e se houver algo a menos de 20cm de distância, é iniciado o processo de levantar a tampa. Passados 10 segundos a tampa fecha e tudo volta ao inicio.
Obviamente a explicação para os 50mS é para que possa ter a leitura máxima (maior frequência de chamada) desse sensor... quem quiser mais informações, pode visitar AQUI.





Meio engasgado, mas já foi bastante tarde e o meu raciocínio já não estava pelo melhor...

Não vou colocar aqui a biblioteca porque não faria sentido, mas poderei facultar a quem pedir via e-mail, para um melhor controlo.
Fica só um exemplo do main() que corresponde ao que está a ser feito no video.
#include <xc.h>
#include "Daviduino.h"
#include "LCD.h"

void main()
{
    char texto[8]={'C','o','n','t','a','g','e','m'};
    char i;
    unsigned int teste;

    initOSCILLATOR();
    initPORT();

    delayms(1000);

    lcd_init();

    while(1)
    {

    lcd_pos(1,5);

    for(i=0;i<8;i++)
    {
        lcd_dat(texto[i]);
    }

    lcd_pos(2,1);
    lcd_dat(62);        //>

        for (teste=0 ; teste<=65534 ; teste++)
        {
            lcd_pos(2,5);
            lcd_write_num(teste);

            delayms(250);
        }

        lcd_cmd(0x01);       //clear LCD
        __delay_ms(2);
    }

} 

Quem nunca sentiu a necessidade de transportar um circuito de um lugar para outro e quando chega ao destino, parece que nada funciona?
Farto disso, decidi construir a plataforma em baixo.
É uma espécie de 2 em 1. Tem uma placa de MDF para dar suporte, um breadboard e um módulo com um micro controlador, que está sempre pronto para testes.
As ligações são feitas com cabos semelhantes a ESTES que custam cerca de 1.5€ no ebay, 40 cabos.
O circuito e a breadboard ocupam sensivelmente metade da placa, sendo por isso a outra metade usada para colocar módulos em testes, etc, e havendo a hipótese de poder ser colado para transporte.
De momento tenho estado a construir um código com várias funções (há medida que vou necessitando delas) e assim fazendo desta placa de testes algo o mais genérico possível, para testes rápidos e/ou que necessitem de ser transportados.

Este circuito saiu do baú de recordações.
Foi o meu primeiro circuito com placa de circuito impresso e com um MCU.
É um termómetro que mostra um digito de cada vez e liga o LED correspondente à sua posição. A cada 2min faz piscar todos os LED's e mostra a temperatura máxima e a mínima desde que se ligou.
Já nem me lembrava disto...
Usa um LM35 e mede de 0 a 55ºC, com uma referência máxima na ADC, o que lhe confere até bastante precisão... precisão que depois não é dada pelo display :D.

Em baixo deixo o código já organizado para fazer e chamar um caractere especial (como um smile).
Estes displays dispõem de uns endereços na sua memória para alojar caracteres especiais. O problema aqui é que esses endereços estão numa memória RAM e quando há uma falha de energia, têm de ser "feitos" novamente.
Os caracteres podem ser feitos com base numa matriz de 5x8 pontos (sendo que a ultima linha deve ser deixada em branco). No caso do código que aqui apresento essa matriz é definida como elementos do vector "caracter[]". A função "chamar_especial()" apenas acessa o endereço onde foi previamente escrito o caracter. Aqui de futuro, não agora, ainda devo fazer alterações de modo a que consiga mudar facilmente o endereço do novo caracter especial.

Rotina para fazer e chamar ao display o caracter especial:
void especial()
{
    char endereco;
    char caracter[8]={0b00000,      //Matriz 5x8
                                     0b01010,
                                     0b01010,
                                     0b00000,
                                     0b10001,
                                     0b01110,
                                     0b00000,
                                     0b00000};


    PORTB = 0b11000000;         //DDRAM
    __delay_us(50);
    PORTBbits.RB7=0;
    __delay_us(50);
    PORTB = 0b11000000;
    __delay_us(50);
    PORTBbits.RB7=0;
    __delay_us(50);

    for(endereco=0;endereco<8;endereco++)
    {
        PORTB = 0b10001000;
        __delay_us(50);
        PORTBbits.RB7=0;
        __delay_us(50);
        PORTB = ((endereco<<1) & 0b1110) + 0b10000000;
        __delay_us(50);
        PORTBbits.RB7=0;
        __delay_us(50);

        PORTB = ((caracter[endereco]>>3) & 0b10) + 0b11000000;
        __delay_us(50);
        PORTBbits.RB7=0;
        __delay_us(50);
        PORTB = ((caracter[endereco]<<1) & 0b11110) + 0b11000000;
        __delay_us(50);
        PORTBbits.RB7=0;
        __delay_us(50);
    }

    chamar_especial();
}

Rotina para chamar ao display o caracter especial do endereço em que foi gravado:
void chamar_especial()
{
    PORTB = 0b11000000;     //DDRAM do crac especial
    __delay_us(50);
    PORTBbits.RB7=0;
    __delay_us(50);
    PORTB = 0b11000000;
    __delay_us(50);
    PORTBbits.RB7=0;
    __delay_us(100);
}

Como disse no artigo anterior, a solução acabaria por fazer a mina própria biblioteca, assim este artigo é sobre o estado em que se encontra a mesma.
Consegui fazer com que os primeiros caracteres aparecessem no ecrã.
Daí dei um jeito no código "em bruto", para ficar mais flexível e fácil de usar no futuro.
Basicamente o que estou a fazer é a inicialização do LCD, a colocação do cursor num endereço e a escrita de caracteres com incremento automático do endereço do cursor.
Código para utilização do LCD com comunicação a 4 bits.

Rotina de configuração do LCD:
void config_lcd()
{
    // E   RS  RW  D7  D6  D5  D4
    // RB7 RB6 RB5 RB4 RB3 RB2 RB1

    char i;
    char config[7]={
                    0b10000100, //1ª config - 4bits
                    0b10000100, //4bits; 2linhas; 5x8pontos + E
                    0b10010000, //4bits; 2linhas; 5x8pontos + E
                    0b10000000, //E + display ON; mostra cursor; cursor pisca
                    0b10011110, //E + display ON; mostra cursor; cursor pisca
                    0b10000000, //E + cursor incrementa; sem display shift
                    0b10001100, //E + cursor incrementa; sem display shift
                  };

    for(i=0;i<7;i++)
    {
        PORTB = config[i];
        __delay_us(50);
        PORTBbits.RB7=0;
        __delay_us(50);
    }  
}

Rotina de posição do cursor:
void cursor_lcd_pos(char posicao)
{
    /*
     * 00h -> linha 1
     * 40h -> linha 2
     */

    PORTB = ((posicao>>3) & 0b1110) + 0b10010000;
    __delay_us(50);
    PORTBbits.RB7=0;
    __delay_us(50);
    PORTB = ((posicao<<1) & 0b11110) + 0b10000000;
    __delay_us(50);
    PORTBbits.RB7=0;
}

Rotina de escrita no display:
void escrever_lcd(char texto[])
{
    char length, i;

    length=strlen(texto);

    for(i=0;i<length;i++)
    {
        PORTB = ((texto[i]>>3) & 0b11110) + 0b11000000;
        __delay_us(50);
        PORTBbits.RB7=0;
        __delay_us(50);
        PORTB = ((texto[i]<<1) & 0b11110) + 0b11000000;
        __delay_us(50);
        PORTBbits.RB7=0;
        __delay_us(50);
    }
}

Exemplo de código main();
void main()
{
    PIC_init();

    config_lcd();
    cursor_lcd_pos(3);
    escrever_lcd("Ola mundo ");

}

Tenho andado a estudar um pouco, um pequeno MCU.
Trata-se do PIC12F1822.... é um monstrinho em 8 pinos.
Além do "comum", este micro tem USART, oscilador interno de 32MHz, DAC, PWM, etc...
Estava a ler e a implementar em simulação uma pequena experiência com uma ADC (10 bits) e quando estava a fazer a configuração, verifiquei que a DAC poderia servir de referência para a ADC.
Mas... espera lá!
A DAC a servir de referência para a ADC?
5/32=156mV
Ou seja, cada salto da DAC é de 156mV.
Se usar isso como referência para a ADC de 10bits, então:
156mV/1024=153uV
Com rigor ou não.... poderei ter leituras na ADC na ordem dos 153uV!
E é assim que se usa uma ADC para ler ruído eheheh.
Fazendo mais uns calculos,
32*1024=32 768
Resumindo, ganha-se uma ADC de 32 768bits a partir de uma ADC de 10bits e uma DAC de 5bits.
Alterando ainda a referencia da DAC para uma interna de 1.024V,
1.024V/32=32mV
Ou seja, cada salto fica com 32mV e sendo dado como referência ao ADC, então,
0.032/1024=0.00003125=31.25uV
Ahahahahah... na teoria não seria sequer necessários ampops... isto conseguiria medir valores de tensão tão baixos!

Quem já ligou uma coisa DESTAS, sabe que por vezes o windows confunde com o Serial Ball Point Mouse.
Tenho andado a tentar ligar o Datalogger ao MATLAB, mas cada vez que começo a receber dados, o windows reconhece o conversor como um rato. Tal e qual a imagem em cima.
Já tentei várias formas, incluindo o "SerialBallPointMouseDisabler", mas ele nunca funciona por muito tempo e passado um pouco (ou desligar e voltar a ligar o conversor), o windows volta a activar o "rato".
Pelo que tenho lido, isto também acontece muito com GPS.
Se alguém souber como desactivar de uma vez o Serial Ball Point Mouse, comente aqui.
Agora para conseguir, tenho de ligar o conversor ao datalogger, ir aos dispositivos, desinstalar o rato, tirar o conversor do circuito, correr o "SerialBallPointMouseDisabler", voltar a ligar o conversor ao circuito e funciona certo.
Em baixo, primeiras experiências a receber dados pelo MATLAB, usando uma porta serial.

Cá está a PCB já feita e com os componentes soldados.
Veio sem dúvida resolver alguns problemas de ligações na breadboard, podendo esta placa ser colocada na vertical junto de uma breadboard para se fazerem as outras ligações.
O autocolante em cima com a identificação dos pinos vem ajudar a dar mais rapidez na colocação dos fios.
PS: esta placa já foi implementada e o MCU já está a correr com um algoritmo para corrigir o movimento de um pequeno robô. Quando tiver algum tempo já coloco fotos.
PS: com os devidos e merecidos agradecimentos ao Diogo Correia, por tão prontamente se ter disponibilizado a corroer a PCB, para a cadeira de Robótica. 

A necessidade de urgente de ter uma board do tipo "arduino", mas com a qualidade de um PIC18F, fez com que resultasse no desenho em baixo. Preciso de fazer um controlador para um robô e preciso fazer as ligações o mais rápido possível.
A placa é muito simples e destina-se a todos os PIC compatíveis, com os pinos de alimentação, pelo menos, com o PIC18F4431 (como é o caso do PIC16F887).
O circuito em baixo foi feito muito à pressa, pelo que não tem o melhor dos aspectos....

Este é um pequeno programa para escrever e ler endereços da EEPROM de um PIC12F675.
O compilador é o MPLAB XC8, que já possui umas macros para fazer isto... mas optei por ser eu mesmo a fazê-las.
A descrição é simples, em escrita ele vai tirando 255 ao valor a aguardar e vai incrementando o número do endereço. Quando termina guarda o número do último endereço no endereço zero.
Aquando da leitura, é lido o endereço zero, que me diz qual é o ultimo endereço a ler e após isso são somados todos os valores (guardados em cada endereço) até lá.
#include <xc.h>

__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & CP_OFF & CPD_OFF);


#define _XTAL_FREQ 4000000


EEPROM_escrita(unsigned int num)
{
signed char i;

i=1;
while(num>255)
{
num=num-255;

//escrita na EEPROM
PIR1bits.EEIF=0;
EEADR=i;
EEDATA=255;
EECON1bits.WREN=1;
EECON2=0x55;
EECON2=0xAA;
EECON1bits.WR=1; //clear por hardware
while(!PIR1bits.EEIF);

i++;
}

//escrita na EEPROM
PIR1bits.EEIF=0;
EEADR=i;
EEDATA=num;
EECON1bits.WREN=1;
EECON2=0x55;
EECON2=0xAA;
EECON1bits.WR=1; //clear por hardware
while(!PIR1bits.EEIF);

//escrita na EEPROM
PIR1bits.EEIF=0;
EEADR=0;
EEDATA=i;
EECON1bits.WREN=1;
EECON2=0x55;
EECON2=0xAA;
EECON1bits.WR=1; //clear por hardware
while(!PIR1bits.EEIF);
}

unsigned int EEPROM_leitura(void)
{
unsigned char i;
unsigned int num;

num=0;

EEADR=0;
EECON1bits.RD=1;
i=EEDATA; //numero de endereços

while(i>0)
{
EEADR=i;
EECON1bits.RD=1;
num+=EEDATA;
i --;
}

return num;
}

void main()
{
unsigned int tempo;

GPIO=0b000000;
CMCON=0b00000000;
TRISIO=0b00001000;

//ADC
ANSEL=0b00000000;


EEPROM_escrita(1000);

tempo=EEPROM_leitura();

__delay_ms(100);


while(1);

}
Diagrama de blocos do PIC12F675.

No outro dia pediram-me para dar uma olhadela num comando de garagem. Ele não funcionava, mas rapidamente se percebeu que era apenas pilhas gastas.
No entanto, quando abri o comando fiquei espantado por não ter um CI dedicado (como é o caso dos comuns comandos de garagem), mas sim um MCU.
É um PIC12F629 e o circuito, embora este tenha apenas 2 botões, deverá ser bastante semelhante ao que está em baixo.
Infelizmente o camando foi logo entregue ao dono e não pude verificar muito mais.
Este não é um post de "review" mas sim de simples curiosidade :).