|
|
View previous topic :: View next topic |
Author |
Message |
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
Temperature Indicator, Math, Hair Loss |
Posted: Tue Jan 29, 2013 4:56 pm |
|
|
CCS PCM C Compiler, Version 4.132
PIC 16LF1828
I've been inside AN1333 for 48 hours now and I'm questioning my sanity. Given an ambient temperature measured at my work bench I've calculated what I "expect" the ADC to read from the temperature indicator. I understand it isn't accurate and in fact this is part of the process to perform the single point calibration detailed inside of AN1333.
The following formulas, from AN1333, were used to calculate the "ideal adc result":
Code: | Ambient Temperature: 21C(measured with a multimeter on bench)
VDD: 3.292V Regulated
ADC VREF: VDD
Vt = 0.659 - ((Temperature + 40) * (0.00132))
Vt = 0.57848
Vtemp = VDD - (4*Vt)
Vtemp = 0.97808
ADC = (Vtemp * 1023) / VREF
ADC = 303(truncated)
|
I added a function to display the binary value of what the ADC is reading via two LEDs. The equivalent decimal value I'm getting is 187 which is what I would have expected if it were -50C. I have tried this with 3 different pics and all 3 yield a similar result.
I understand the internal temperature indicators aren't very accurate, but I really think I've made a mistake in my calculations that I haven't seen yet. Any pokes or suggestions would be appreciated.
Code: |
#include <16LF1828.h>
#DEVICE adc = 10
#use delay (internal = 8MHz)
#FUSES INTRC_IO, NOWDT, PUT, NOMCLR, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT, NOCLKOUT, NOIESO, NOFCMEN, NOWRT, NOSTVREN, PLL_SW
#define RED_INDICATOR_PIN PIN_C6
#define GREEN_INDICATOR_PIN PIN_C7
#define BOOST_FEEDBACK_LO PIN_A5
#define BOOST_FEEDBACK_HI PIN_C2
#define BOOST_ENABLE_PIN PIN_C5
#define TRIS_A_LO_BOOST 0b00011100
void display_binary_value(unsigned int16 value)
{
static unsigned int8 byte_bit = 9;
//GREEN = 1, RED = 0, DISPLAYS 10 bit integer with LEDs, MSB first
if(bit_test(value, byte_bit))
OUTPUT_HIGH(GREEN_INDICATOR_PIN);//Bit = 1
else
OUTPUT_HIGH(RED_INDICATOR_PIN);//Bit = 0
DELAY_MS(500);
OUTPUT_LOW(GREEN_INDICATOR_PIN);
OUTPUT_LOW(RED_INDICATOR_PIN);
if(byte_bit)
{
byte_bit--;
DELAY_MS(500);
}
else
{
byte_bit = 9;
DELAY_MS(1500);
}
}
void main(void)
{
OUTPUT_A(0x00);
OUTPUT_B(0x00);
OUTPUT_C(0x00);
SETUP_OSCILLATOR(OSC_8MHZ | OSC_INTRC | OSC_PLL_OFF);
/*These values are hardware specific to enable the voltage regulator*/
SET_TRIS_A(TRIS_A_LO_BOOST);
OUTPUT_HIGH(BOOST_FEEDBACK_HI);
OUTPUT_HIGH(BOOST_FEEDBACK_LO);
OUTPUT_HIGH(BOOST_ENABLE_PIN);
ENABLE_INTERRUPTS(GLOBAL);
ENABLE_INTERRUPTS(PERIPH);
DELAY_MS(100);
SETUP_DAC(DAC_OFF);
SETUP_VREF(VREF_OFF | VREF_COMP_DAC_OFF | VREF_ADC_OFF | TEMPERATURE_INDICATOR_ENABLED | TEMPERATURE_RANGE_HIGH);
SETUP_ADC(ADC_CLOCK_DIV_8);
SETUP_ADC_PORTS(NO_ANALOGS | VSS_VDD);
SET_ADC_CHANNEL(TEMPERATURE_INDICATOR);
DELAY_MS(10);
while(TRUE)
{
READ_ADC(ADC_START_ONLY);//start the conversion
while(!ADC_DONE())//wait until conversion is complete
TRUE;
display_binary_value(READ_ADC(ADC_READ_ONLY));
}//END OF WHILE LOOP
}//END OF MAIN
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Wed Jan 30, 2013 3:17 pm |
|
|
forgive me for being dense, but I am not sure what I'm supposed to be seeing in the post you linked to.
I put all function names in lower case to improve readability. I also added an extra while loop to ensure that value displayed by my leds is only the most recent adc conversion. I also tried running at 4MHZ.
Code: |
#include <16LF1828.h>
#DEVICE adc = 10
#use delay (internal = 4MHz)
#FUSES INTRC_IO, NOWDT, PUT, NOMCLR, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT, NOCLKOUT, NOIESO, NOFCMEN, NOWRT, NOSTVREN, PLL_SW
#define RED_INDICATOR_PIN PIN_C6
#define GREEN_INDICATOR_PIN PIN_C7
#define BOOST_FEEDBACK_LO PIN_A5
#define BOOST_FEEDBACK_HI PIN_C2
#define BOOST_ENABLE_PIN PIN_C5
#define TRIS_A_LO_BOOST 0b00011100
int1 display_binary_value(unsigned int16 value)
{
int1 temp = 1;
static unsigned int8 byte_bit = 9;
//GREEN = 1, RED = 0, DISPLAYS 10 bit integer with LEDs, MSB first
if(bit_test(value, byte_bit))
output_high(GREEN_INDICATOR_PIN);
else
output_high(RED_INDICATOR_PIN);
delay_ms(500);
output_low(GREEN_INDICATOR_PIN);
output_low(RED_INDICATOR_PIN);
if(byte_bit)
{
byte_bit--;
delay_ms(500);
}
else
{
byte_bit = 9;
delay_ms(1500);
temp = 0;
}
return temp;
}
void main(void)
{
output_a(0x00);
output_b(0x00);
output_c(0x00);
setup_oscillator(OSC_4MHZ | OSC_INTRC | OSC_PLL_OFF);
/*These values are hardware specific to enable the voltage regulator*/
set_tris_a(TRIS_A_LO_BOOST);
output_high(BOOST_FEEDBACK_HI);
output_high(BOOST_FEEDBACK_LO);
output_high(BOOST_ENABLE_PIN);
//enable_interrupts(GLOBAL);
//enable_interrupts(PERIPH);
delay_ms(100);
setup_dac(DAC_OFF);
setup_vref(VREF_OFF | VREF_COMP_DAC_OFF | VREF_ADC_OFF | TEMPERATURE_INDICATOR_ENABLED | TEMPERATURE_RANGE_HIGH);
setup_adc(ADC_CLOCK_DIV_8);
setup_adc_ports(NO_ANALOGS | VSS_VDD);
set_adc_channel(TEMPERATURE_INDICATOR);
delay_ms(10);
while(TRUE)
{
read_adc(ADC_START_ONLY);//start the conversion
while(!adc_done())//wait until conversion is complete
TRUE;
while(display_binary_value(read_adc(ADC_READ_ONLY)))
TRUE;
}//END OF WHILE LOOP
}//END OF MAIN |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jan 30, 2013 4:49 pm |
|
|
Quote: | I am not sure what I'm supposed to be seeing in the post you linked to. |
You are trying to read the PIC's internal temperature indicator.
The linked code is an example of how to do that. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Jan 30, 2013 5:15 pm |
|
|
Can't argue with your logic, but two things strike me:-
1) AN1333 recommends you only use HIGH mode for Vref above 3V6.
2) Your method for reading the ADC looks rather convoluted, why not use an LCD or RS232?
Mike |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Wed Jan 30, 2013 8:17 pm |
|
|
PCM:
-I understand now. Do you see something at fault with the way my code is trying to obtain that data? Aside of the method of displaying the data, and that I added code to poll the go_done bit, I haven't spotted a difference in operations. Please advise. I do not mean to be obtuse so I will try your code when I get back to the bench.
Mike:
-I'm hoping your first point leads me to my problem. I also spotted a table in the 16LF1828 datasheet that said those same constraints on the range setting. According to my calculations, with a Vdd of 3.292V at -40C the voltage produced by the temp indicator is 0.656V. At 85C it is 1.316V. These are both well with in the range imposed by my ADC voltage reference.
The formulas I used to calculate those numbers are:
Code: |
Vt = 0.659 - ((Temperature + 40) * (0.00132))
Vt = 0.57848
Vtemp = VDD - (4*Vt)
Vtemp = 0.97808 |
-RE my readout: Convoluted, maybe. Inefficient, most definitely. Truth be told I don't have the foggiest idea how to use an LCD to read data. But my picdem4 board just arrived today so perhaps I will dig in.
From AN1333 Page 2:
Quote: |
Care needs to be taken in selecting a mode, since Vt
may be as high as 0.75V at low temperatures... |
In my calculation, using the formula above, entering a temperature of -40C(the lowest operating temperature listed in datasheet) I calculate Vt at 0.659V. I have to enter -109 to get a Vt at 0.75V. Does that seem right?
Grasping at straws. PCM, I'll try your code, and Mike hopefully I don't have much trouble getting the LCD running.
Thanks |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Jan 31, 2013 8:43 am |
|
|
CCS provides sample code for both RS232 and LCD, so with your new board you should be OK.
Like I said before I can't fault you logic.
Without knowing more about what goes on inside the PIC we can only guess at why they need the voltage overhead to drive the temperature measuring system.
The app note and data sheet are both saying the same.
My intuition tells me you should be getting an error the other way (i.e. reading too hot rather than cold)
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Thu Jan 31, 2013 9:49 am |
|
|
Remember the pull down in the temperature sensor circuit, is a current sink. This has a minimum operating voltage, which is dependant on the supply. Hence the minimum working voltages. Like you, I'd probably have expected the voltage to go to high when this stops working, but your behaviour suggests this isn't the case.
Best Wishes |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Thu Jan 31, 2013 2:21 pm |
|
|
Trying this at a higher voltage:
Vdd set at 4.56 Volts, regulated benchtop supply.
Decimal result from ADC read of Temperature Indicator: 409.
Expected result from application note: 503.
Still having this consistent offset. |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Thu Jan 31, 2013 2:52 pm |
|
|
Something else to chew on here.
I just changed a line of code to:
Code: |
setup_vref(TEMPERATURE_RANGE_HIGH | TEMPERATURE_INDICATOR_DISABLED ); |
And I get the same result as if I type in "TEMPERATURE_INDICATOR_ENABLED" |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Jan 31, 2013 3:30 pm |
|
|
I'd be looking at the register settings.
Mike |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 01, 2013 11:54 pm |
|
|
I think the reason for the temperature offset between AN1333A and
your test results is due to the variation between PIC families, production
batches, and individual PICs.
Look at Figure 2 on the first page of AN1333A:
http://ww1.microchip.com/downloads/en/AppNotes/01333A.pdf
This is a graph of the forward voltage drop vs. temperature, of an
individual diode in a single 16F1937. The lowest temperature that
they measured was -40 degC, and they measured 0.659v as the drop.
That's where they got the magic number of 0.659 for their equation.
But this number is really only good for the one PIC that they tested.
For example, I tested a 16F1824 which is in the same family as your
16F1828. With a Vdd of 5v and at 27 degC, I got an ADC output of 476.
The ADC measures the voltage drop across the current source, not
the diodes. So you have to calculate the drop across the diodes:
(476/1023) * 5v = 2.33v, which is the drop across the current source.
So the drop across the four diodes is then 5.0v - 2.33v = 2.67v.
The voltage drop across one diode is 2.67v / 4 = 0.668v and that's
at 27 degC, which is close enough to their test condition of 25 degC.
Note to Ttelmah: I am using 1023 because that's what they use in
AN1333A. I'm doing it for reasons of consistency.
Look at the graph in Figure 2 in AN1333A. They measured 0.5735v
at 25 degC. But I measured 0.668v at 27 degC. That's a huge
difference in the center voltage between the two PICs. In fact, my
center voltage value of 0.668v is about what they measured at -40 degC.
This explains the huge temperature offset that you're seeing. And not
only is there an offset, but the slope could be different as well.
So basically, each PIC needs to be calibrated, and the calibration value
needs to be stored in eeprom. They explain this in the rest of AN1333A.
Then whenever you read the ADC and calculate the temperature, you
use the calibration value to adjust the result.
Here's the test program that I used to study this:
Code: |
#include <16F1824.H>
#device adc=10
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
//==========================================
void main()
{
int16 adc_result;
float tempC;
float tempF;
printf("Start:\n\r");
setup_vref(TEMPERATURE_INDICATOR_ENABLED | TEMPERATURE_RANGE_HIGH);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(TEMPERATURE_INDICATOR);
delay_us(200);
while(1)
{
adc_result = read_adc();
printf("%lu \n\r", adc_result);
// tempC = ((0.659 - ( (5/4.0) * (1 - (adc_result/1023.0)) )) / .00132) - 40;
tempC = ((0.756 - ( (5/4.0) * (1 - (adc_result/1023.0)) )) / .00132) - 40;
//tempF = (tempC * 1.8) + 32;
printf("TempC = %5.1f \n\r", TempC);
//printf("TempF = %5.1f \n\r", TempF);
delay_ms(1000);
}
}
|
The 0.756 in the equation above is my attempt to calibrate the equation
to fit my PIC. The delta between -40 degC and 27 degC (my center
temperature, as tested) is 67. I used the same slope value of .00132
as in AN1333A just because it's easier. So 67 * .00132 = .08844
Then .08844v + .668v = 0.756v. That's my calculated number for
the left side of the graph in Figure 2 (the voltage drop for -40 degC).
With that calibration value, the displayed room temperatures are
pretty close to a thermometer that I have in the room.
The equation above is the same as in AN1333A, but converted to C.
I realize it could be simplified and made to run much faster. I left it
unchanged, just to make it easier to compare it to the Appnote. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9240 Location: Greensville,Ontario
|
|
Posted: Sat Feb 02, 2013 6:16 am |
|
|
Ok, I have to ask...aside from the 'mind challenge' of getting it to work what's the real purpose of using the internal temperature sensor?
Seems like a HUGE amount of time (and $$) has, is and will be spent on this when a simple external sensor ie: MCP9701a or DS18S20 could be bought, installed and code for far less time and money.
I'm all for tweaking out a design but even I have a limit!
Maybe the OP can explain the reason to me ....
jay |
|
|
stinky
Joined: 05 Mar 2012 Posts: 99 Location: Central Illinois
|
|
Posted: Sun Feb 10, 2013 7:58 pm |
|
|
Jay, My real purpose for using the internal temperature sensor is coarse temperature indications. My application does not need super accurate temp info but it does need to know arbitrary hot and cold points. Your comment is quite valid and I wish I were simply using an external sensor but as of yet my time invested has not warranted a BOM change. Like I said, I don't need anything more than coarse hot and cold points.
PCM:
I believe you are quite correct. I thought there would be variance in those threshold voltages but I incorrectly assumed that they would be at or around the given forward voltage on the AN1333 test pic. Thanks for catching my mistake.
Everyone:
Thanks for your input. Invaluable members in this forum. |
|
|
harlequin2
Joined: 11 Jun 2011 Posts: 21
|
|
Posted: Thu Mar 07, 2013 9:58 pm |
|
|
I'm very pleased to have read through this forum, it makes me feel a little less stupid! I, also, have been reading through AN1333 and wondering why I/they bothered.
I happen to have a small board with a 16F1826 on board driving an LCD and I thought I would turn it into a digital thermometer, just out of interest. Its not easy to make any hardware changes, but the software, well, that can do anything!
My plan also is to power it with 3 x 1.5 AA cells (the lcd works down to 3 v) and make it work forever by putting it to sleep and waking up every so many minutes, doing a temp measurement and displaying it.
I wrestled with AN1333 and I think I see how to do it all, except for measuring Vdd. I guess one would set the adc to measure ref-lo = FVR, ref-hi = Vdd and select FVR as the input channel? I'm not sure! |
|
|
|
|
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
|