|
|
View previous topic :: View next topic |
Author |
Message |
kel
Joined: 17 Oct 2005 Posts: 68 Location: Brisbane
|
16f877a temperature sensor not working!! |
Posted: Wed Feb 08, 2006 3:13 am |
|
|
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
|
|
Posted: Wed Feb 08, 2006 3:44 am |
|
|
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
|
|
Posted: Wed Feb 08, 2006 8:25 am |
|
|
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
|
16F887a temperature sensor not working!! |
Posted: Wed Feb 08, 2006 11:05 pm |
|
|
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:
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
|
It's working but printf() function seems to have a bug!! |
Posted: Thu Feb 09, 2006 2:02 am |
|
|
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....
|
|
|
Ttelmah Guest
|
|
Posted: Thu Feb 09, 2006 4:57 am |
|
|
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
|
|
Posted: Thu Feb 09, 2006 8:57 pm |
|
|
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 |
|
|
kel
Joined: 17 Oct 2005 Posts: 68 Location: Brisbane
|
Hva fixed the garbadge problem |
Posted: Fri Feb 10, 2006 1:02 am |
|
|
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 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
|
Guys I need your help!! |
Posted: Sat Feb 11, 2006 9:50 pm |
|
|
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 |
|
|
|
|
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
|