Paymaan
Starting Member
- Total Posts : 60
- Reward points : 0
- Joined: 2006/04/07 07:17:18
- Location: 0
- Status: offline
ADC conversion simple question :)
Hi Everybody, I am trying to use ADC in 18F452 (@20MHz) for the first time. THe source of voltage is a simple LM335Z Kelvin temperature sensor with a range of -40 to +100. As datasheet says, it should have about 2.98V at 25 centigrade, or 2.7315V at 0 degrees Celcius. The circuit uses the simplest method, the Vdd is connected to the pin2 (+ of the diode like sensor), and pin 3 (GND) is connected to GND, and Pin2 is connected to AN0 of 18F452. here is the code to read it: ---- int pjread_adc(void) { int result; // configure A/D convertor OpenADC( ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_1ANA_0REF, ADC_CH0 & ADC_INT_OFF ); Delay10TCYx( 5 ); // Delay for 50TCY ConvertADC(); // Start conversion while( BusyADC() ); // Wait for completion result = ReadADC(); // Read result CloseADC(); // Disable A/D converter return result; } -- The routine returns currently something around 625. and I have checked it by cooling and heating and it seems to work. Now after all these descriptions, and considering I am using the GND and VDD=5V as internal Vrefs, while the lowest possible V from sensor expected to be about 2.33 (10mv per degree, and 0 Celsius is 2.7315), I don't know how to correctly convert the number read to voltage, or to temperature, can anybody describe the correct formula in this case? Cheers,
|
Guest
Super Member
- Total Posts : 80500
- Reward points : 0
- Joined: 2003/01/01 00:00:00
- Location: 0
- Status: online
RE: ADC conversion simple question :)
2006/05/18 07:15:19
(permalink)
Although you are getting meaningful readings from the ADC, I suggest you to have 2 functions: init the ADC only once, at the start of your readings, and then simply get every reading, without calling CloseADC(). A reading of 625 for your setup suggests a room temperature of 32°C, is that the room temperature when you get a 625 reading? The conversion from the sensor 'Kelvin' output voltage to Celsius temperature would be: Tcelcius = (Vout - Vzero) / 10mV where Vzero is 2.7315V, Vout is the actual voltage reading, and Tcelsius is the equivalent temperature in celsius degrees. For example, if Vout is 3.051V, Tcelsius would be = (3.051 - 2.7315) / 10mV = 31.95°C Now, the ADC has the following ideal transfer function, for a right-justified ADRES, and 5V VREF: ADRES = Vin / ((Vref+ - Vref-) / 1024) => Vin / (5/1024) => Vin * 1024 / 5 => Vin * 204.8 So, our 3.051V would ideally be converted to: 3.051 * 204.8 = 624.84 => 624 The conversion of the ADRES code to celsius temperature would similarly be: Tdigital = (ADRES - Tdzero) / Td_1C where Tdzero is the ADC theoretical digital code for 2.7315V (559.41), and Td_1C is (2.048), the theoretical digital code for 1°C. So, our value 624 would evaluate to = 31.54°C. The error (0.41°C) is due to the quantization error of the LSb size of 4.883mV/LSb, meaning that for your 10mV/°C analog range, the ADC has a resolution of 0.4883°C/LSb. The above formula has fractional values for the Tdzero and Td_1C constants, and requires that you process it with floating point math, or with enough fractional length fixed point math, to avoid rounding errors. But you are one lucky guy, because if you do process that formula with integer math only, with the constants rounded to integer, you get the rounding bias to almost cancel each other. The rounded final values will have a 0.5°C non-linearity. That can be bad or not for your application, you have to decide. For example, if we evaluate the above formula entirely in integer it will become: Tdigital = (ADRES - 559) / 2 So, our value of 624 would be: = (624 - 559) / 2 => 32°C. Therefore, for your circuit, the above integer formula will get you a linear range of temperatures with an error of ±0.5°C. If 1°C accuracy is good for you, that is the simplest conversion formula that you could have: just need to get the ADRES value in 16bit, subtract 559 from it, and shift right one position.
|
Artic
Super Member
- Total Posts : 2288
- Reward points : 0
- Joined: 2004/06/17 06:21:59
- Location: Wales now in Sofia,BG
- Status: offline
RE: ADC conversion simple question :)
2006/05/18 07:58:26
(permalink)
Hi, Another problem you will see is ADC drift because you are using an internal Vref. (Internal Vref is dependant on the current value of Vdd) It is always good practice to use a "fixed" Vref (typcial values 2.5v or 4.096v). Using a fixed Vref ensures that all your hardwork is software is valid today and next week, etc. You can get some very good repeatable results from.. 1. Using fixed floating point maths (depending on the precision of the maths [typcially no more than 24 to 32 bit is required]) 2. Over-sampling of the ADC result (this technique should easy give you an additional 1 bit resolution) Another factor that will limit your design is the Sensor Response Time. There is no point in running the ADC at 1000's of samples per second - if your sensor has a dynamic rate of change of 10mV per second... Hope it helps Artic
|
Paymaan
Starting Member
- Total Posts : 60
- Reward points : 0
- Joined: 2006/04/07 07:17:18
- Location: 0
- Status: offline
RE: ADC conversion simple question :)
2006/05/18 08:22:16
(permalink)
j_doin, First thank you very much for detailed explanations, A reading of 625 for your setup suggests a room temperature of 32°C, is that the room temperature when you get a 625 reading? Although the cheap thermometer I have in hand might not be preious, but it seems the temperature at the point sensor is put was almost 32. Curently it shows 31/30, and ADC value is 621/622 while my voltmeter reads sensor in-circuit 3.03v. So I guess ADC is reading almost correctly. I used this formula before reading your reply: int t; signed short t1; t1 = (short)(t*(0.48828125)-273.15); Why I used that formula temporarily was that having 5000/1024 (to have it in milivolts), was making floating point problems. So tried to have a better number to not loose the important values. using fprintf(_H_USART, "%f", t1) is where I face a worst problem, and I guess it is because I am not yet enough experienced with C18. I simply can not print a floating point number to serial port. I hope you also help me with this, as all of type castings etc. didn't help either, the only way I got some results was to use %d for t1, which is obviously not the best way. The 0.5°C precision is quite enough for my purpose in this case, but being able to do it better helps in later cases ofcourse. So I guess the current question is: 1- How to calculate the formula and have it in Floating point format (float, etc.), 2- How can I fprintf a floating point in C18? 3- How can I convert a floating point to a string in C18?! to Artic: Thanks you too, the Vdd in this pproject is from a 7805, and I guess it can keep itself almost fixed, but I accept that having a external Vref will give much better precision. You can get some very good repeatable results from.. 1. Using fixed floating point maths (depending on the precision of the maths [typcially no more than 24 to 32 bit is required]) I am having problems with floating points at the moment, so my own preferred method is the same, 2. Over-sampling of the ADC result (this technique should easy give you an additional 1 bit resolution) Another factor that will limit your design is the Sensor Response Time. There is no point in running the ADC at 1000's of samples per second - if your sensor has a dynamic rate of change of 10mV per second... Can you please explain the Over-sampling? I only read the sensor each 500ms, so that is ok. Cheers,
|
Guest
Super Member
- Total Posts : 80500
- Reward points : 0
- Joined: 2003/01/01 00:00:00
- Location: 0
- Status: online
RE: ADC conversion simple question :)
2006/05/18 10:36:05
(permalink)
Some comments on your small conversion code: * short is not a floating point type. On C18, short is the same as int (16bit integer). * Your conversion expression uses floating point constants, so that makes C18 to evaluate the whole expression in floating point, and then the result value will be cast to int, discarding the fraction. To preserve the full floating point value, declare t1 as float. You can't print floating point with the printf() function family. There is a discussion on how to print flating point numbers at this thread: http://forum.microchip.com/fb.aspx?m=122316. I agree with Artic that if you use a external VREF regulator your accuracy will be better than using the internal VDD. You may want to use a 4.096V VREF, as it gives you exact 4mv quantization per LSb, and this will probably give you less rounding errors. Artic is also right about the oversampling. For example: if you read the ADC 4 times instead of a single time, and add the ADRES readings, you will have a 12bit reading, instead of a 10bit reading. If your signal has enough dithering noise at the LSb, you will get a meaningful 12bit value. If you are using a 4.096V, you will get 1mV/LSb, and will get a 0.1°C/LSb, in your case.
|
Paymaan
Starting Member
- Total Posts : 60
- Reward points : 0
- Joined: 2006/04/07 07:17:18
- Location: 0
- Status: offline
RE: ADC conversion simple question :)
2006/05/18 13:32:47
(permalink)
* short is not a floating point type. On C18, short is the same as int (16bit integer). You are right, I forget to menion I have also tried that with Float, but as printf didn't show anything, I thought there might be a problem with float casting, and changed it to short to see some output at first. Also thanks for explaining the over sampling, It will be for sure helpful for more precise conversions. The sensor I am using at the moment has only a 0.5°C precision so the current method seems to be enough. Now I am getting the voltage with 9 digits after point like this: fp_a=30.560943616 Which is amazing. You can't print floating point with the printf() function family. There is a discussion on how to print flating point numbers at this thread: http://forum.microchip.com/fb.aspx?m=122316. Thanks for your great hints also on printing the floating point number, and I didn't know printf can not print floats in C18, so it was the main problem in my case. Thanks alot, Cheers,
|
DSchabel
Super Member
- Total Posts : 1714
- Reward points : 0
- Joined: 2005/05/24 14:00:34
- Location: Western NY State
- Status: offline
RE: ADC conversion simple question :)
2006/05/18 14:11:50
(permalink)
ORIGINAL: Paymaan Also thanks for explaining the over sampling, It will be for sure helpful for more precise conversions. The sensor I am using at the moment has only a 0.5°C precision so the current method seems to be enough. Now I am getting the voltage with 9 digits after point like this: fp_a=30.560943616 Which is amazing. Using a 7805 as your voltage reference won't get you much in the way of accuracy, in your case. The voltage from this device is spec'd at +/-5%. A 5% error in your voltage reading can equate to a nearly 15 deg C error! Unless you have some way of calibrating out this voltage error, I'd encourage you in the strongest way to use a precision voltage reference, or some other way of measuring temperature.
|
Guest
Super Member
- Total Posts : 80500
- Reward points : 0
- Joined: 2003/01/01 00:00:00
- Location: 0
- Status: online
RE: ADC conversion simple question :)
2006/05/18 17:21:48
(permalink)
... or use a precision 5V regulator for VDD, like the LP2950ACZ-5.0, a 0.5% low-dropout precision regulator with the sme pinout as the LM78L05. Alternatively, you can use the LP2950-5.0 as a VREF+ source also. For a 0.5% application, this may be enough to have uncalibrated accuracy.
|
Paymaan
Starting Member
- Total Posts : 60
- Reward points : 0
- Joined: 2006/04/07 07:17:18
- Location: 0
- Status: offline
RE: ADC conversion simple question :)
2006/05/19 06:49:07
(permalink)
Using a 7805 as your voltage reference won't get you much in the way of accuracy, in your case. The voltage from this device is spec'd at +/-5%. A 5% error in your voltage reading can equate to a nearly 15 deg C error! Unless you have some way of calibrating out this voltage error, I'd encourage you in the strongest way to use a precision voltage reference, or some other way of measuring temperature. That could not be tolerated. Although my current 7805s never show such a differnece in voltage, but even an error half that is much. I checked the LP2950ACZ-5.0 datasheet, typical applications differs from 7805 and it only outputs 100mA, which is not much for the rest of circuit. On the other hand much Voltage Refrences are at 1.2, 2.5 or around those voltages, can you please suggest something above 4V, which is also high precision? And to have a better output, what about using LM135A/235A which have a much better uncalibrated accuracy? Cheers,
|
Guest
Super Member
- Total Posts : 80500
- Reward points : 0
- Joined: 2003/01/01 00:00:00
- Location: 0
- Status: online
RE: ADC conversion simple question :)
2006/05/19 07:24:31
(permalink)
ORIGINAL: Paymaan I checked the LP2950ACZ-5.0 datasheet, typical applications differs from 7805 and it only outputs 100mA, which is not much for the rest of circuit. Not much? What is your circuit that draws over 50mA? Is the PIC driving any high-current loads directly from its pins? On the other hand much Voltage Refrences are at 1.2, 2.5 or around those voltages, can you please suggest something above 4V, which is also high precision? I use the Analog Devices REF198 as VREF+ in my analog measurements applications. It is a 4.096V ±2mV guaranteed. That is a 12bit accuracy voltage reference. The nice thing about it is that you get a 4mV quantization at 10bits, and 1mV quantization at 4x oversampling. And to have a better output, what about using LM135A/235A which have a much better uncalibrated accuracy? If you want better precision, you can use the LM35A, a 10mv/°C linear sensor with 0V = 0°C. It is the best sensor from National analog temperature sensors family, with guaranteed min 0.5°C accuracy at 25°C, and a maximum of 1°C error at temperature extremes (-55°|+150°C). Its typical accuracy and max absolute nonlinearity is 0.25°C, and relative linearity is 0.08°C. The nice thing about the LM35 is that you can expand the sensor voltage range by using a precision OpAmp as a simple non-inverting amplifier, and have an output that is larger than 10mV/°C. With a 6V/V amplification factor you can have 60mV/°C, and have a range from 0°C to 68.2°C (if using a 4.096V VREF) with 10bits base resolution, or 0.0 66°C/LSb. You can make a high-resolution temperature acquisition system with that.
|
Paymaan
Starting Member
- Total Posts : 60
- Reward points : 0
- Joined: 2006/04/07 07:17:18
- Location: 0
- Status: offline
RE: ADC conversion simple question :)
2006/05/19 14:45:07
(permalink)
Not much? What is your circuit that draws over 50mA? Is the PIC driving any high-current loads directly from its pins? Well my board is self made, and here I have a 18F452 with 30+ IO ports to experiment with, and currently it drives my 2Wire LCD interface (fortunately without backlite at the moment) and an I2C bus with RTC already installed. I have not yet drived any high current load, but I am sure even 100 mA will be not enough in some experiments. I use the Analog Devices REF198 as VREF+ in my analog measurements applications. It is a 4.096V ±2mV guaranteed. That is a 12bit accuracy voltage reference. The nice thing about it is that you get a 4mV quantization at 10bits, and 1mV quantization at 4x oversampling. Thanks for suggestion, I will give it a try as soon as I can. If you want better precision, you can use the LM35A, a 10mv/°C linear sensor with 0V = 0°C. It is the best sensor f I wanted to work on LM35A at first, but I noticed it needs a negative supply for temperature below zero, and I have tried to keep things very simple so I learn things with PIC faster. So even now I am doing my best to choose the simplest method wherever possible. The first project after these experiments is about environment monitoring, so negative temeratures are naturally exist. LM335 has a 6 Deg Celcius Max error when uncalibrated, but still uses one supply, and counts in Kelvin (which is easy to convert to Celcius). and well I can even calibrate with 10K pot when essential. I thought using LM135A with a Max error of 1 Deg may eliminate the need for calibration work as well. Cheers,
|
Guest
Super Member
- Total Posts : 80500
- Reward points : 0
- Joined: 2003/01/01 00:00:00
- Location: 0
- Status: online
RE: ADC conversion simple question :)
2006/05/19 15:20:14
(permalink)
I see. In that case (a general-purpose board) I agree with you, use just the bare kelvin scale LM135. If you use the recommended REF198 and do a filtering of the analog input you can achieve 12bits of resolution, or 0.1°C. You must follow good analog design practices: good filtering for the VREF regulator, good filtering for the VREF line, quiet ground plane for the analog circuitry, good decoupling capacitors for the PIC, very close to every VDD/VSS pin. With a good analog circuit board, you can achieve noise of less than one LSb at 10 bits (noise < 4mV), just enough to have a little dithering. >>> added: For calibration, please do not use any potentiometers. If you have to calibrate, use software to compute the calibration constant from the ADC values read. Use at least 2 thermal stable points (water fusion and boiling points, for example), and correct the PVT values for your ambient pressure. Remember, these sensors are very slow, so you must allow for temperature stabilization.
post edited by j_doin - 2006/05/19 15:23:26
|
Paymaan
Starting Member
- Total Posts : 60
- Reward points : 0
- Joined: 2006/04/07 07:17:18
- Location: 0
- Status: offline
RE: ADC conversion simple question :)
2006/05/20 01:04:21
(permalink)
What about AD586 series instead of REF198? (I see I can obtain it faster), And thanks for nice hints for Analog, I really need them, as I am very unexperienced with Analog design. The only filtering I use at the moment is using 100nf capacitors at Vdd/Vss pins of ICs. Can you please also suggest a link on those topics to study? So you mean potentiometers add noise as well? Cheers,
post edited by Paymaan - 2006/05/20 01:05:50
|
Guest
Super Member
- Total Posts : 80500
- Reward points : 0
- Joined: 2003/01/01 00:00:00
- Location: 0
- Status: online
RE: ADC conversion simple question :)
2006/05/20 16:49:51
(permalink)
ORIGINAL: Paymaan What about AD586 series instead of REF198? (I see I can obtain it faster), The AD586 is a 5V VREF regulator, not a 4.096V. It is equivalent to the REF198 in terms of accuracy and stability, but you must pay attention to the suffix letter. Only the AD586M has a 2mV accuracy. You may also check other excellent voltage references: - MAX6341 (0.02%, 0.5ppm/°C)
- LT1461 (<0.04%, Low-Dropout)
- LT1019 (< 0.05%)
- ADR43x (ADR430, ADR431, ADR433, ADR434, ADR435, ADR439)
- LM4140
And thanks for nice hints for Analog, I really need them, as I am very unexperienced with Analog design. The only filtering I use at the moment is using 100nf capacitors at Vdd/Vss pins of ICs. Can you please also suggest a link on those topics to study? So you mean potentiometers add noise as well? Potentiometers are inherently innacurate devices. The rule is: what can be easily changed can easily uncalibrate. If you have software at your service, you should design analog circuitry with the most stable signals possible, and use software to calibrate the fixed offsets and gains of the circuit. For good analog sources of theory and practical advice:
|
Paymaan
Starting Member
- Total Posts : 60
- Reward points : 0
- Joined: 2006/04/07 07:17:18
- Location: 0
- Status: offline
RE: ADC conversion simple question :)
2006/05/22 01:09:55
(permalink)
j_doin, Thank you very much for the detailed explanations, I am trying to use your advices to improve my ADC reading, also studying the links you mentioned for better analog design. Cheers,
|