Ao ler o modulo analógico o qual varia sua conversão de 0 a 1024, sendo então enviado este valor ao aparelho ou equipamento que irá receber("no meu caso usei um celular pra isso"), o calculo da tensão fica por conta do smatphone pois assim caso mude o range de leitura, o que pode ser feito colocando um divisor resistivo(basta fazer uma busca sobre o assunto no google), basta configurar isso no aparelho.Por exemplo se eu quiser que o pic faça a leitura de 0 a 30V, devo configurar no software do celular para valor máximo de 30 assim ele irá calcular em cima deste valor.
O aplicativo para android está disponível no link : https://drive.google.com/open?id=0Bx9JeN0dmzXxcUszcEh4LTR1T3M .
O vídeo de demostração do funcionamento é este :
O Esquemático:
O Código fonte:
/*
* voltimetro DC - via serial
*
* Compilador : MPlabXC8
* Microcontrolador: 12F675
* Autor: aguivone
* Versão: 1
* Data : 15/09/2015
* Revisado: 29/10/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
#define TX GP2//configura o pino que será TX
#define RX GP1//configura o pino que será RX
int tensao=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(unsigned long 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]);
}
//////////////////////////////////////////////////////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
for(;;)
{ __delay_ms(300);
tensao = ler_adc_un();
long_to_char(tensao);
}//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