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

16f877a temperature sensor not working!!

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



Joined: 17 Oct 2005
Posts: 68
Location: Brisbane

View user's profile Send private message

16f877a temperature sensor not working!!
PostPosted: Wed Feb 08, 2006 3:13 am     Reply with quote

I have connected PORTA PIN_A0 to LM335 which is connected to 5v through a 2020 ohms resistor,then grounded as required.The following is the code.it's giving wrong results. please have a look and help me out.ti's frustrating me coz i'm suppose to woprk on the date callender by now since the timer is working perfectly
Code:
#include "C:\Program Files\PICC\Examples\pic16f88.h"
#include <lcd_driver.c>
//#include <kel_functions.c>
//extern GLOB_clock;
//void ADC_RESULT(void);
//#int_ADAD_isr(){}
struct time {
               int8  hrs;
               int8  mins;
               int8  secs;
               int16 mSec;
               long int val;
               unsigned int8 ADC_Results;
               float Temp_deg;
               }GLOB_clock={15,58,45,0,0,0,0};

void ADC_RESULT(void);
#int_TBE
TBE_isr()
{

}

#int_RDA
RDA_isr()
{

}

#int_TIMER0
TIMER0_isr()
{
    static int16 tick=0;
    static int1 toggle=0;
     //set_timer0(96);
     tick+=256;   //   set_timer0(206); 20 mhz clock, no prescaler, set timer 0 to overflow in 35us
                    // 256-(.001024/(4*256/20000000))
   if(toggle) {
         toggle=0;
         GLOB_clock.ADC_Results=read_adc(ADC_READ_ONLY);
         }
         else {
         toggle=1;
         read_adc(ADC_START_ONLY);
       }
   if(tick>3125) {  //2500){
         tick-=3125;
         if(++GLOB_clock.mSec>=25)  {    //1000){
            GLOB_clock.mSec-=25;        //1000;
            if(++GLOB_clock.secs>=60) {
               GLOB_clock.secs=0;
               if(++GLOB_clock.mins>=60) {
                  GLOB_clock.mins=0;
                  if(++GLOB_clock.hrs>=24) {
                  GLOB_clock.hrs=0;
                  }
               }
            }
         }
   }
}



void main()
{

   //char cnt;
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_32);    //ADC_CLOCK_INTERNAL//SET adc conversion clock speed
                                   //TAD(per bit)=1/20Mhz X 32 = 0.16us ;Requires min. 12 TAD for 10 bit
                                   //Min. conversion time approx. 2us
   set_adc_channel(0);             //Set ADC channel to port0(pin 2,AN0).
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
   // setup_psp(PSP_DISABLED);setup_spi(FALSE);setup_timer_1(T1_DISABLED);setup_timer_2(T2_DISABLED,0,1);
  // setup_comparator(NC_NC_NC_NC);setup_vref(FALSE);enable_interrupts(INT_AD);/ enable_interrupts(INT_TBE);enable_interrupts(INT_RDA);

   lcd_init();
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);             //printf("Sampling adc"

   lcd_gotoxy(2,1);
   lcd_putc("\fSampling....");
   delay_ms(1000);
   lcd_putc("\f");

while(1)
   {
   ADC_RESULT();
   delay_ms(200);
   }

}

void ADC_RESULT(void){
     //static char cnt;
   static int32 avgsum;
   static int16 adcval;
   static int8 tim_12_hr;
   struct time local_clock;   
   memcpy(&local_clock,&GLOB_clock, sizeof(struct time));
   avgsum+=local_clock.ADC_Results;
   adcval=avgsum/8;                                       //Average value- using/8 since in binary, this is quicker
   avgsum-=adcval;
   
   //Displaying time here
   if((local_clock.hrs)>=13)  tim_12_hr=(local_clock.hrs)-12;
   else tim_12_hr=local_clock.hrs;
   lcd_gotoxy(4, 1);   //lcd_putc("LCD Ready...");
   printf(LCD_PUTC,"%02d:%02d:%02d\n",tim_12_hr,local_clock.mins,local_clock.secs);

   lcd_gotoxy(12, 1);
   if(local_clock.hrs>11) lcd_putc("PM");

   else   lcd_putc("AM");
   
    //local_clock. ADC_Results=(local_clock.val/=10);
     lcd_gotoxy(4,2);
    local_clock.Temp_deg = ((adcval - 559L)/2);   //Temp_Kelvin = (Temp_degrees + 273.15); Temp_Kelvin =((((float)val*5)/1024)-273.15);
    printf(LCD_PUTC," %2ld %2.1f\n\r",adcval,local_clock.Temp_deg);
    //printf(LCD_PUTC," %2u %2.1f\n\r",local_clock.ADC_Results,local_clock.Temp_deg);
}


The results are very frustrating indeed and are shown below:
Code:
dcval=89
local_clock.Temp_deg=32533.0 degrees at air cond.condition which is suppose to be 25 degrees

I just wonder whether the formula is the right one:
Code:
local_clock.Temp_deg = ((adcval - 559L)/2);

also which is the compiler not accepting the
Code:
 printf"%2u",adcval)?
//adcval is declared as int16...

please help me out.i'm stressing it up.i will aprreciate..
cheers
Ttelmah
Guest







PostPosted: Wed Feb 08, 2006 3:44 am     Reply with quote

Adcval, is a _long_. You need %2Lu.
I don't see where you are setting #device ADC=10?. Without this, you will get an 8bit ADC result, and a value that is 1/4 what it should be.
The conversion, is relatively simple. Your ADC, has 5/1024 volts per 'step'. The chip should give 2.73v at 0C. Hence you will get a reading of 2.73/(5/1024) = 559.
Then if the reading was (say) 20C, the chip should give 2.93v. This would give a reading of 2.93/(5/1024) = 600. Using the formula, gives (600-559)/2 = 20.
One big caveat, adcval, will need to be a _signed_ int16, if the value can ever be below 0C.
Have you checked that the voltage on the ADC input pin, really is what it should be?.
Are you sure the constant to select AN0,is 'AN0' on your compiler?. On the 16F88, the ADC selection, is different from most chips, with the ability to select individual ADC inputs (most chips only allow you to select certain 'patterns' of pins). Because of this, the ADC definition constants are non-standard, and 'sAN0' is needed to select the AN0 channel in 'setup_adc_ports'.

Best Wishes
rwyoung



Joined: 12 Nov 2003
Posts: 563
Location: Lawrence, KS USA

View user's profile Send private message Send e-mail

PostPosted: Wed Feb 08, 2006 8:25 am     Reply with quote

Quote:
#include "C:\Program Files\PICC\Examples\pic16f88.h"
and your subject line says you are using a 16F877a?
_________________
Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month!
kel



Joined: 17 Oct 2005
Posts: 68
Location: Brisbane

View user's profile Send private message

16F887a temperature sensor not working!!
PostPosted: Wed Feb 08, 2006 11:05 pm     Reply with quote

Thanks alot gusy for your time.Here is the code with the header.I'm not using Pic16f88 but pic16f877a.
Code:
#include <16f877a.h>
#device *=16
#device adc=10
#fuse HS,NOWDT,NOPROTECT,NOLVP,NOPUT
#use dleay(clock=20000000)
#include <lcd_driver.c>

struct time {
               int8  hrs;
               int8  mins;
               int8  secs;
               int16 mSec;
               int16 adcvalz;
               float Temp_deg;
               }GLOB_clock={15,58,45,0,0,0,0};

void ADC_RESULT(void);
#int_TBE
TBE_isr()
{

}

#int_RDA
RDA_isr()
{

}

#int_TIMER0
TIMER0_isr()
{
    static int16 tick=0;
    static int1 toggle=0;
     //set_timer0(96);
     tick+=256;   //   set_timer0(206); 20 mhz clock, no prescaler, set timer 0 to overflow in 35us
                    // 256-(.001024/(4*256/20000000))
   if(toggle) {
         toggle=0;
         GLOB_clock.adcvalz=read_adc(ADC_READ_ONLY);
         }
         else {
         toggle=1;
         read_adc(ADC_START_ONLY);
       }
   if(tick>3125) {  //2500){
         tick-=3125;
         if(++GLOB_clock.mSec>=25)  {    //1000){
            GLOB_clock.mSec-=25;        //1000;
            if(++GLOB_clock.secs>=60) {
               GLOB_clock.secs=0;
               if(++GLOB_clock.mins>=60) {
                  GLOB_clock.mins=0;
                  if(++GLOB_clock.hrs>=24) {
                  GLOB_clock.hrs=0;
                  }
               }
            }
         }
   }
}



void main()
{

   //char cnt;
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_32);    //ADC_CLOCK_INTERNAL//SET adc conversion clock speed
                                   //TAD(per bit)=1/20Mhz X 32 = 0.16us ;Requires min. 12 TAD for 10 bit
                                   //Min. conversion time approx. 2us
   set_adc_channel(0);             //Set ADC channel to port0(pin 2,AN0).
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
   // setup_psp(PSP_DISABLED);setup_spi(FALSE);setup_timer_1(T1_DISABLED);setup_timer_2(T2_DISABLED,0,1);
  // setup_comparator(NC_NC_NC_NC);setup_vref(FALSE);enable_interrupts(INT_AD);/ enable_interrupts(INT_TBE);enable_interrupts(INT_RDA);

   lcd_init();
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);             //printf("Sampling adc"

   lcd_gotoxy(2,1);
   lcd_putc("\fSampling....");
   delay_ms(1000);
   lcd_putc("\f");

while(1)
   {
   ADC_RESULT();
   delay_ms(200);
   }

}

void ADC_RESULT(void){
     //static char cnt;
   static int32 avgsum;
   static int16 adcval;
   static int8 tim_12_hr;
   struct time local_clock;   
   memcpy(&local_clock,&GLOB_clock, sizeof(struct time));
   avgsum+=local_clock.adcvalz;
   adcval=avgsum/8;                                       //Average value- using/8 since in binary, this is quicker
   avgsum-=adcval;
   
   //Displaying time here
   if((local_clock.hrs)>=13)  tim_12_hr=(local_clock.hrs)-12;
   else tim_12_hr=local_clock.hrs;
   lcd_gotoxy(4, 1);   //lcd_putc("LCD Ready...");
   printf(LCD_PUTC,"%02d:%02d:%02d\n",tim_12_hr,local_clock.mins,local_clock.secs);

   lcd_gotoxy(12, 1);
   if(local_clock.hrs>11) lcd_putc("PM");

   else   lcd_putc("AM");
   
    //local_clock. ADC_Results=(local_clock.val/=10);
     lcd_gotoxy(4,2);
    local_clock.Temp_deg = ((adcval - 559L)/2);   //Temp_Kelvin = (Temp_degrees + 273.15); Temp_Kelvin =((((float)val*5)/1024)-273.15);
    printf(LCD_PUTC," %2ld %2.1f\n\r",adcval,local_clock.Temp_deg);
    //printf(LCD_PUTC," %2u %2.1f\n\r",local_clock.ADC_Results,local_clock.Temp_deg);
}

Ttelmah mate, you have made it more clearer through that simple example.Unless if the problem is with #device *=16 which is suppose to use full ram.I have check the voltage on pin_A0 and it's 2.987V at room temperature.
AN0 HAS BEEN DEFINED IN THE HEADER FILE AS:
Code:
#define AN0     0X0E
and i'm not using any refernce voltage,could this be the source of the problem?
Come thanks


Last edited by kel on Thu Feb 09, 2006 2:29 am; edited 1 time in total
kel



Joined: 17 Oct 2005
Posts: 68
Location: Brisbane

View user's profile Send private message

It's working but printf() function seems to have a bug!!
PostPosted: Thu Feb 09, 2006 2:02 am     Reply with quote

The printf() function for the following code does give wierd two decimal places .What could be the results.The temperature counts up really fast and then settle at 20.07.0 which is suppose to be 20.1 deg.this then leaves a garbage of .70.0!!!
Code:
adcval=600->correct.
local.tem_deg=>20.070.0 incorrect due to two decimal points placed

What can i do since the printf("%2.1F",local.clock.Temp_deg) gives correct temperature plus garbadge???i.e.",
Code:
local.clock.Temp_deg=20.07.0

what can i do about the temperature counting up really fast? coz a thermometer on a turn on of power supply cannot count and settled.It has to settled as soon as the power is on!!!
please help....
Rolling Eyes
Ttelmah
Guest







PostPosted: Thu Feb 09, 2006 4:57 am     Reply with quote

On the startup speed, what you do, is to 'preload' the sum register, on wakeup. This then ensures that the system starts up fast, but with a 'non averaged' first reading. So have a flag in the 'ADC_RESULT' routine called 'first'. make it static, and have it wake up as 'true'. Then if this is true', set avgsum, to the first reading*8, and set it to false. When it is false, proceed as normal. This way, the sum will immediately be loaded with the first value.
However this will only work, if you can guarantee that a reading has already been taken, the first time you call the routine. This is going to take quite a time, since you have slowed the interrupt right down. You have set the prescaler to 64, which means the interrupt will only be being called 305 times per second. It takes two calls to the interrupt before the ADC value is available. You have quite a long delay (normally 15mSec) in the LCD_INIT code, so if you move this to after starting the interrupts, then the ADC value ought to be ready for you.
You will need to recalculate your counter in the interrupt. Because you have changed the prescaler, the timings will be wrong.
There is not a problem with the printf. The problem is that you are not clearing stuff left on the screen. If (for instance), the value wakes up as 100C, and is written to the screen as:
100.0

and the value then changes to 1C:
1.0

The screen will show:
1.0.0

Because the old data has just been overwritten. You need to either clear the screen, use a fixed width numeric output, or have the value written with a few trailing zeros, to gt rid of the remaining data on the display.

Best Wishes
kel



Joined: 17 Oct 2005
Posts: 68
Location: Brisbane

View user's profile Send private message

PostPosted: Thu Feb 09, 2006 8:57 pm     Reply with quote

Quote:
You have set the prescaler to 64, which means the interrupt will only be being called 305 times per second. It takes two calls to the interrupt before the ADC value is available. You have quite a long delay (normally 15mSec) in the LCD_INIT code, so if you move this to after starting the interrupts, then the ADC value ought to be ready for you.


changing the prescaler to Div_2 and using 2500,000 (2500 & 1000 in the if statement) meaning the interrupt occurs every 0.1024 ms does not stop the counter counting up.
the
Code:
if(firts){avgsum=local_clock.adcvalz;first=false;}
speed it up a lill bit.
i've tried everything to clear the screen but with no success.the trailing zeros does not sound to be a good design especially if you wana show the temperature.
Quote:
You have quite a long delay (normally 15mSec) in the LCD_INIT code, so if you move this to after starting the interrupts, then the ADC value ought to be ready for you.

what do you want me to move after starting interrupts?
Here is the modified code..
Code:
#include <16f877a.h>
#device *=16
#device adc=10
#fuse HS,NOWDT,NOPROTECT,NOLVP,NOPUT
#use dleay(clock=20000000)
#include <lcd_driver.c>

struct time {
               int8  hrs;
               int8  mins;
               int8  secs;
               int16 mSec;
               int16 adcvalz;
               float Temp_deg;
               }GLOB_clock={15,58,45,0,0,0,0};

void ADC_RESULT(void);
#int_TBE
TBE_isr()
{

}

#int_RDA
RDA_isr()
{

}

#int_TIMER0
TIMER0_isr()
{
    static int16 tick=0;
    static int1 toggle=0;
     //set_timer0(96);
     tick+=256;   //   set_timer0(206); 20 mhz clock, no prescaler, set timer 0 to overflow in 35us
                    // 256-(.001024/(4*256/20000000))
   if(toggle) {
         toggle=0;
         GLOB_clock.adcvalz=read_adc(ADC_READ_ONLY);
         }
         else {
         toggle=1;
         read_adc(ADC_START_ONLY);
       }
   if(tick>2500) {  //2500){
         tick-=2500;
         if(++GLOB_clock.mSec>=1000)  {    //1000){
            GLOB_clock.mSec-=1000;        //1000;
            if(++GLOB_clock.secs>=60) {
               GLOB_clock.secs=0;
               if(++GLOB_clock.mins>=60) {
                  GLOB_clock.mins=0;
                  if(++GLOB_clock.hrs>=24) {
                  GLOB_clock.hrs=0;
                  }
               }
            }
         }
   }
}



void main()
{

   //char cnt;
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_DIV_32);    //ADC_CLOCK_INTERNAL//SET adc conversion clock speed
                                   //TAD(per bit)=1/20Mhz X 32 = 0.16us ;Requires min. 12 TAD for 10 bit
                                   //Min. conversion time approx. 2us
   set_adc_channel(0);             //Set ADC channel to port0(pin 2,AN0).
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
   // setup_psp(PSP_DISABLED);setup_spi(FALSE);setup_timer_1(T1_DISABLED);setup_timer_2(T2_DISABLED,0,1);
  // setup_comparator(NC_NC_NC_NC);setup_vref(FALSE);enable_interrupts(INT_AD);/ enable_interrupts(INT_TBE);enable_interrupts(INT_RDA);

   lcd_init();
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);             //printf("Sampling adc"

   lcd_gotoxy(2,1);
   lcd_putc("\fSampling....");
   delay_ms(1000);
   lcd_putc("\f");

while(1)
   {
   ADC_RESULT();
   delay_ms(200);
   }

}

void ADC_RESULT(void){
   static int first=true;
   static int32 avgsum;
   static int16 adcval;
   static int8 tim_12_hr;
   struct time local_clock;   
   memcpy(&local_clock,&GLOB_clock, sizeof(struct time));
if(firts){avgsum=local_clock.adcvalz*8;
            first=false;
          }
else
{
   avgsum+=local_clock.adcvalz;
   adcval=avgsum/8;                                       //Average value- using/8 since in binary, this is quicker
   avgsum-=adcval;
}
    local_clock.Temp_deg = ((adcval - 559L)/2);   //Temp_Kelvin = (Temp_degrees + 273.15); Temp_Kelvin =((((float)val*5)/1024)-273.15);
 
   //Displaying time here
   if((local_clock.hrs)>=13)  tim_12_hr=(local_clock.hrs)-12;
   else tim_12_hr=local_clock.hrs;
   lcd_gotoxy(4, 1);   //lcd_putc("LCD Ready...");
   printf(LCD_PUTC,"%02d:%02d:%02d\n",tim_12_hr,local_clock.mins,local_clock.secs);

   lcd_gotoxy(12, 1);
   if(local_clock.hrs>11) lcd_putc("PM");

   else   lcd_putc("AM");
   
    //local_clock. ADC_Results=(local_clock.val/=10);
     lcd_gotoxy(4,2);
       printf(LCD_PUTC," %2ld %2.1f\n\r",adcval,local_clock.Temp_deg);
    //printf(LCD_PUTC," %2u %2.1f\n\r",local_clock.ADC_Results,local_clock.Temp_deg);
}

help me fixed the garbadge..
cheers Sad
kel



Joined: 17 Oct 2005
Posts: 68
Location: Brisbane

View user's profile Send private message

Hva fixed the garbadge problem
PostPosted: Fri Feb 10, 2006 1:02 am     Reply with quote

Thanks to you Ttelmah and pcm programmer.With your help i was able to fix the garbadge problem.I thought my problem was fixed completely however looking at the second component, it counts up variably;there are times when it swap over to next second faster then normal.Ttelmah mate i'm using ur modification of the clock.DIV_2, and the 2500 & 1000.I've tried to fixed the problem it does not seem to be fixed.As long the Display of the clock is in the
Code:
READ_ADC()
function.The count is irregular not even.

Code:
#int_TIMER0
TIMER0_isr()
{
    static int16 tick=0;
    static int1 toggle=0;
     //set_timer0(96);
     tick+=256;   //   set_timer0(206); 20 mhz clock, no prescaler, set timer 0 to overflow in 35us
                    // 256-(.001024/(4*256/20000000))
   if(toggle) {
         toggle=0;
         GLOB_clock.adcvalz=read_adc(ADC_READ_ONLY);
         }
         else {
         toggle=1;
         read_adc(ADC_START_ONLY);
       }
   if(tick>2500) {  //2500){
         tick-=2500;
         if(++GLOB_clock.mSec>=1000)  {    //1000){
            GLOB_clock.mSec-=1000;        //1000;
            if(++GLOB_clock.secs>=60) {
               GLOB_clock.secs=0;
               if(++GLOB_clock.mins>=60) {
                  GLOB_clock.mins=0;
                  if(++GLOB_clock.hrs>=24) {
                  GLOB_clock.hrs=0;
                  }
               }
            }
         }
   }
}

main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);

while(1){
Read_adc();
delay_ms(400);}
}
kel



Joined: 17 Oct 2005
Posts: 68
Location: Brisbane

View user's profile Send private message

Guys I need your help!!
PostPosted: Sat Feb 11, 2006 9:50 pm     Reply with quote

Please check my code and help me if possible.I know i'm beaten but we cannot all be beaten by this programming problem.I'm new to CCS PICC compiler and it's the very reason why i have this high level of difficulty...
Help me fixed the timing which count irregularly.At time faster and at the other times slowly.
Also help me fixed the temperature counter which count up on the start up and settle about a second later.I believe one cannot have a thermomter which starts counting up before settling...
I will appreciate anybody who is willing to help.God bless you in advance..
God bless this forum as well..
cheers Idea
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