View previous topic :: View next topic |
Author |
Message |
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
HELP! ADC Vref |
Posted: Tue Sep 17, 2013 10:43 am |
|
|
hello guys!
I need help!
I have a pic18f2553 and use it with v 4.3
I would put the voltage reference for the ADC 5V
I am having trouble configuring the external reference for ADC reading.
Please help me!
I tried this, but reading does not correspond.
Code: |
setup_adc_ports (AN0_to_AN9 | VSS_Vref);
setup_adc (ADC_CLOCK_INTERNAL);
|
|
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Tue Sep 17, 2013 11:07 am |
|
|
Hi,
So, Vdd = 4.3V and Vref = 5V? What do the Electrical Specifications in the datasheet say about the range of Vref?
Post a complete, compilable test program that we can easily test.
John |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Wed Sep 18, 2013 5:34 am |
|
|
I found some examples like the one posted above, but nothing works properly! |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Wed Sep 18, 2013 6:39 am |
|
|
Hi,
I say again post a complete, compilable test program that we can easily test.
Two lines of ADC setup code is hardly enough to go on! Who knows, without seeing
your complete, compilable test program, we would all just be guessing at the problem!
John |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Wed Sep 18, 2013 6:47 am |
|
|
I still do not understand how this can help, because the important thing is setting the ADC
setup_adc_ports(AN0_to_AN9 | Vref_Vref);
setup_adc(ADC_CLOCK_INTERNAL);
//setup_adc(ADC_CLOCK_DIV_2);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //Incremento em 1.6uS
setup_timer_2(T2_DIV_BY_4,249,5); //Incremento em 1.0mS
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
ext_int_edge(0,H_TO_L); // Int_Ext sensível a borda de descida
ext_int_edge(1,H_TO_L); // Int_Ext sensível a borda de descida
// Analógica 00
Leitura=0;
pacote.adc0=0;
set_adc_channel(0);//seta adc A0
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
for(cont=1;cont<=200;cont++){//faz a media das 200 Leituras descartando as 40 primeiras
pacote.adc0 = read_adc();//ler adc A0
//for(X=0;X<Tempo_Delay;X++){}
delay_us(100);
if(cont>40){
Leitura+=pacote.adc0;
} //if
}//for
Leitura=(Leitura/160);
//pacote.adc0 = Leitura*12.21;// coloca em mV*10
pacote.adc0 = Leitura; |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Wed Sep 18, 2013 7:18 am |
|
|
By posting a complete program we can easily see several errors...
First...
The 'program' you posted' is NOT complete!
first line should say what PIC header to use...
2nd line might be the CPU clock speed..
3rd no MAIN section
again you MUST supply us with a COMPLETE program listing.We honestly can't solve your prolems without it!!
Second...
You enable several interrupts without any ISRs. This WILL cause the program to crash, or not even run...
Third...
It is NOT normal to use adc_clock_internal.If we knew what speed you're running the PIC at, we could tell you what the corect setting would be.If you read the 'adc section' of the datasheet, you'll see a chart of CPU speed vs. ADC clock settings.
As others have requested, post the COMPLETE program, otherwise nobody can help.
hth
jay |
|
|
lucasromeiro
Joined: 27 Mar 2010 Posts: 167
|
|
Posted: Wed Sep 18, 2013 7:29 am |
|
|
Code: |
#include <18F2553.h>
#device adc=12
#FUSES NOWDT //No Watch Dog Timer
//#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PROTECT //Code protected from reads
#FUSES noBROWNOUT //precisa p evitar reset indesejado ao entrar na bateria //Reset when brownout detected
//#FUSES BORV20 //Brownout reset at 2.0V
//#FUSES PUT //Power Up Timer
//#FUSES NOCPD //No EE protection
//#FUSES STVREN //Stack full/underflow will cause reset
//#FUSES NODEBUG //No Debug mode for ICD
//#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
//#FUSES NOWRT //Program memory not write protected
//#FUSES NOWRTD //Data EEPROM not write protected
//#FUSES IESO //Internal External Switch Over mode enabled
//#FUSES FCMEN //Fail-safe clock monitor enabled
//#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
//#FUSES NOWRTC //configuration not registers write protected
//#FUSES NOWRTB //Boot block not write protected
//#FUSES NOEBTR //Memory not protected from table reads
//#FUSES NOEBTRB //Boot block not protected from table reads
//#FUSES NOCPB //No Boot Block code protection
#FUSES NOMCLR //Master Clear pin disabled
//#FUSES LPT1OSC //Timer1 configured for low-power operation
//#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
//#FUSES PLL1 //No PLL PreScaler
#FUSES CPUDIV1 //System Clock by 1
//#FUSES USBDIV //USB clock source comes from PLL divide by 2
//#FUSES VREGEN //USB voltage regulator enabled
#use delay(clock=20000000,RESTART_WDT)
#use rs232(baud=2400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,restart_wdt)
//Estação Transmissora
#include <string.h>
#INCLUDE <stdlib.h>
#define dig1 input(pin_b4)
#define dig2 input(pin_b5)
#define dig3 input(pin_b6)
#define dig4 input(pin_b7)
#define LED_TX pin_c1
#define LED_PULSO pin_c0
#define Tempo_Delay 50
#include "..\Biblioteca (Protocolo)\protocolo.h"
#include "..\Biblioteca (Manchester)\manchesterEncoder.h"
static protocolo pacote;
float32 Leitura;
int cont;
int16 X; // Variável de Incremento do For para o Tempo_Delay
float32 ADC_01_Aux;
float32 ADC_02_Aux;
float32 ADC_03_Aux;
float32 ADC_04_Aux;
int32 Quantidade_de_Capturas=0;
int1 Flag_Incrementa_Hidro1=0;
int1 Flag_Incrementa_Hidro2=0;
//*****************************************************
unsigned int16 Numero_Estacao = 80;
unsigned int16 Intervalo_A = 14600;
unsigned int16 Intervalo_B = 10010;
//*****************************************************
unsigned int16 Tempo_mS=0; //Conta a cada vez que entra na interrupção
unsigned int8 Flag_Envios; //Flag dos Intervalos de Envio
unsigned int16 Intervalo; //Intervalos Específicos
//------------------------------
// Interrupções do Timer 2
//------------------------------
#int_TIMER2
void TIMER2_isr(void){
Tempo_mS++;
} // void TIMER2_isr(void)
//------------------------------
// Interrupções do Hidrômetro
//------------------------------
#int_EXT
void EXT1_isr(void)
{
Flag_Incrementa_Hidro1=1;
}//EXT_isr(void)
#int_EXT1
void EXT_isr(void)
{
Flag_Incrementa_Hidro2=1;
}//EXT1_isr(void)
//------------------------------
// Captura de [spam]ógicas
//------------------------------
void Captura_ADC(){
Leitura=0;
pacote.adc0=0;
pacote.adc1=0;
pacote.adc2=0;
pacote.adc3=0;
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// [spam]ógica 00
Leitura=0;
pacote.adc0=0;
set_adc_channel(0);//seta adc A0
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
for(cont=1;cont<=200;cont++){//faz a media das 200 Leituras descartando as 40 primeiras
pacote.adc0 = read_adc();//ler adc A0
//for(X=0;X<Tempo_Delay;X++){}
delay_us(100);
if(cont>40){
Leitura+=pacote.adc0;
} //if
}//for
Leitura=(Leitura/160);
//pacote.adc0 = Leitura*12.21;// coloca em mV*10
pacote.adc0 = Leitura;
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// [spam]ógica 01
Leitura=0;
pacote.adc1=0;
set_adc_channel(1);//seta adc A1
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
for(cont=1;cont<=200;cont++){//faz a media das 200 Leituras descartando as 40 primeiras
pacote.adc1 = read_adc();//ler adc A1
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
if(cont>40){
Leitura=Leitura+pacote.adc1;
}//if
}//for
Leitura=(Leitura/160);
//pacote.adc1 = Leitura*12.21;// coloca em mV*10
pacote.adc1 = Leitura;
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// [spam]ógica 05
Leitura=0;
pacote.adc2=0;
set_adc_channel(4);//seta adc A5
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
for(cont=1;cont<=200;cont++){//faz a media das 200 Leituras descartando as 40 primeiras
pacote.adc2 = read_adc();//ler adc A0
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
if(cont>40){
Leitura=Leitura+pacote.adc2;
}//if
}//for
Leitura=(Leitura/160);
//pacote.adc2 = Leitura*12.21;// coloca em mV*10
pacote.adc2 = Leitura;
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// [spam]ógica 09
Leitura=0;
pacote.adc3=0;
set_adc_channel(9);//seta adc A1
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
for(cont=1;cont<=200;cont++){//faz a media das 200 Leituras descartando as 40 primeiras
pacote.adc3 = read_adc();//ler adc A1
delay_us(100);
//for(X=0;X<Tempo_Delay;X++){}
if(cont>40){
Leitura=Leitura+pacote.adc3;
}//if
}//for
Leitura=(Leitura/160);
//pacote.adc3 = Leitura*12.21;// coloca em mV*10
pacote.adc3 = Leitura;
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//Mecanismo de integração da variável ADC_0X_Aux para posteriormente calcular a média,
//a depender do valor de quantidade de capturas realizadas.
ADC_01_Aux = ADC_01_Aux + pacote.adc0;
ADC_02_Aux = ADC_02_Aux + pacote.adc1;
ADC_03_Aux = ADC_03_Aux + pacote.adc2;
ADC_04_Aux = ADC_04_Aux + pacote.adc3;
} // void Captura_ADC()
//------------------------------
// Cálculo da média das [spam]ógicas
//------------------------------
void Media_ADC(){
//Atribui a cada elemento pacote.adcX o valor da variável ADC_0X_Aux divido
//pela quantidade de capturas realizadas até o momento do envio.
pacote.adc0 = ADC_01_Aux/Quantidade_de_Capturas;
pacote.adc0 = pacote.adc0*12.21; // coloca em mV*10
pacote.adc1 = ADC_02_Aux/Quantidade_de_Capturas;
pacote.adc1 = pacote.adc1*12.21; // coloca em mV*10
pacote.adc2 = ADC_03_Aux/Quantidade_de_Capturas;
pacote.adc2 = pacote.adc2*12.21; // coloca em mV*10
pacote.adc3 = ADC_04_Aux/Quantidade_de_Capturas;
pacote.adc3 = pacote.adc3*12.21; // coloca em mV*10
//Zerando as variáveis ADC_0X_Aux e Quantidade_de_Captura.
Quantidade_de_Capturas=0;
ADC_01_Aux=0;
ADC_02_Aux=0;
ADC_03_Aux=0;
ADC_04_Aux=0;
}
//------------------------------
// Captura de Digitais
//------------------------------
void Captura_Digitais(){
pacote.d1=dig1;
pacote.d2=dig2;
pacote.d3=dig3;
pacote.d4=dig4;
} // void Captura_Digitais()
//------------------------------
// Captura de Hidrômetros
//------------------------------
void Captura_Hidrometros(){
if(Flag_Incrementa_Hidro1==1){
output_high(LED_PULSO); // Acende LED para demonstrar
delay_ms(100); // que houve interrupção
output_low(LED_PULSO); // após 250 ms apaga LED
pacote.hidro1++;
if(pacote.hidro1>=9999999)pacote.hidro1=0;
Flag_Incrementa_Hidro1=0;
}
if(Flag_Incrementa_Hidro2==1){
output_high(LED_PULSO); // Acende LED para demonstrar
delay_ms(100); // que houve interrupção
output_low(LED_PULSO); // após 250 ms apaga LED
pacote.hidro2++;
if(pacote.hidro2>=9999999)pacote.hidro2=0;
Flag_Incrementa_Hidro2=0;
}
}
void main(){
setup_adc_ports(AN0_TO_AN9|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
//setup_adc(ADC_CLOCK_DIV_2);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //Incremento em 1.6uS
setup_timer_2(T2_DIV_BY_4,249,5); //Incremento em 1.0mS
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
ext_int_edge(0,H_TO_L); // Int_Ext sensível a borda de descida
ext_int_edge(1,H_TO_L); // Int_Ext sensível a borda de descida
//Identificação da Estação (Máximo de Quatro Dígitos)
pacote.id=Numero_Estacao;
pacote.hidro1=0;
pacote.hidro2=0;
//Flag dos Intervalos de Envio
Flag_Envios=1;
//pisca o led 4 vezes //versão 130417
output_high(LED_TX);
output_high(LED_PULSO);
delay_ms(250);
output_low(LED_TX);
output_low(LED_PULSO);
delay_ms(250);
output_high(LED_TX);
output_high(LED_PULSO);
delay_ms(250);
output_low(LED_TX);
output_low(LED_PULSO);
delay_ms(250);
output_high(LED_TX);
output_high(LED_PULSO);
delay_ms(250);
output_low(LED_TX);
output_low(LED_PULSO);
delay_ms(250);
output_high(LED_TX);
output_high(LED_PULSO);
delay_ms(250);
output_low(LED_TX);
output_low(LED_PULSO);
delay_ms(250);
while(true){
//---------------------------------------------------------
//Realiza as Capturas
Captura_ADC();
Captura_Digitais();
Captura_Hidrometros();
Quantidade_de_Capturas++;
//---------------------------------------------------------
//Definição do Intervalo
if(Flag_Envios==1 || Flag_Envios==2 || Flag_Envios==3){
Intervalo=Intervalo_A;
}
else if(Flag_Envios==4 || Flag_Envios==5){
Intervalo=Intervalo_B;
}
else if(Flag_Envios==6){
Intervalo=( (5000) + (pacote.id*100) );
Flag_Envios=0;
}
//---------------------------------------------------------
//Condição para o envio
if(Tempo_mS>=Intervalo){
Tempo_mS=0;
Flag_Envios++;
Media_ADC();
output_high(LED_TX);
montaPacote(&pacote);
enviaPacote(mensagem,(sizeof(protocolo)+2));
output_low(LED_TX);
} // if(Tempo_mS>=Intervalo)
//---------------------------------------------------------
} // while(true)
} // void main() |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Sep 18, 2013 11:28 am |
|
|
Start with some basic things:
1) VSS_Vref, means that the Vref high voltage needs to be fed into RA3. Is this what you are doing?.
2) Has your Vref got the required source impedance?. It needs to be able to deliver 150uA, without dropping during the conversion.
3) It has already been pointed out the ADC_CLOCK_INTERNAL, is _not_ a legitimate clock (unless you use sleep to stop the CPU during the conversion, which you don't). ADC_CLOCK_DIV_16 32, or 64 are the only recommended clocks at your CPU clock rate.
4) Why throw away 40 reading?. You gain nothing.
5) You don't need two delays:
Code: |
set_adc_channel(0);//seta adc A0
for(cont=1;cont<=160;cont++)
{ //You use 160 readings
delay_us(100);
pacote.adc0 = read_adc();//ler adc A0
Leitura+=pacote.adc0;
}
|
6) Use integers for your sums, rather than floats. You gain nothing from using floats, they take more space, and time to work with. Only convert to float for the final division.
I gave up here... |
|
|
|