Um detalhe que influencia no resultado final são as sapatas usadas como elemento sensor(pode ser de borracha, espuma ou qualquer outro elemento que apresente a propriedade mecânica de ser elástico).Neste projeto como eu queria algo mais sensível usei espumas(tipo de colchoes), veja que a variação de unidades lidas vão depender da curva característica das sapatas de apoio e também da capacidade de flambar(sofrer flexão) do material usado como base.
A opção de usar um fotodiodo é devido a seu maior tempo de resposta embora que o uso de LDR seja uma boa opção devido a sua característica de varia a resistência numa faixa maior do que os fotodiodos, o capacitor de 100nF é para filtrar pequenos ruídos que possam afetar a leitura.O esquemático elétrico é visto a seguir:
Observe que este projeto é uma aplicação do exemplo apresentado anteriormente aqui no blog("emulando uma porta serial" ), para comunicar com o PC é necessário usar um CI para fazer o "casamento" das tensões(popular MAX232).O software para usar a porta serial pode ser qualquer aplicativo que "leia" a porta serial de seu pc. As configurações da seria são 9600b/s, 8 bits de dados, sem paridade, 1 bit de stop.Todo o circuito funciona com 5V, veja o vídeo de demonstração:
Agora vamos para a parte lógica desta balança veja as linhas de código fonte a seguir:
/* * balança óptica * * Compilador : MPlabXC8 * Microcontrolador: 12F675 * Autor: aguivone * Versão: 1 * Data : 05/08/2016 */ #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 ////High speed para o cristal #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 descomentar esta linha e comentar as 2 anteriores //#define TIME_BAUD 202//4800 bps - 20MHZ //#define BAUD_RX 200//4800 bps - 20MHZ #define TX GP2//configura o pino que será TX #define RX GP1//configura o pino que será RX #define BOTAO GP3//configura o pino como entrada, botão setar nova referencia ///variaveis globais usada neste projeto long tensao=0; char flag_libera=0; long tensao_anterior=0; long variacao=0; long referencia=0; bit flag_sinal=0; ///usado para converter tensão. 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 porta serial emulada /////// 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 } //imprime uma cadeia de caracteres void escreve_frase(char *frase) { int tam_frase = strlen(frase); int contagem = 0; while (contagem < tam_frase) { escreve_char(frase[contagem]); contagem++; } } //usado para converter um numero em string 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_frase(" \r\n"); } // pega referência para calcular a variação somente na descida do sinal void pega_ref(void) { referencia = 0; for(int val=0;val<5;val++) { referencia = referencia + ler_adc_un(); __delay_ms(100); } referencia = referencia/5;//tira media escreve_frase("Referencia:"); long_to_char(referencia); escreve_frase("\r\n"); } ///////////////////////////////////////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(100);//debounce e tempo para preparar hardware //logo a frequencia de interrupção é 250khz escreve_frase("inicializando... \r\n");//a primeira escrita é sempre perdida(ainda não sei o porque) escreve_frase("Pesagem optica \r\n"); //inicializa pegando um valor de referencia pega_ref();//pega referencia for(;;) { // __delay_ms(100);//como tem um intevalo grande tira ruidos pontuais if(BOTAO == 0) { pega_ref();//pega nova referencia __delay_ms(500);//debounce } tensao = ler_adc_un(); if(tensao_anterior >tensao) { variacao = tensao_anterior - tensao; flag_sinal=1;//indica que o sinal está descendo } else { variacao = tensao - tensao_anterior; flag_sinal=0;//indica que o sinal está subindo } if(variacao > 3)//verifica variação se é maior que 3 (filtro) { if((referencia > tensao)&&(flag_sinal==1))//o valor sempre terá que ser menor que o de referencia(pois o led aproxima mais do sensor)) {///se for maior pode ser ruidos(no momento de desdetecção) escreve_frase("Valor lido ="); long_to_char(tensao); escreve_frase("Variacao = "); long_to_char(referencia - tensao); } tensao_anterior = tensao; } }//loop infinito }//main //NOTAS DE PARAMETRIZAÇÃO(sugestã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
Obrigado a todos que acompanham minhas postagens, e até a próxima pessoal!
Nenhum comentário :
Postar um comentário
olá,digite aqui seu comentário!