Ir ao conteúdo
  • Cadastre-se

Voltímetro e amperímetro Digital para fonte de bancada, com uc PIC16F677


Posts recomendados

Olá pessoal, eu estou finalizando um projeto, entre tanto, está complicado de resolver o erro acumulativo que ocorre com o sensor ASC712, fora isso o projeto está pronto, gostaria de uma ajuda para resolver esse problema, eu utilizei o compilador XC8 para o projeto. Segue o código do projeto e o vídeo do mesmo.

 

adicionado 2 minutos depois

//INSTRUMENTO DE BANCADA BY (TERRIBLE_LAB)
//AUTOR:LUCAS PEREIRA DE SOUZA PINTO
//DATA:21/05/2015

//INCLUDES
#include <stdlib.h>
#include <stdio.h>
#include <pic16f677.h>
#include <xc.h>
//********************************************************************************************************************************************************
//CONFIG
#pragma config FOSC = HS            // Oscillator Selection bits (INTOSC oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF           // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF          // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON           // RESET ON
#pragma config BOREN = OFF          // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF             // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF            // Data Code Protection bit (Data memory code protection is disabled)
#pragma config IESO = OFF           // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF          // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
//********************************************************************************************************************************************************
//DEFINES
#define _XTAL_FREQ 20000000         // cristal de 20 Mhz
#define delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

//Definição de linhas de endereço do display*****************
#define T1           PORTCbits.RC4  //NPN1
#define T2           PORTCbits.RC5  //NPN2
#define T3           PORTCbits.RC6  //NPN3
#define T4           PORTCbits.RC7  //NPN4
//Definição linhas de dados do display **********************
#define A            PORTCbits.RC0  //A
#define B            PORTCbits.RC1  //B
#define C            PORTCbits.RC2  //C
#define D            PORTCbits.RC3  //D
//************************************************************
#define LAMP         PORTAbits.RA2  //PISCA PISCA
#define B_T          PORTBbits.RB4  //tensão
#define B_A          PORTBbits.RB5  //AMPER
#define tensão       PORTBbits.RB6  //tensão/LED
#define CORRENTE     PORTBbits.RB7  //CORRENTE/LED
//********************************************************************************************************************************************************


//****************************************************************************
//PROTOTIPO DE FUNÇÃO
void pic_start();
void bank(char num);
void aciona_display(int numero, int casa);
void escrever_variavel(int valor);
void escrever_unidade(int unidade);
void escrever_dezena(int dezena);
void escrever_centena(int centena);
void escrever_milhar(int milhar);
int read_AD();
//****************************************************************************
//PROGRAMA PRINCIPAL
int main()
{
    pic_start();        //START PIC
    float var = 0;      //VARIAVEl GLOBAL
    
       while(1)
    {
    //START
    //ROTINA MODO NORMAL
    if(B_T == 0 && B_A == 0 || B_T == 1 && B_A == 1)
    {
    ADCON0bits.ADON = 0;
    tensão = 0;
    CORRENTE = 0;
    LAMP = !LAMP,delay_ms(200);
    A=1,B=1,C=1,D=1,T1=1,T2=1,T3=1,T4=1;
    }
    //ROTINA DO VOLTIMETRO
    else if(B_T == 1 && B_A == 0)
    {
    ADCON0bits.CHS0 = 0;
    ADCON0bits.CHS1 = 0;
    ADCON0bits.CHS2 = 0;
    ADCON0bits.CHS3 = 0;
    tensão = 1;
    CORRENTE = 0;
    LAMP = 0;
    ADCON0bits.ADON = 1;
    var = read_AD();
    var = read_AD()*25.00;      //Pega sinal do AD e multiplica pela tensão que você ira medir
    var = var/1024;             //Divide  por 1024 para achar volts/bits
    var = var * 100;            //multiplica por 100 para aparecer no display de 7 segmentos, ja que a variavel esta framentada   
    escrever_variavel(var);     //Escreve variavel no display 7 Segmentos
    var = 0x00;                 //Limpa variavel
    }
    //ROTINA DO AMPERIMETRO
    else if(B_T == 0 && B_A == 1)
    {
    ADCON0bits.CHS0 = 1;
    ADCON0bits.CHS1 = 0;
    ADCON0bits.CHS2 = 0;
    ADCON0bits.CHS3 = 0;   
    tensão = 0;
    CORRENTE = 1;
    LAMP = 0;
    ADCON0bits.ADON = 1;
    var = read_AD();        //Faz Leitura do converso AD e iguala a variavel a ser trabalhada    
    var = var -512;         //Faz subttação de 512 do sesor, devido ele trabalhar em -5 e +5 ou seja 512 = 2.5 V = 0A         
    var = var*0.004882812;  //Pega a variavel e multiplica pela divisão de 5/1024 para ad de 10 bits
    var = var/0.185;        //Pega a resolção do sensor divide pela variavel
    var = var*1000;         //multiplica por 1000 para aparecer no display de 7 segmentos, ja que a variavel esta framentada   
    escrever_variavel(var); //Escreve variavel no display 7 Segmentos*/
    var = 0x00;     
    }
   
    //END
    }
}
//*****************************************************************************
//TRATAMENTO DE PROTOTIPO
void pic_start()
{
    bank(1);                    //SELECT BANK ONE
    TRISC = 0b00000000;         //ALL PORTC WITH OUT
    TRISA = 0b00111011;         //VOLT,AMP,RESET,RA4,RA5 = IN , LAMP = OUT
    TRISB = 0b00110000;         //ONLY RB4 e RB5 IN
    bank(0);                    //SELECT BANK ZERO
    CORRENTE = 0;
    tensão = 0;

    ADCON0bits.ADFM = 1; //Conversor justificado para direita
    ADCON0bits.VCFG = 0; //Tensão do microcontrolador

    //Conversor AD SELEÇÃO DO CANAL AN0 PARA TENSÃO PARA INICIO
    ADCON0bits.CHS0 = 0;
    ADCON0bits.CHS1 = 0;
    ADCON0bits.CHS2 = 0;
    ADCON0bits.CHS3 = 0;

    //Ligando conversor AD
    ADCON0bits.ADON = 1; //Ligado

    //Configurando fonte de clock para AD
    ADCON1bits.ADCS0 = 1;
    ADCON1bits.ADCS1 = 0;
    ADCON1bits.ADCS2 = 0;

    //Configurando se o pino é analógico ou digiral
    ANSEL = 0b00000011;
    ANSELH = 0b00000000;
}
void bank(char num)
{
    //Banco 0
    if(num == 0)
    {
        RP0 = 0, RP1 = 0;
    }
    //Banco 1
    else if(num == 1)
    {
        RP0 = 0, RP1 = 1;
    }
    //Banco 2
    else if(num == 2)
    {
        RP0 = 1, RP1 = 0;
    }
    //Banco 3
    else if(num == 3)
    {
        RP0 = 1, RP1 = 1;
    }
}
void aciona_display(int numero, int casa)
{
    if(casa == 1)
    {
        switch(numero)
        {
            case 0: A=0,B=0,C=0,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 1: A=1,B=0,C=0,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 2: A=0,B=1,C=0,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 3: A=1,B=1,C=0,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 4: A=0,B=0,C=1,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 5: A=1,B=0,C=1,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 6: A=0,B=1,C=1,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 7: A=1,B=1,C=1,D=0,T1=1,T2=0,T3=0,T4=0;
            break;
            case 8: A=0,B=0,C=0,D=1,T1=1,T2=0,T3=0,T4=0;
            break;
            case 9: A=1,B=0,C=0,D=1,T1=1,T2=0,T3=0,T4=0;
            break;
        }
    }
    if(casa == 2)
    {
        switch(numero)
        {
            case 0: A=0,B=0,C=0,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 1: A=1,B=0,C=0,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 2: A=0,B=1,C=0,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 3: A=1,B=1,C=0,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 4: A=0,B=0,C=1,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 5: A=1,B=0,C=1,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 6: A=0,B=1,C=1,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 7: A=1,B=1,C=1,D=0,T1=0,T2=1,T3=0,T4=0;
            break;
            case 8: A=0,B=0,C=0,D=1,T1=0,T2=1,T3=0,T4=0;
            break;
            case 9: A=1,B=0,C=0,D=1,T1=0,T2=1,T3=0,T4=0;
            break;
        }
    }
    if(casa == 3)
    {
        switch(numero)
        {
            case 0: A=0,B=0,C=0,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 1: A=1,B=0,C=0,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 2: A=0,B=1,C=0,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 3: A=1,B=1,C=0,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 4: A=0,B=0,C=1,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 5: A=1,B=0,C=1,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 6: A=0,B=1,C=1,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 7: A=1,B=1,C=1,D=0,T1=0,T2=0,T3=1,T4=0;
            break;
            case 8: A=0,B=0,C=0,D=1,T1=0,T2=0,T3=1,T4=0;
            break;
            case 9: A=1,B=0,C=0,D=1,T1=0,T2=0,T3=1,T4=0;
            break;
        }
    }
        if(casa == 4)
     {
        switch(numero)
        {
            case 0: A=0,B=0,C=0,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 1: A=1,B=0,C=0,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 2: A=0,B=1,C=0,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 3: A=1,B=1,C=0,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 4: A=0,B=0,C=1,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 5: A=1,B=0,C=1,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 6: A=0,B=1,C=1,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 7: A=1,B=1,C=1,D=0,T1=0,T2=0,T3=0,T4=1;
            break;
            case 8: A=0,B=0,C=0,D=1,T1=0,T2=0,T3=0,T4=1;
            break;
            case 9: A=1,B=0,C=0,D=1,T1=0,T2=0,T3=0,T4=1;
            break;
        }
    }//desabilita todos os 4511
}
void escrever_variavel(int valor)
{
    escrever_unidade(valor);
    escrever_dezena(valor);
    escrever_centena(valor);
    escrever_milhar(valor);
    if(valor >= 9999)
    {
        A=1,B=1,C=1,D=1,T1=1,T2=1,T3=1,T4=1;
    }
    else
    {
        valor = valor;
    }
}
void escrever_unidade(int unidade)
{
    unidade = ((unidade/1000)%10);//Primeiro digito
    aciona_display(unidade,4),delay_ms(125);
}
void escrever_dezena(int dezena)
{
 dezena = ((dezena/100)%10);//Segundo digito
 aciona_display(dezena,3),delay_ms(125);
}
void escrever_centena(int centena)
{
    centena = ((centena/10)%10);//Terceiro digito
    aciona_display(centena,2),delay_ms(125);
}
void escrever_milhar(int milhar)
{
    milhar = (milhar%10);//Quarto digito
    aciona_display(milhar,1),delay_ms(125);
}
int read_AD()
{
    int result_AD;                              //Declaração variavel local
    ADCON0bits.GO = 1;                          //Inicia conversão
    while(ADCON0bits.GO);                       //aguarda conversão
    result_AD = (((int)ADRESH)<<8)|(ADRESL);    //Obtem o valor da conversão
    return result_AD;                           //Retorna para result_AD
}

adicionado 19 minutos depois

 

Link para o comentário
Compartilhar em outros sites

@Lucas Pereira de Souza ,

 

Bom, a nível de aprendizado, é interessante.... mas a nível prático, hoje se compra isso pronto a um preço bem interessante, mesmo aqui no Brasil.

 

Dá uma olhada .... :

 

http://produto.mercadolivre.com.br/MLB-798152421-voltimetro-e-amperimetro-digital-led-dc-0-100v-10a-_JM

 

 

adicionado 4 minutos depois
2 horas atrás, ViniciusKruz disse:

Isso tá mais pra erro de conversão do AD, embora você tenha dito que testou sem o AD e o erro persistiu. Verifica também a separação das unidades, dezenas, centenas e milhar pode haver erro nessa parte também. Se tudo isso estiver correto, desconfie do simulador.

 

 

 

Olha, eu já usei o ISIS para simular montagens com o ACS712, e nunca tive problemas, até um wattímetro que montei com medição de fator de potência bateu com as simulações, usando um ACS712 e um transformador para sample da tensão ... posso garantir que esse erro não é do simulador.

 

Desconfie do compilador ou do código utilizado, ou da eletrônica !

 

Paulo

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

6 horas atrás, aphawk disse:

@Lucas Pereira de Souza ,

 

Bom, a nível de aprendizado, é interessante.... mas a nível prático, hoje se compra isso pronto a um preço bem interessante, mesmo aqui no Brasil.

 

Dá uma olhada .... :

 

http://produto.mercadolivre.com.br/MLB-798152421-voltimetro-e-amperimetro-digital-led-dc-0-100v-10a-_JM

 

 

adicionado 4 minutos depois

 

Olha, eu já usei o ISIS para simular montagens com o ACS712, e nunca tive problemas, até um wattímetro que montei com medição de fator de potência bateu com as simulações, usando um ACS712 e um transformador para sample da tensão ... posso garantir que esse erro não é do simulador.

 

Desconfie do compilador ou do código utilizado, ou da eletrônica !

 

Paulo

Eu concordo com você Paulo, entre tanto, a graça é você fazer o próprio instrumento. Estou desconfiado da eletrônica, acredito que o AD e o compilador esta normal, o voltímetro não tem esse problema, apenas com o ACS712 provavelmente pode ser ele, será que essa montagem que eu fiz no Proteus esta correta em relação a ele ? vou dar uma olhada na folha de dados dele.

Link para o comentário
Compartilhar em outros sites

@Lucas Pereira de Souza ,

 

Para mim, o seu tratamento matemático está meio confuso, mas o esquema me parece correto !

 

O sensor para correntes de 5A possui tensão de saída de 2,5 Volts para corrente  igual a 0.

A saída varia 185 mV/A .

Se a corrente chegar a 5A no sentido positivo, a tensão na saída será de 2.5 + 0.185 x 5 = 3.425 Volts.

Eu calcularia da seguinte maneira :

 

- leitura do conversor A/D com Vref=5V dá o valor val_medido

- se val_medido > 511 então corrente é no sentido positivo; se for < 512 então é negativa.

- supondo que a corrente é positiva :

- X = val_medido x 1023/5 ; teremos a tensão em volts

- X = X - 2.5  ;  teremos o acréscimo causado pela corrente   $$$$$$$$$$$$$

- X = X/0.185 ;  agora X é o valor em Amperes

 

Fácil .... se a leitura do conversor for < 511 então basta fazer X = 2.5 - X na linha marcada com os $$$$$$$$$$$$$  !

 

Veja se modificando seu programa resolve....

 

Paulo

Link para o comentário
Compartilhar em outros sites

Em 05/04/2017 às 22:44, aphawk disse:

@Lucas Pereira de Souza ,

 

Para mim, o seu tratamento matemático está meio confuso, mas o esquema me parece correto !

 

O sensor para correntes de 5A possui tensão de saída de 2,5 Volts para corrente  igual a 0.

A saída varia 185 mV/A .

Se a corrente chegar a 5A no sentido positivo, a tensão na saída será de 2.5 + 0.185 x 5 = 3.425 Volts.

Eu calcularia da seguinte maneira :

 

- leitura do conversor A/D com Vref=5V dá o valor val_medido

- se val_medido > 511 então corrente é no sentido positivo; se for < 512 então é negativa.

- supondo que a corrente é positiva :

- X = val_medido x 1023/5 ; teremos a tensão em volts

- X = X - 2.5  ;  teremos o acréscimo causado pela corrente   $$$$$$$$$$$$$

- X = X/0.185 ;  agora X é o valor em Amperes

 

Fácil .... se a leitura do conversor for < 511 então basta fazer X = 2.5 - X na linha marcada com os $$$$$$$$$$$$$  !

 

Veja se modificando seu programa resolve....

 

Paulo

Amigo, eu fiz o procedimento que você falou o erro persistiu, não faço ideia o que seja o erro, estou montando o projeto físico para ver o que descubro.

Link para o comentário
Compartilhar em outros sites

@Lucas Pereira de Souza ,

 

Não é um erro acumulativo. é um erro nos cálculos. Repare que se você começar com 0.300, vai ter o valor errado logo de cara, de 316 .... pode apostar que é algum erro de tipo de variável, ou de coisa desse tipo no compilador.

 

Se fosse erro acumulativo, você mediria 316 na primeira leitura, e na segunda mediria um valor ainda maior, e na terceira maior ainda.....  se você sempre tem 316, é erro nos cálculos, talvez tipo de variável utilizada.

 

Se você disponibilizar o seu arquivo do Proteus, eu faço o programa com o Bascom pra testar.

 

Paulo

Link para o comentário
Compartilhar em outros sites

Em 11/04/2017 às 15:10, aphawk disse:

@Lucas Pereira de Souza ,

 

Não é um erro acumulativo. é um erro nos cálculos. Repare que se você começar com 0.300, vai ter o valor errado logo de cara, de 316 .... pode apostar que é algum erro de tipo de variável, ou de coisa desse tipo no compilador.

 

Se fosse erro acumulativo, você mediria 316 na primeira leitura, e na segunda mediria um valor ainda maior, e na terceira maior ainda.....  se você sempre tem 316, é erro nos cálculos, talvez tipo de variável utilizada.

 

Se você disponibilizar o seu arquivo do Proteus, eu faço o programa com o Bascom pra testar.

 

Paulo

Amigo, segue em anexo os arquivos do projeto.

Voltimetro e Amperimetro digital.rar

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!