CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I need great HELP about A/D

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mojsa2000



Joined: 18 May 2010
Posts: 78

View user's profile Send private message

I need great HELP about A/D
PostPosted: Wed Nov 03, 2010 2:01 pm     Reply with quote

Hi
I have a big problem with my project. I am disappointed to solve it. I need your advice seriously.
I've made an energy calculator that has 2 analog inputs. The inputs are between 0-5 volts. My project has two parts:
Main program and calibration program that calibrates inputs. In calibration program I do reading pins (A0,A1) continuously and use analog to digital (A/D) conversion module. But unfortunately the the conversion results are
not accurate. (it has a 0.1-0.3 V tolerance)

This is the calibration program. Please check it and help me by finding my faults.

thanks all


Code:


#include <16f877a.h>
#byte H_addr=0x1e
#byte L_addr=0x9e
#FUSES XT,NOWDT,PUT,BROWNOUT,NOLVP
#DEVICE ADC=10
#use delay (clock=4000000)
#use fast_io (A)
#include <H:\PIC\My sources\flex_lcd.c>


static float energy,total_energy;
static float v_out,i_out,v_out2,i_out2;
float v_buffer,i_buffer;
static unsigned int channel;
int8 counter=0;
int8 ave_counter=0;
//*********************  All flags  *******************************************

int1 calculating_flag,display_flag;
int1 v_sign,i_sign;

//*****************************************************************************


#int_AD
void  AD_isr(void)
{
counter++;
if(counter==3){
if(i_sign)//read channel(0)_reserved for current
{
i_buffer=read_adc(ADC_READ_ONLY);
i_sign=0;
channel=1;
}
}
if(counter==6){
if(v_sign)//read channel(1)__reserved for voltage
{
v_buffer=read_adc(ADC_READ_ONLY);
v_sign=0;
calculating_flag=1;
counter=0;
channel=0;
H_addr=0;
L_addr=0;
}
}
}

#int_TIMER2
void  TIMER2_isr(void)
{
if(channel==0)
{
set_adc_channel(0);
i_sign=1;
}
else
{
set_adc_channel(1);
v_sign=1;
}
read_adc(ADC_start_ONLY);
}

void calculating()
{
if(calculating_flag)
{
ave_counter++;
v_out+=v_buffer*5/1023;
i_out+=i_buffer*5/1023;
if(ave_counter==100){
display_flag=1;
v_out2=v_out/100;
i_out2=i_out/100;
v_out=0;
i_out=0;
energy=v_out2*i_out2*0.62;//calculates the energy in per 620ms
total_energy=total_energy+energy;
ave_counter=0;
}
}
calculating_flag=0;
}
void main()
{
SET_TRIS_A( 0xFF );
enable_interrupts(GLOBAL);
enable_interrupts(INT_AD);
enable_interrupts(INT_RTCC);
setup_adc_ports(AN0_AN1_VSS_VREF);
setup_adc(ADC_CLOCK_DIV_8);
setup_timer_2(T2_DIV_BY_4,255,1);//1ms
enable_interrupts(INT_TIMER2);
setup_comparator(NC_NC_NC_NC);
set_timer2(0);
delay_ms(10);
lcd_init();
   
while(1)
{
calculating();
if(display_flag){
lcd_gotoxy(1,1);
printf(lcd_putc,"V=%.3f ",v_out2);
lcd_gotoxy(9,1);
printf(lcd_putc,"I=%.3f ",i_out2);
lcd_gotoxy(1,2);
printf(lcd_putc,"E=%5.3f ",energy);
lcd_gotoxy(9,2);
printf(lcd_putc,"T=%5.3f ",total_energy);
display_flag=0;
}
}
}



Last edited by mojsa2000 on Thu Nov 04, 2010 1:39 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 03, 2010 2:30 pm     Reply with quote

My advice is to get rid of all the interrupt routines. Also, get rid of the
"start only" and "read only" stuff. Just do a simple reading of the A/D.
Make your program work with a simple while() loop in main(). Then later,
after it's working, you can add the interrupt routines if you want to.
mojsa2000



Joined: 18 May 2010
Posts: 78

View user's profile Send private message

PostPosted: Thu Nov 04, 2010 1:44 am     Reply with quote

dear PCM
I did the way that you suggested but the result didn't change.


Code:
while(1)
{
set_adc_channel(0);
delay_us(20);
i_buffer=read_adc (ADC_START_AND_READ);
delay_us(40);
i_out=i_buffer*5/1023;
lcd_gotoxy(9,1);
printf(lcd_putc,"I=%.3f ",i_out);
delay_ms(500);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Thu Nov 04, 2010 3:27 am     Reply with quote

In which case you need to look at your hardware.

First thing, if the pins is not used, connect a separate _smooth_ supply to the Vref pin, program the ADC to use this, and see if things change. I suspect you will find it will. Using the supply is _not_ a route to accuracy. Both since it will change instantaneously as other things occur in your board, and because it will tend to drift with temperature (standard Vregs are not that stable). Use a bandgap reference warranted to give at least 10bit accuracy, if you want 10bit accuracy from the ADC...

If you still have problems, then look at the stability of the circuitry generating the inputs. Does it meet the specifications for the minimum output impedance?. Noise?.

A search here will find why 'not' to use INT_AD. It is basically pointless, unless you are triggering a synchronous ADC reading using the CCP.

Remember if you select an ADC channel, you _must_ allow Tacq, before starting a read. In your original code, you don't. You select the channel, and immediately start a read. This would have given completely 'false' readings, so the simpler code should be better in terms of the reading actually having _some_ relation to the real value, but if the reading is still wrong, then you have a problem in the signals involved...

Best Wishes
mojsa2000



Joined: 18 May 2010
Posts: 78

View user's profile Send private message

PostPosted: Thu Nov 04, 2010 2:46 pm     Reply with quote

Hi
thanks Ttelmah
I did your advices. Problem didn't solve. I have a new question. I used the "setup_adc_ports(AN0_AN1_VSS_VREF)" setup
when I faced to the problem I changed my ADC setup. I configure pins as
setup_adc_ports(AN0_AN1_AN2_AN4_AN5_VSS_VREF) but I use only pin A0 and pin A5. I changed program by this new
arrangements. I did reading only Pin A5 and result was "0" when the value on this pin was 2.5v.
I'm confused. I'm sure that there is a point about pins when they are in ADC mode ADC that I don't know it.
mojsa2000



Joined: 18 May 2010
Posts: 78

View user's profile Send private message

PostPosted: Thu Nov 04, 2010 3:57 pm     Reply with quote

Hi again
There is strange event. I simultaneously use 2 channels A0, A1 and input values are variable.
When one of them (for example A0) increases or decreases in large value affects other channel.
I used suitable delays in program. But why this take places????
Please help me. This matter is vital for me....

Code:
void main()
{
SET_TRIS_A( 0xFF );
enable_interrupts(GLOBAL);
enable_interrupts(INT_AD);
enable_interrupts(INT_RTCC);
setup_adc_ports(AN0_AN1_VSS_VREF);
setup_adc(ADC_CLOCK_DIV_32);
setup_timer_2(T2_DIV_BY_4,255,1);//1ms
enable_interrupts(INT_TIMER2);
setup_comparator(NC_NC_NC_NC);
set_timer2(0);
delay_ms(10);
lcd_init();
while(1)
{
ave_counter++;
read_adc (ADC_OFF);
set_adc_channel(0);
delay_us(40);
v_buffer=0;
i_buffer=read_adc (ADC_START_AND_READ);
delay_us(40);
i_out+=(i_buffer*5/1023);
delay_ms(2);
read_adc (ADC_OFF);
set_adc_channel(1);
delay_us(40);
i_buffer=0;
v_buffer=read_adc (ADC_START_AND_READ);
delay_us(40);
v_out+=v_buffer*5/1023;
delay_ms(2);
if(ave_counter==100)
{
v_out2=v_out/100;//make an average
i_out2=i_out/100;
v_out=0;
i_out=0;
energy=v_out2*i_out2*0.62;//calculates the energy in per 8ms
total_energy=total_energy+energy;
ave_counter=0;
lcd_gotoxy(1,1);
printf(lcd_putc,"V=%.3f ",v_out2);
lcd_gotoxy(9,1);
printf(lcd_putc,"I=%.3f ",i_out2);
lcd_gotoxy(1,2);
printf(lcd_putc,"E=%5.3f ",energy);
lcd_gotoxy(9,2);
printf(lcd_putc,"T=%5.3f ",total_energy);
}
}
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Fri Nov 05, 2010 3:03 am     Reply with quote

Go back to my question about the output impedance of your circuits feeding the ADC's.

The ADC on the PIC, is internally a capacitor. It takes time to charge. The capacitor in your chip, is 120pF. The multiplexer has an 'apparent' resistance of about 7KR, while the rest of the input structure in the PIC, adds another 1KR. The capacitor is specified to charge to withing 0.5 bit of the incoming voltage in under 20uSec _provided the source impedance of the circuitry feeding the ADC, is under 10KR_. If the source impedance is over this, the time rises, and the accuracy degrades (there are leakage currents which are asymmetric, so impedance's significantly over this should not be used.

You have all the symptoms of using a source that does not have a low enough impedance to properly charge the capacitor....

Best Wishes
mojsa2000



Joined: 18 May 2010
Posts: 78

View user's profile Send private message

PostPosted: Fri Nov 05, 2010 3:26 pm     Reply with quote

Dear Ttelmah
thanks for your advices
I recognized my problem. When I do reading Pin A0, pin A1 must be "0" or it be read as "0", but it isn't. A very small voltage is read on PinA1 when A0 is reading (there is a low current on pinA1 that decreases/increases by decreasing/increases voltage on A0 ). There is a same story about pin A1 when is reading. When I connect the one of pins to ground (by a wire) the problem was solved.
Now the problem is cleared for me to solve it, but I need your help too.
Is there a way to solve it on my program? Or I need a hardware change on the pins?
please help me
thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Fri Nov 05, 2010 3:43 pm     Reply with quote

You need to redesign your hardware I'm afraid....

Best Wishes
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Fri Nov 05, 2010 10:06 pm     Reply with quote

It sounds like you do not have low impedance drives to your A0 and A1 pins.

Reread what Ttelmah said on Friday.
_________________
The search for better is endless. Instead simply find very good and get the job done.
mojsa2000



Joined: 18 May 2010
Posts: 78

View user's profile Send private message

PostPosted: Sat Nov 06, 2010 1:46 pm     Reply with quote

thanks
I'll do that said Ttelmah. I redesign my project hardware. It has two part. I think it is related to power supply designing. Also the inputs come from 2 op-amp u741.
I will report the results as soon as possible to my friends in this forum.
best wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group