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 CCS Technical Support

Temperature Indicator, Math, Hair Loss
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

Temperature Indicator, Math, Hair Loss
PostPosted: Tue Jan 29, 2013 4:56 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jan 29, 2013 5:56 pm     Reply with quote

See if this helps:
http://www.ccsinfo.com/forum/viewtopic.php?t=48263&start=3

And please don't write function names in ALL CAPS. The C standard
is for #define'd constants to be that way, but not function names.
It makes the code harder to read.
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Wed Jan 30, 2013 3:17 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 30, 2013 4:49 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 30, 2013 5:15 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jan 30, 2013 8:17 pm     Reply with quote

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. Smile 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

View user's profile Send private message

PostPosted: Thu Jan 31, 2013 8:43 am     Reply with quote

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: 19504

View user's profile Send private message

PostPosted: Thu Jan 31, 2013 9:49 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jan 31, 2013 2:21 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jan 31, 2013 2:52 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jan 31, 2013 3:30 pm     Reply with quote

I'd be looking at the register settings.

Mike
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 01, 2013 11:54 pm     Reply with quote

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: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 02, 2013 6:16 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Feb 10, 2013 7:58 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 07, 2013 9:58 pm     Reply with quote

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!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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