Este chip se baseia na medida de corrente elétrica através do campo eletromagnético gerado em torno da área de condução do sensor, é possível com auxilio de um osciloscópio ver nitidamente a forma de onda da corrente elétrica produzida por uma fonte AC em uma carga.No nosso exemplo vou usar o chip para implementar um amperímetro que consegue medir corrente de até 20A, lembrando que é possível dependendo do modelo do chip medir até 30A conforme mostrado na figura abaixo(retirado do datasheet do fabricante):
Como ele mede corrente AC então no momento em que não há carga o sinal de saída é a metade da tensão de alimentação do circuito ou seja para 5V você terá 2,5V, como consequência o sinal varia de 2,5V até 5V nos semiciclos positivo e de 2,5 até 0V para os semiciclo negativo, logo para medir a tensão continua o sinal de saída irá depender do sentido da corrente no circuito da carga, para resolver esse problema podemos calcular a variação de unidades de medidas, assim independente se é positivo ou negativo a variação será a mesma,mas como a tensão de saída depende da alimentação então no algoritmo de leitura o circuito deve fazer um referenciamento do valor de saída do sensor quando não houver sinal(no meu caso coloquei pra fazer isso assim que ligar o circuito e então ele começa a pegar as amostras).
Para conectar o chip ACS712 com o pic é bem simples e usa poucos componentes externos veja na imagem abaixo como ficaria o esquema elétrico da parte de interface:
Veja que a saída serial RS-232 deve ser ligada a um chip Max232 ou similar para que possa ser ligado ao PC, o capacitor de 10nF é para estabilizar a tensão lida e evitar pequenas flutuações.
Por fim vou mostrar como é plotado as mensagens num terminal serial do PC, veja a próxima figura, e logo em seguida é apresentado o código fonte.Este C.I. pode ser adquirido também na forma de placas montadas (no mercado livre tem aos montes).
O código fonte:
/* * Amperímetro - via serial * * Compilador : MPlabXC8 * Microcontrolador: 12F675 * Autor: aguivone * Versão: 1 * Data : 05/11/2015 * Descrição : mede corrente usando o CI ACS712 (usa porta serial emulada) */ #include <stdio.h> #include <stdlib.h> #include <string.h> //para trabalhar com string #include <xc.h> #define _XTAL_FREQ 20000000 /////////////////////////////////////////////////////////configurações////////////////////////////////////////////////// // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High speed crystal/resonator on GP4/OSC2/CLKOUT and GP5/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 = OFF // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD) #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) ///parametros da porta serial emulada//////////////////////////////////////////////////////////////// #define TIME_BAUD 97//9600 bps - 20MHZ #define BAUD_RX 95//9600 bps - 20MHZ #define TX GP2//configura o pino que será TX - não será usado aqui #define RX GP1//configura o pino que será RX int ler_adc_un() { int ulcorrente; PIR1bits.ADIF = 0;//limpa flag ADCON0bits.GO = 1; //inicia conversão while (PIR1bits.ADIF == 0); //espera finalizar leitura ulcorrente = (ADRESH << 8) | ADRESL; return(ulcorrente); } /////////////////////Funçoes utilizadas pela serial///////////////////////////////////////////////////////////// void escreve_char(char dados) { int contagem = 0; TX = 0; while (contagem < 8) //envia dados + stop bit { __delay_us(TIME_BAUD); if ((dados & 0X01) == 0X01) //testa bit menos significativo (LSB) { TX = 1; } else { TX = 0; } dados = dados >> 1; //rotaciona bit contagem++; } __delay_us(TIME_BAUD); //tempo do ultimo bit TX = 1; //volta pra nivel alto (fim de transmissão de caracter) __delay_us(TIME_BAUD); //stop bit } ///é interessante observar que está rotina irá trabalhar melhor se for ///usado na rotina de interrupção de estado no pino, aqui vou deixar na rotina principal por // ser um exemplo simples char ler() { int contagem = 0; char RX_dados = 0X00; if (RX == 0)//tem dados pra ler { RX_dados = 0X00; while (contagem < 8) //recebe dados + stop bit { __delay_us(BAUD_RX); //compensa algum delay na recepção if (RX == 1) { RX_dados = (RX_dados | 0X80); //seta bit mais significativo (MSB) } RX_dados = RX_dados >> 1; contagem++; } contagem = 0; while ((RX == 0) && (contagem < 4)) { contagem++; //time out para não travar,tempo de 4 bits __delay_us(TIME_BAUD); } } return (RX_dados); } void escreve_frase(char *frase) { int tam_frase = strlen(frase); int contagem = 0; while (contagem < tam_frase) { escreve_char(frase[contagem]); contagem++; } } void long_to_char(long ulQuant) { char cTexto[5]={'0','0','0','0','0'}; while(ulQuant>=10000) { ulQuant=ulQuant-10000; cTexto[4]++; } if(cTexto[4] > '0') {//se igual a zero não imprime escreve_char(cTexto[4]); } while(ulQuant>=1000) { ulQuant=ulQuant-1000; cTexto[3]++; } escreve_char(cTexto[3]); escreve_char(','); while(ulQuant>=100) { ulQuant=ulQuant-100; cTexto[2]++; } escreve_char(cTexto[2]); while(ulQuant>=10) { ulQuant=ulQuant-10; cTexto[1]++; } escreve_char(cTexto[1]); while(ulQuant>=1) { ulQuant=ulQuant-1; cTexto[0]++; } escreve_char(cTexto[0]); escreve_char('\n');//pula linha escreve_char('\r');//coloca no inicio do terminal } //////////////////////////////////////////////////////Rotina principal/////////////////////////////////////////////////////////////// void main(void) { CMCON = 7;//desabilita comparadores ANSEL = 0X31;//usa AN0 como entrada analógica e usa o clock interno do chip(2 a 6 us) WPU = 0X00;//desabilita pull ups TMR0 = 0; ADCON0 = 0X80;//justificado a esquerda , ref ligado ao vdd,usando AN0 OSCCAL = 0XFF;//configura o oscilador interno para frequência maxima(4mhz) OPTION_REG = 0X81;//pull up desabilitado/preescaler ligado ao timer0(dividido por 4) PIR1 = 0X00; //desabilita interrupções não necessária TRISIO = 0X03;//configura gp0 e gp1 como entrada INTCON = 0XC0;//desabilita interrupção do timer 0 e habilita interrupção global e de periféricos ADCON0bits.ADON = 1;//liga modulo de conversão __delay_ms(1000);//debounce e tempo para preparar hardware int referencia = 0; long aux;//auxilia nas contas que necessitem de valores maiores int corrente = 20; while(corrente>0)//somatório de 20 amostras { referencia = ler_adc_un() + referencia; __delay_ms(100); corrente--; } referencia = referencia/20;//tira uma media para servir como referencia for(;;) { __delay_ms(500); //envia valor a cada 0,5s corrente = ler_adc_un();//lê o conversor if((corrente >= referencia-1)&&(corrente <= referencia+1))//range de +ou- 1 unidades {//para filtrar erros ou pequenas variações long_to_char(0); } else { if(corrente >= referencia) {//usar a parte inferior é mais confiável aux = (corrente - referencia) * 49;//dá o valor com 3 casas decimais escreve_char('+');//corrente positiva } else { aux = (referencia - corrente) * 49;//dá o valor com 3 casas decimais escreve_char('-');//corrente positiva } if(aux>20000) { escreve_frase("Perigo! valor acima da escala \n\r"); } else { long_to_char(aux); } } }//loop infinito } //NOTAS DE PARAMETRIZAÇÃO: //*********************************************************************************************************** //oscilador interno do pic 12F675(testado fisicamente )////////////////////////////////////////////////////// // configure assim o fuse do oscilador interno => #pragma config FOSC = INTRCIO // configure assim o fuse do cristal de 4MHZ => #pragma config FOSC = XT // //#define TIME_BAUD 14//19200 bps - 4MHZ - usando cristal //#define TIME_BAUD 16//19200 bps - 4MHZ - usando oscilador interno //#define BAUD_RX 12//19200 bps - 4MHZ - osc. interno - recepção não fica confiável //#define TIME_BAUD 68//9600 bps - 4MHZ - usando oscilador interno //#define BAUD_RX 58//9600 bps - 4MHZ - cristal 4MHZ - recepção funcionou bem(houve pouquíssimo erros) - no proteus esse valor não funciona //#define BAUD_RX 60//9600 bps - 4MHZ - recepção funcionou bem(houve pouquíssimo erros) //#define TIME_BAUD 175//4800 bps - 4MHZ //#define BAUD_RX 165//4800 bps - 4MHZ - recepção funcionou muito bem(100% confiável fisicamente, mas no proteus apresenta falhas) //************************************************************************************************* // oscilador com cristal de 20MHZ (testado fisicamente funcionou ok) // configure assim o fuse do cristal => #pragma config FOSC = HS //#define TIME_BAUD 45//19200 bps - 20MHZ //#define BAUD_RX 42//19200 bps - 20MHZ //#define TIME_BAUD 97//9600 bps - 20MHZ //#define BAUD_RX 95//9600 bps - 20MHZ //#define TIME_BAUD 202//4800 bps - 20MHZ //#define BAUD_RX 198//4800 bps - 20MHZ
Olá, tem algum exemplo do uso deste mesmo sensor com o pic16f628a?
ResponderExcluir