![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Gaara
Joined: 10 Feb 2014 Posts: 11
|
Temperature A/D conversion - LM35DT to PIC18F2580 |
Posted: Mon Feb 10, 2014 8:09 am |
|
|
Hi everyone,
I'm slightly new to the world of A/D conversion especially using the CCS C compiler so forgive me if I'm asking an already answered question (I'll indicate later in the post the research I've conducted with regards to this forum).
My objective is to interface my PIC18F2580 with the LM35DT temperature sensor () which means A/D conversion.
At the moment I'm targeting the measurement of positive temperature values hence the manner in which my PIC is connected to the temp sensor is as seen in page 2 of the temp sensor datasheet ().
To tackle the task I broke my approach as follows:
Step 1 - get the A/D reading logic up and running without the temp sensor connected whilst using LED toggling to confirm each time the A/D conversion is done
Step 2 - Same approach as step 1 but with the temp sensor connected.
Step 3 - convert the obtained A/D conversion value to a Celsius temperature value and the printing the temperature value on a terminal program.
I know I've omitted the printing out of the ADC value and I've done this in order to at least establish I've fully understood my query below.
To execute step 1 firstly I've studied the example ex_admm.c to understand CCS C basics with regards to A/D conversion. Based on this and reading up the following posts on the forum:
https://www.ccsinfo.com/forum/viewtopic.php?t=37731&view=next
http://www.ccsinfo.com/forum/viewtopic.php?t=36381
http://www.ccsinfo.com/forum/viewtopic.php?t=32168&start=1
https://www.ccsinfo.com/forum/viewtopic.php?t=44432&view=previous
http://www.ccsinfo.com/forum/viewtopic.php?t=44201&highlight=adc+example
http://www.ccsinfo.com/forum/viewtopic.php?t=44115&highlight=adc+example
plus further research online I'm still not a 100% clear regarding how to set up the A/D conversion clock particularly as mentioned on page 259 of my PIC datasheet as follows:
the A/D conversion clock (TAD) must be as short as possible, but greater than the minimum TAD
In my code below I selected the operation option ADC_CLOCK_DIV_4 as I compared my oscillator frequency with the maximum device frequency as per table 20-1 on page 259 of the PIC datasheet.
Code: |
#include<18F2580.h>
#fuses XT,PUT,NOBROWNOUT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#define LED_ONE PIN_B2
unsigned int8 adc_value;
void temp_sensor();
void temp_sensor() {
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_4);
set_adc_channel(0);
adc_value = read_adc();
if(adc_done()) {
output_toggle(LED_ONE);
}
}
void main() {
do {
temp_sensor();
delay_ms(1000);
} while (TRUE);
}
|
I also went through the explanation of the A/D conversion clock as per this link http://www.piclist.com/images/www/hobby_elec/e_pic7_5.htm which was quite insightful.
In mentioning the above is this the right approach as to selecting the A/D conversion clock?
Thanks for any help. |
|
![](templates/subSilver/images/spacer.gif) |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Feb 10, 2014 10:35 am |
|
|
Hi,
I made a "driver" for the LM35 a while back.
http://www.ccsinfo.com/forum/viewtopic.php?t=48525
You might find it useful...
Be advised i was powering the Sensor with a Charge Pump..
you dont need to include the Timer ISR or timer code...
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
![](templates/subSilver/images/spacer.gif) |
Gaara
Joined: 10 Feb 2014 Posts: 11
|
|
Posted: Mon Feb 10, 2014 11:24 am |
|
|
Thanks Gabriel. I'll have a detailed look at your proposal tomorrow morning |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Mon Feb 10, 2014 12:51 pm |
|
|
and as a comment, 'hurrah' on reading the data sheet. Your ADC clock selection is right.
However look at Tacq. The ADC requires this time between the channel being selected, and starting the ADC conversion. |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Feb 10, 2014 8:03 pm |
|
|
what is the range of temperature you wish to resolve?
your results and resolution may be much improved by analog amplification of the LM35 signal if you are operating in the area below 40 deg Cent .
the resolution of the PIC ADC can be quite limiting if you are operating in the
area below 40 degrees |
|
![](templates/subSilver/images/spacer.gif) |
TokTok
Joined: 22 Jan 2014 Posts: 35
|
|
Posted: Tue Feb 11, 2014 9:23 am |
|
|
Hi asmboy,
I intend on measuring temperature ranges between -30 degrees Celsius to 45 degrees Celsius hence the reason I selected the LM35 which is rated for full -55 degrees Celsius to 150 degrees Celsius.
In mentioning this I've been trying to read up on how -ve voltages will be generated in order for the PIC to read -ve temperature values. Do you have any ideas as of how to enable measurement of -ve temperatures?
Also in terms of understanding the conversion of the ADC value to the Celsius value I've drafted the code below:
Code: |
#include<18F2580.h>
#fuses XT,PUT,NOBROWNOUT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=14400, parity=N, xmit=PIN_C6, rcv=PIN_C7, STREAM=HWAREUART, ERRORS)
#define LED_ONE PIN_B2
#define LED_TWO PIN_B3
unsigned int8 adc_value;
float received_voltage, temp_value, temp_conversion_constant = 0.01; // i.e. 1 degreee celcius == 10mV
void temp_sensor();
void temp_sensor() {
output_toggle(LED_ONE);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_4);
set_adc_channel(0);
adc_value = read_adc();
printf(HWAREUART,"%d", adc_value);
// Check if the ADC is done reading the voltage level from the temp sensor.
// If it is done then convert this voltage to the respective temp value.
if(adc_done()) {
// Convert the ADC value to voltage
received_voltage = adc_value * 0.00488281;
// Obtain temp value based on conversion constant
temp_value = received_voltage / temp_conversion_constant;
//printf(HWAREUART, "\f%3.2f", temp_value);
if(temp_value > 0) {
// Flash the DATA_LED once to confirm that the temp was read
output_high(LED_TWO);
delay_ms(1000);
output_low(LED_TWO);
delay_ms(1000);
}
}
}
void main() {
do {
temp_sensor();
delay_ms(2000);
} while (TRUE);
}
|
Any chance someone could look at the above and see if I'm on the right path i.e. in terms of then converting the ADC value to a Celsius value.
Regards,
Gaara. |
|
![](templates/subSilver/images/spacer.gif) |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Feb 11, 2014 9:47 am |
|
|
Be sure to connect the LM35 accordingly to measure -temps.
the datasheet should show a diagram with 2 diodes. if i remember correctly its figure 7 on the datasheet. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Tue Feb 11, 2014 10:00 am |
|
|
The LM35, is going to get complicated (a little...).
To read -ve temperatures, you'll have to 'offset' things. Either using an op-amp, and adding an offset to the output (so the PIC only receives +ve values), or doing a similar thing by running the LM35, off a 'ground', that is above the PIC's GND....
Unnecessary work.
Look at the LM335 instead. The big difference with this, is that the output voltage is scaled to represent Celsius, instead of Centigrade, so it gives 2.98v out at 0C. Keeps everything nice and +ve....
Comfortably covers your required temperature range.
Then key thing missing on your code:
#device adc=10
Then for the sort of accuracy that you can really get, forget fiddling around with float values.
Read the ADC value into a signed int16.
Then:
Code: |
reading=read_adc();
reading-=610;
reading/=2;
|
Ideally have a 'calibration' done when you set the system up, which takes the sensor reading at 0C, stores this in EEPROM, and uses it in place of the 610 above.
You then get simple integer degrees. The silly thing is that it will be in error by less than 0.5C at the ends of the scale, and take hundreds of times less maths.....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Tue Feb 11, 2014 10:30 am |
|
|
I've used the LM34/35 for over 2 decades but have gone 'digital', using the DS18B20PAR devices.
It's a viable option you should consider.When you get 'offset' working(opamp, diodes,etc.) and 'calibration' figured out you'll have invested a lot of time and a few coins. For pennies more the DS unit is overall better.
just an option to consider.
jay |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Feb 11, 2014 12:06 pm |
|
|
here is the essential problem you are still facing, if you want to use
an un-ampilfied,un-offset connection to the PIC ADC at 10 bits.
you have a 75 degree span, and the raw output of the LM335 or LM35 is
just 10mv/degree_C
that is a delta voltage change of just 750mv for your whole span.
Assuming
a 5V ADC reference, this is going to unfortunately map your whole span into just 154 bits of the 1024 you have. or appx 1/2 degree C resolution, with a APPX +/- 1 degree uncertainty .
one way to improve this is with an analog pre processor.
However the simpler,cheaper way is to upgrade your project to a 12BIT ADC PIC.
if the result has to be low cost, switching to a 12bit PIC in the 18F family might be the cheapest - and simplest way forward for you, as that one change will give you 1/8th degree resolution and a commensurate factor of four, reduction in the uncertainty of the result as well.
Last edited by asmboy on Tue Feb 11, 2014 3:00 pm; edited 2 times in total |
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Tue Feb 11, 2014 12:30 pm |
|
|
One advantage to the digital over the analog devices for sensing things is the ability to use them on a remote lead for sensing things a short distance away from the board/processor (it would be even nicer if the digital thingies appended a checksum on the end). Analog can work remotely, but it is tougher to make sure the reading you are getting is valid and not due to the sensor + oxidized connection resistance for example. Just a consideration.
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
Gaara
Joined: 10 Feb 2014 Posts: 11
|
|
Posted: Wed Feb 12, 2014 5:14 am |
|
|
Hi all,
Thank you for all the comments and suggestions.
@Gabriel:
Be sure to connect the LM35 accordingly to measure -temps.
the datasheet should show a diagram with 2 diodes. if i remember correctly its figure 7 on the datasheet.
I’ve had a closer look at the LM35 datasheet and indeed there’s a figure i.e. figure 18 which indicates two Vouts a +ve and –ve. Pardon the basic question but I assume this means connections to two analog pins e.g. AN0 and AN1 as opposed to one.
Here is my current connection between my LM35 and my PIC18F2580 which can only measure +ve temperatures - https://1d563b1a-a-62cb3a1a-s-sites.googlegroups.com/site/bgedsadownloads/Temp%20sensor%20schematic.png?attachauth=ANoY7cpNmq1Z54SyHh6GT41Tfa6CXpv5TdxswtwJ2JhKXHOc-LQKjnaWckhJkBBFQWop2gGhqmUoCJcvdMeUucw6hKt1ZvT93pyxrmc9mm1b9rrYXZibRrO2o9S09jbD7xqDuNftVSWpNVbPVpJmteLdcIT2qoY8L_jl3fy03Gn1LLMkpjtCR10XzrTDydL7NAhI1wZQMJKrr7hjumUGY1uLXp_HnCQGXaA9vzr_ynEYkiLCCOfCFZQ%3D&attredirects=0.
So regarding the use of the diode setup as per figure 18 on the LM35 datasheet, a query I have is the feeding of negative voltages to an analog pin of the PIC.
As per the datasheet, the maximum negative voltage I can feed into the PIC 18F2580 is -0.3v and hence was wondering from anyone’s experience if there are any side effects of connecting the two Vouts as per figure 18 of the LM35 datasheet to my PIC’s AN0 and AN1 pins?
@ttelmah:
The LM35, is going to get complicated (a little...).
To read -ve temperatures, you'll have to 'offset' things. Either using an op-amp, and adding an offset to the output (so the PIC only receives +ve values), or doing a similar thing by running the LM35, off a 'ground', that is above the PIC's GND....
Unnecessary work.
The above indeed sounds very tedious hence is this also the case if you were to use the setup I mentioned above i.e. as per figure 18 of the LM35 datasheet?
Look at the LM335 instead. The big difference with this, is that the output voltage is scaled to represent Celsius, instead of Centigrade, so it gives 2.98v out at 0C. Keeps everything nice and +ve....
Comfortably covers your required temperature range.
I’ve had a closer look at the LM335 datasheet. Firstly and apologies if this sounds trivial but following the setup as per figure 15 in the datasheet is it possible to use this setup measure both positive and negative temperatures and if possible does this mean the measurement will be taking place on the same PIC analog pin e.g. AN0
Unfortunately I currently have a limited access to new development components but I’m looking at getting in 2 LM335s in ASAP.
Then key thing missing on your code:
#device adc=10
Thanks. I’ve had a look at the CCS compiler help manual.
Then for the sort of accuracy that you can really get, forget fiddling around with float values.
Read the ADC value into a signed int16.
Sticking to the LM35 for now apart from the temperature scale factor I’ve declared the rest of my variables as signed int16. This can be seen in my code below:
Code: |
#include<18F2580.h>
#device adc=10
#fuses XT,PUT,NOBROWNOUT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=14400, parity=N, xmit=PIN_C6, rcv=PIN_C7, STREAM=HWAREUART, ERRORS)
#define LED_ONE PIN_B2
#define LED_TWO PIN_B3
signed int16 temp_value, adc_value, received_voltage;
float temp_scale_factor = 0.01; // i.e. 1 degreee celcius == 10mV
void temp_sensor();
void temp_sensor() {
output_toggle(LED_ONE);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_4);
set_adc_channel(0);
adc_value = read_adc();
//printf(HWAREUART, "%x", adc_value);
// Check if the ADC is done reading the voltage level from the temp sensor.
// If it is done then convert this voltage to the respective temp value.
if(adc_done()) {
// Convert the ADC value to voltage
received_voltage = adc_value * 0.00488281;
// Obtain temp value based on conversion constant
temp_value = received_voltage / temp_scale_factor;
printf(HWAREUART, "%x", temp_value);
}
}
void main() {
do {
temp_sensor();
} while (TRUE);
}
|
Then:
Code:
reading=read_adc();
reading-=610;
reading/=2;
Ideally have a 'calibration' done when you set the system up, which takes the sensor reading at 0C, stores this in EEPROM, and uses it in place of the 610 above.
You then get simple integer degrees. The silly thing is that it will be in error by less than 0.5C at the ends of the scale, and take hundreds of times less maths.....
Sorry if this sounds silly but I don’t get it when you mention which takes the reading at 0C . I definitely would like to add calibration into my code as I want the temperature value to be as accurate as possible.
@temtronic:
I've used the LM34/35 for over 2 decades but have gone 'digital', using the DS18B20PAR devices.
It's a viable option you should consider.When you get 'offset' working(opamp, diodes,etc.) and 'calibration' figured out you'll have invested a lot of time and a few coins. For pennies more the DS unit is overall better.
I’ve had a look at the DS18B20PAR datasheet http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf and was wondering for example using figure 4 in the datasheet as a connection guide does one need any connections between the DS18B20PAR and a PIC MCU to enable the measurement of negative temperatures.
Another question I had about the DS18B20PAR was in terms of calibaration, is calibrartion needed after reading the adc value using read_adc()
Also I’m looking into getting two units of the DS18B20PAR but as mentioned earlier unfortunately I currently have a limited access to new development components.
@asmboy:
Assuming
a 5V ADC reference, this is going to unfortunately map your whole span into just 154 bits of the 1024 you have. or appx 1/2 degree C resolution, with a APPX +/- 1 degree uncertainty .
one way to improve this is with an analog pre processor.
For the my ADC setup I’m using my Vdd which is 5V as my voltage reference hence my questions as per your highlighted comments above. Firstly how did you come about the 154 bits value? Also what does integrating an analog pre-processor entail? (sorry if both sound basic).
@gpsmikey:
Thanks for the suggestion and I’ll keep this in mind. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19383
|
|
Posted: Wed Feb 12, 2014 5:43 am |
|
|
The point about the 335, is that it gives 2.98v at 0C, rising at the same 10mV/degree as you go positive of this, and falling at 10mV/degree as you go -ve. So at -30C, it'll give 2.68v, while at +30C, it'll give 3.28v.
As I say, it is scaled in Celsius, not centigrade. So 0Centigrade=298Celsius. Hence the output is always +ve. 2.98v = 610 counts on the ADC. So if you subtract 610 from the input, you get an adc value that goes -ve below 0C, and +ve above.
Now the key thing is that with both the 35, and the 335, you only have 10mV/degree. So 70C=0.7v. The ADC gives 0 to 5v as 1024 counts (0 to 1023), so 0.7v, is just 1/7th the range of the ADC (154 counts)...
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Wed Feb 12, 2014 6:33 am |
|
|
You also need to know that VDD is NOT a good voltage reference.
1) depending on the regulator used it could easily be 4.95-5.05 volts.
2) current drawn will change the VDD value.
re 2) Anytime the PIC does more work, or an LED turns on,relay, etc. more current is drawn and a 'dip' in VDD will occour.While the PIC still runs fine, the ADC ref will drop from what you think it always is.This will give you a 'bad' reading as the alculations will be in error as Vref is not 5.000.
re: DS18B20PAR. -ve temps set a bit in the 'temp registers' and there's a couple 'drivers' in the code library here that show how to extract and display the temperature correctly.As for calibration, you could run simple test of 'ice water','boiling water' using a goodm known thermometer as a reference.
Depending on the application,you have to decide if accuracy of a wide range is critical( say +-.25*C) or not(+-1*C) is OK.Also how 'fine' a reading has to be(say +_.01*C or +-.1*C).I used the LM34 before PICs were around to control remote energy systems,with PICs I used them then switched to the DS digital sensors.It's one of the few 'upgrades' I've been more than happy with.
hth
jay |
|
![](templates/subSilver/images/spacer.gif) |
Gaara
Joined: 10 Feb 2014 Posts: 11
|
|
Posted: Wed Feb 12, 2014 7:03 am |
|
|
Hi Ttelmah,
Ah .. I see but just to confirm I fully understand using the LM335 with regards to my target range of -30 degrees Celsius to +45 degrees Celsius I'm I right in saying that the respective voltage range would be from 2.68v to 4.92v.
I believe this voltage range is fine with regards to absolute maximum rating of the analog pin on the PIC which is stated as Vdd+0.3v (my Vdd is 5.0).
In mentioning the above I also get what you mentioned earlier regarding the range 1/2 C accuracy which for now (especially as I then need to buy the LM335) I do not mind working with. Once I'm able to confirm the basics of my above posted code are working with the LM335 which I'm going to buy I'll then focus on improving the accuracy. Do you reckon this is a good approach?
I'll do my best to then buy the LM335 but in brief search I noticed the letter A and upon reading further my understanding is that the LM335A has an "Uncalibrated Temperature Error" of 1°c nominal, 3°c max while the non A version is 2°c nominal, 6°c max. Is this correct? Hence ideally I should buy the LM335A as it has lower error values.
Also I noticed in the datasheet in the basic setup as per figure 15 there's a resistor connected to one of the two pins of the LM335. To determine the resistor value I assume (and correct me if I'm wrong) the key thing would be to output a voltage value from the resistor that is is under the maximum input rating of the LM335. I'm I right to think this way?
Once again thanks for the insightful reply. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|