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

ADC module in 18F4550

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



Joined: 19 Apr 2016
Posts: 6

View user's profile Send private message

ADC module in 18F4550
PostPosted: Wed Apr 20, 2016 9:21 am     Reply with quote

I am working in a project with 18F4550.
It needs to acquire data from an LM35 and send it to a PC via USB
The problem is the data acquired is "jumping" in value about 3 or 5 degrees above or below. It must be steady unless temperature arises or changes.
I think something is wrong with the configuration of everything involved with the ADC MODULE, Specially the adjustment of the Tad.
I have a 20MHZ Xtal and it is raised by PLL to 48MHZ

I would like somebody of you could write for me some example of the lines I should write into my program for the ADC.

I think the Tad is too short and that is the reason why it jumps.

Thank you in advance.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 20, 2016 9:34 am     Reply with quote

Use the forum's search page:
http://www.ccsinfo.com/forum/search.php
Search for:
Quote:
LM35 setup_adc

Set it to search for all term:
Quote:
[x]Search for all terms

This will get you every thread that has ADC code for the LM35.
ingemilo



Joined: 19 Apr 2016
Posts: 6

View user's profile Send private message

PostPosted: Wed Apr 20, 2016 10:23 am     Reply with quote

PCM programmer wrote:
Use the forum's search page:
http://www.ccsinfo.com/forum/search.php
Search for:
Quote:
LM35 setup_adc

Set it to search for all term:
Quote:
[x]Search for all terms

This will get you every thread that has ADC code for the LM35.


I found something similar to my problem
in "Extrange changes in ADC" by verba

Data entered to the hyperterminal is similar to this. The diference is I am using just one channel, and I am using 18F4550 instead 16F876

C0=0 - C1=64 - C2=0 - C3=1018 - C4=51 - C5=58
C0=2 - C1=64 - C2=0 - C3=1023 - C4=58 - C5=56
C0=0 - C1=55 - C2=0 - C3=1022 - C4=60 - C5=56
C0=2 - C1=59 - C2=0 - C3=1023 - C4=64 - C5=56
C0=0 - C1=58 - C2=2 - C3=1022 - C4=60 - C5=60
C0=1 - C1=60 - C2=0 - C3=1022 - C4=55 - C5=56
C0=1 - C1=57 - C2=0 - C3=1023 - C4=60 - C5=56
C0=0 - C1=59 - C2=2 - C3=1023 - C4=57 - C5=57
C0=4 - C1=60 - C2=1 - C3=1021 - C4=57 - C5=55
C0=0 - C1=58 - C2=1 - C3=1023 - C4=61 - C5=58
C0=0 - C1=58 - C2=1 - C3=1022 - C4=60 - C5=56
C0=0 - C1=51 - C2=0 - C3=1023 - C4=58 - C5=56
C0=0 - C1=56 - C2=0 - C3=1021 - C4=60 - C5=57
C0=0 - C1=58 - C2=0 - C3=1022 - C4=56 - C5=57
C0=4 - C1=58 - C2=0 - C3=1019 - C4=51 - C5=60
C0=2 - C1=59 - C2=0 - C3=1022 - C4=56 - C5=56
C0=0 - C1=58 - C2=0 - C3=1023 - C4=56 - C5=56
C0=0 - C1=55 - C2=0 - C3=1023 - C4=59 - C5=51
C0=0 - C1=59 - C2=3 - C3=1023 - C4=59 - C5=51
C0=1 - C1=58 - C2=0 - C3=1022 - C4=60 - C5=56
C0=0 - C1=57 - C2=0 - C3=1022 - C4=55 - C5=60
C0=1 - C1=61 - C2=2 - C3=1023 - C4=60 - C5=60
C0=0 - C1=60 - C2=0 - C3=1023 - C4=57 - C5=58
C0=0 - C1=60 - C2=0 - C3=1023 - C4=57 - C5=56

any idea what to do for solve this? making changes in the adc module?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Apr 20, 2016 10:54 am     Reply with quote

Obvious questions.
What are you using for Vref?.

What other circuitry is on the board?.

If you are using the PIC supply, then this is almost certainly 90% of the reason for variations.....

If you look at other threads with variable values, like:
<http://www.ccsinfo.com/forum/viewtopic.php?t=50585&highlight=lm35+setupadc>

You will see that this was caused by insufficient smoothing.

The software solution, is to average the adc readings. Will only 'solve' the problem if the noise is basically random.

Looking at the noise pattern, one thing leaps out, which is that the change is basically the same for low values as the high values. Suggests noise in the ground connection between the PIC and the LM35...
ingemilo



Joined: 19 Apr 2016
Posts: 6

View user's profile Send private message

PostPosted: Wed Apr 20, 2016 11:22 am     Reply with quote

This is my code
Code:

#include <18f4550.h> 
#device adc=10
#fuses hspll,nowdt,noprotect,nodebug,usbdiv,pll5,cpudiv1,vregen
#use delay(clock=48000000)
#include <usb_cdc.h>

int16  grados;
int16 medicion;

void main(){

usb_cdc_init();
usb_init();

do{
  usb_task();

  setup_adc(adc_clock_div_32);
  setup_adc_ports(all_analog);
  setup_adc_ports(AN0);
  set_adc_channel(0);
  delay_us(20);

  if(usb_enumerated()){
     medicion=read_adc();
     delay_us(20);
     setup_adc(adc_off);

     grados=((medicion)*(500))/(1024);

     printf(usb_cdc_putc,"\r %Lu C",grados);
     delay_ms(1000);
    }
  }

while(true);
}

Please let me know if I have to make any change in it.

Circuit is fed with +5V regulated with 7805.

I have a doubt in the line .
Code:
setup_adc(adc_clock_div_32);

Is taken 48MHz/32? or
is taken 20MHz/32?

Because my Xtal is 20MHz

Another doubt I have:
If I use
Code:
setup_adc(adc_clock_internal);

Is the time always between 2-4 us regardless the oscillator of 48MHz or 20MHz or 4MHz or whatever?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Apr 20, 2016 2:37 pm     Reply with quote

ADC_CLOCK_INTERNAL is not recommended for processor speeds above 1MHz, unless you put the processor to sleep for the conversion.

The reason is that the clock is asynchronous to the processor operation, and with lots of processor instructions in each ADC clock, you will get random variation in the results as the processor instruction clock 'beats' with the adc clock. A sure way to get poor stability.

Couple this to using the Vss supply as a Vref, and you are unlikely to get values ever better than several counts of variation.
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Apr 20, 2016 3:13 pm     Reply with quote

Whenever I used the LM34/ LM35 sensors I built a 'signal conditioning PCB which consisted of the LM34, a rail to rail OP AMP used as a voltage follower, 2- 10r resistors and 2- 22mfd caps. The Rs and Cs formed a 2 stage R-C filter on the power going to the opamp and LM34. As well there was a small cap (I think 1 mfd) on the output of the opamp to slow down the analog signal. I easily had 50 feet (20 meters ?) of cable between the sensor and the PIC. Generally speaking 'temperature' controllers do NOT require fast response, 1/4 second is actually fast.
Also, 'noise' can come in the Vdd and gnd lines of the PIC, so be sure to use bypass caps (.1 mfd) at all power feeds.
To get very stable readings Vref of the ADC needs to be precise, the LM7805 isn't, can easily be 4.9 to 5.1 and WILL vary depending on load. Turning on a couple LEDs can drop Vdd, and your math conversion as well as actual ADC reading will be wrong.
Also, consider that a DVM or DMM actually only sample at 3-4 times per second. It's well 'filtered' to NOT jump around and actually hides noise.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Apr 21, 2016 1:13 am     Reply with quote

Also, the code posted is turning the ADC off after the first reading. Read then has to switch it back on. It will do so, but there will then be no acquisition time. Another reason for getting poor readings.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu Apr 21, 2016 9:12 am     Reply with quote

You also need to think about this conversion:

Code:
grados=((medicion)*(500))/(1024);


Over what range will this work? Hint: not the full range of the sensor. What will happen if the value is out of range? Hint: not what you may expect. Why? Hint: think about the ranges of the intermediate values in the expression. While this uses integer maths, which is good, it uses 16 bit integer arithmetic and that isn't enough to deal with all possible ADC values that the sensor can produce.

This would work better as:

Code:
grados = (medicion * 125)/256;

// There is no need for all those brackets, they just confuse things.
// This could even be, as this is a special case (think about it...):

grados = make8(medicion * 125, 1);

// In all three versions, grados only needs to be int8.



And in no case will it work below a few degrees C.
ingemilo



Joined: 19 Apr 2016
Posts: 6

View user's profile Send private message

PostPosted: Sat Apr 23, 2016 8:16 am     Reply with quote

Ttelmah wrote:
Also, the code posted is turning the ADC off after the first reading. Read then has to switch it back on. It will do so, but there will then be no acquisition time. Another reason for getting poor readings.


Good point. Let me check it.
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