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

Read temp from lm35 and converting it
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
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

Read temp from lm35 and converting it
PostPosted: Sat May 15, 2010 9:55 am     Reply with quote

Hello,

I'm new to your forum and I have a question for reading the temperature from the LM35 connected to the analog input.

I don't have any pic so I simulate it with proteus.

I put an operational amplifier with gain 4 after the LM35.

For example I have 1V output after the LM35 and 5V output after the op amp.

But I have a problem in my code : I think it's when I convert it in °C.

So here is my code:
Code:

#include "H:\projet PIC\Programme\electro_juin.h"
#ZERO_RAM
#include <stdio.h>
#include <stdlib.h>

#int_RDA
void  RDA_isr(void)
{

}

int16 temp,temp1;

void main()
{
   setup_adc (ADC_CLOCK_DIV_8);
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);   
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

   set_tris_d(0x00);   
   
   while(1)
   {
    delay_ms (500);
    temp=read_adc();
    temp1=temp*20;                        <-------CORRECT ?
    printf("%2.1f\n\r",(float) temp1);
   
    if(temp1 < 100)    //If temperature < 100°C
    {
     output_high(PIN_d6);     //switch on the green led
     output_low(PIN_d7);      //switch off the red led
    }
    else           
    {
     output_high(PIN_d7);     //switch on the red led
     output_low(PIN_d6);      //switch off the green led
    }
   
   }
}


Thanks a lot for your help...I really need it !
And sorry for my bad english...I'm french

See ya Wink
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 15, 2010 1:31 pm     Reply with quote

Post this .h file:
Quote:
#include "H:\projet PIC\Programme\electro_juin.h"

We need to see if you have a "#device adc=xx" statement in there.
This will tell us if you are using the ADC in 8-bit or 10-bit mode.
Also, we need to see what PIC you are using, and your #use delay()
statement, and your #fuses, to see if they are correct.

Quote:

#int_RDA
void RDA_isr(void)
{

}

Don't use an empty #int_rda routine, with the interrupts enabled.
If you do get an incoming character, the interrupt will occur but the
character will not be read, because you don't have a getc() statement
in the interrupt routine. You will then get continuous INT_RDA interrupts
and your program will appear to "lock up". At a minimum, you need to
do this:
Code:

#int_RDA
void  RDA_isr(void)
{
char c;

c = getc();
}

This will get the character and discard it. But at least the program will
not lock up.
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sat May 15, 2010 2:30 pm     Reply with quote

Hello,

Thanks a lot for your help.

Here is my electro_juin.h file:

Code:
#include <16F877.h>
#device ADC=10   

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD

#use delay(clock=4000000)      
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


I put #device ADC=10
So when I read on the adc I will receive a value between 0 and 255...
Am I correct?

So the conversion for me should better be I think:
Code:
temp=read_adc();
temp1=(temp*100)/255;


So I tested this conversion but my green led only switches on when the voltage received on the AN0 pin is between 3.24V and 4.40V...
And my red led never swiches on Crying or Very sad

That's really stange...

For the RDA_isr I will receive an int from the computer so I can change the threshold for these 2 leds. (Now the threshold is at 100)
So according to you, can I do receive an integer ? (for example 39)
Or only char?

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 15, 2010 4:43 pm     Reply with quote

Quote:
I put #device ADC=10
So when I read on the adc I will receive a value between 0 and 255...
Am I correct?

No. ADC=10 tells the compiler to use 10-bit mode. 10 bits is 0 to 1023.

Quote:

#FUSES LVP

You're not using Low Voltage Programming mode. In Proteus it may
not matter, but in a real hardware board, it does matter. Change it to
NOLVP. Do that in all your programs.

Quote:
So according to you, can I do receive an integer ? (for example 39)
Or only char?

Make a test program to display the raw values that you are reading from
the ADC. Example:
http://www.ccsinfo.com/forum/viewtopic.php?t=40279&start=3
The link above displays the ADC values in hex (0 to 0x3FF). If you want
to display them in decimal, then change the printf statement to use "%lu".
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sat May 15, 2010 9:16 pm     Reply with quote

Thanks a lot for your explanations,

I changed my code for converting the temperature read from the analog input:
Code:
temp1=5*temp*100/1024;


Now it works but I always return to 0 when I reach 63
I don't get it at all...

I have one more question:
Is it possible to read and send data between proteus and a terminal or monitor ?

Cause I have to read the temperature send by the pic on a java application I have to make.
I saw there was a serial input/output monitor with picc but I don't know if it is devoted for that...and how to use it...I searched on google but didn't find anything.

Thanks Wink
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 15, 2010 9:43 pm     Reply with quote

Quote:
Now it works but I always return to 0 when I reach 63

1. Post the complete test program that shows this result.

2. Post a description of your external circuit on the A/D pin.

3. What is the range of the voltage that you measure on the A/D pin ?
This is the voltage measured directly on the pin, given in Volts.

4. What is the voltage on the A/D input pin at the exact moment when
the A/D value goes from 63 to 0 ?
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sun May 16, 2010 3:08 pm     Reply with quote

The problem is that I don't see where the output will be printed if I do a printf with proteus...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 16, 2010 3:15 pm     Reply with quote

I don't have Proteus, but with a little bit of googling I found this schematic.
It looks like Proteus has a little serial port terminal widget that can be
connected directly to a PIC:
http://www.elektrotekno.com/userpix/10512_proteus_stop_1.jpg
Use that to see the output.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Sun May 16, 2010 3:30 pm     Reply with quote

On the value from your LM35. You refer to a *4 op-amp, but then say that you have 5vout for 1v in (*5)...
Which is right?.

Now the LM35, gives 10mV/degree.
The ADC, if using 5v as it's reference, gives values from 0 to 1023, for the range, but the scaling is not quite as simple as V/1023. Look at the diagrams in the Microchip data sheets about this. Effectively it reaches the 'top' value, half a bit before the full voltage, and the '0' reading is given for -0.5 bit to +0.5bit.

Assuming your op-amp, is *5, then you have 50mV/degree, which 'almost' makes the maths simple. The ADC will record one step for 5/1024 volt change, which is 4.8mV. So a count of '1', will actually correspond to almost 0.1C.

Your maths goes wrong in this example, because of the size of the numbers.
Multiplication has precedence over division, so 'temp' * 100 * 5, overflows if temp>131 (132*500 = 66000 - largest value an int16 can hold is 65535)....

Assuming you want to actually work to 100C, then start by setting your op-amp gain to 4.88*.
Then your operation becomes really simple:
Code:

printf("%4.1w\n\r",temp);

There is potentially 0.5 bit error (0.05C), because this does not allow for the slight zero offset on the ADC, but this is tiny.

This prints the integer, 0 to 1023, as 0.0 to 102.3
If the op-amp scaling is right, so will be the result.

Best Wishes
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sun May 16, 2010 4:42 pm     Reply with quote

Wow thanks a lot for all there informations !

Thanks a lot for the info PCM programmer ! I just found this...it is called virtual terminal...it will be very useful !


In fact I deleted my op amp and now I just have the LM35 directly connected to the AN0 pin...but I will see if I can do something with the virtual terminal

Thanks again Wink
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sun May 16, 2010 5:12 pm     Reply with quote

Unfortunately I don't have any display on the virtual terminal...
I crossed tx and rx...
I'm doing a printf in my program so I don't see what else do I have to do...
I searched for examples but I didn't found anything clear...
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sun May 16, 2010 5:22 pm     Reply with quote

Ooops sorry it works now !

Sorry for any inconvenience
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sun May 16, 2010 5:50 pm     Reply with quote

When I put 64 on the lm35 (0.64V) I get
0083

And then when I put 65 (0.65V) I get
0086

So the temp returned by the read_adc() function is an hexa value...
But then I need to convert it to decimal right ???


Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 16, 2010 5:54 pm     Reply with quote

Post your test program that shows how you get those values.
vever001



Joined: 15 May 2010
Posts: 21

View user's profile Send private message

PostPosted: Sun May 16, 2010 5:57 pm     Reply with quote

I finally succeeded to get the right temp displayed

I was wrong about the conversion

Now it works great with this code :

Code:
temp1= 5*temp*(100.00/1023.00);


Thanks again for your help PCM programmer Wink
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