Todas as especificações estão no manual que montei deem uma olhada neste link http://microcontroladores-c.blogspot.com.br/2015/12/medindo-tensao-ac-com-o-sensor-amf-16.html,
O microcontrolador usado é o PIC 12F675 como ele não tem serial, foi usado o artificio de emular uma serial,ele apenas envia os dados num intervalo pré definido, sendo então o sinal elétrico convertido em luz através do optoacoplador para que seja ligado diretamente a um microcontrolador secundário sem risco de queimar.
O código fonte:
/* * voltimetro via serial * * Compilador : MPlabXC8 * Microcontrolador: 12F675 * Autor: aguivone * Versão: 1 * Data : 15/09/2015 */ #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 /////para simulação do proteus //#define TIME_BAUD 202//4800 bps - 20MHZ //#define BAUD_RX 198//4800 bps - 20MHZ #define TX GP2//configura o pino que será TX #define RX GP1//configura o pino que será RX #define TAM_MAX 10//tamanho maximo do vetor de amostragem(numero de pontos) #define NUM_MED 6//numero de intens para formar a media dos picos //#define TEMPO_ENVIO 110//(aprox. 15ms)tempo para enviar os dados(em tempo de rotina)) //#define TEMPO_ENVIO 1100//(aprox. 150ms)tempo para enviar os dados(em tempo de rotina)) #define TEMPO_ENVIO 7000//(aprox. 1s)tempo para enviar os dados(em tempo de rotina)) int vetor[TAM_MAX+1]; int tensao=0; char flag_libera=0; int ler_adc_un() { int ultensao; PIR1bits.ADIF = 0;//limpa flag ADCON0bits.GO = 1; //inicia conversão while (PIR1bits.ADIF == 0); //espera finalizar leitura ultensao = (ADRESH << 8) | ADRESL; return(ultensao); } /////////////////////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(int ulQuant) { char cTexto[4]={'0','0','0','0'}; while(ulQuant>=1000) { ulQuant=ulQuant-1000; cTexto[3]++; } escreve_char(cTexto[3]); 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('-'); } void gira_vetor() { int aux=0; while(aux<TAM_MAX) { vetor[aux] = vetor[aux+1]; aux++; } } //////////////////////////////////////////////////////Rotina principal/////////////////////////////////////////////////////////////// void main(void) { CMCON = 7;//desabilita comparadores ANSEL = 0X31;//usa AN0 como entrada analogica 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 frequencia maxima(4mhz) OPTION_REG = 0X81;//pull up desabilitado/preescaler ligado ao timer0(dividido por 4) PIR1 = 0X00; //desabilita interrupções não necessaria TRISIO = 0X03;//configura gp0 e gp1 como entrada INTCON = 0XC0;//desabilita interrupção do timer 0 e habilitainterrupção global e de perifericos ADCON0bits.ADON = 1;//liga modulo de conversão __delay_ms(300);//debounce e tempo para preparar hardware //logo a frequencia de interrupção é 250khz char tempo_media = 0; int tempo_de_envio = 0; int flag=0; for(;;) { // __delay_us(1); //para garantir uma leitura estavel vetor[TAM_MAX] = ler_adc_un(); if((flag_libera == 1)) { if(vetor[TAM_MAX]<vetor[0])//localizou o pico de tensão { int valor =0; int aux=0; while(valor<TAM_MAX) {//procura o maior valor if(aux < vetor[valor]) { aux = vetor[valor]; } valor++; } tensao = aux + tensao;//sempre pega a média da leitura de pico atual pela anterior if(tempo_media >= NUM_MED) { tensao =tensao/(NUM_MED + 2);//sempre pega a média da leitura de pico atual pela anterior if(tempo_de_envio >= TEMPO_ENVIO) { long_to_char(tensao); tempo_de_envio = 0; } tempo_media =0; } else { tempo_media++; } flag_libera=0; } } else {//flag de liberação desligado if(vetor[TAM_MAX] > vetor[0])//localizou o inicio de subida { flag_libera=1; } } gira_vetor(); tempo_de_envio++; }//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 confiavel //#define TIME_BAUD 68//9600 bps - 4MHZ - usando oscilador interno //#define BAUD_RX 58//9600 bps - 4MHZ - cristal 4MHZ - recepção funcionou bem(houve pouquissimo erros) - no proteus esse valor não funciona //#define BAUD_RX 60//9600 bps - 4MHZ - recepção funcionou bem(houve pouquissimo erros) //#define TIME_BAUD 175//4800 bps - 4MHZ //#define BAUD_RX 165//4800 bps - 4MHZ - recepção funcionou muito bem(100% confiavel 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
Nenhum comentário :
Postar um comentário
olá,digite aqui seu comentário!