View previous topic :: View next topic |
Author |
Message |
vever001
Joined: 15 May 2010 Posts: 21
|
Read temp from lm35 and converting it |
Posted: Sat May 15, 2010 9:55 am |
|
|
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](images/smiles/icon_wink.gif) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 15, 2010 1:31 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sat May 15, 2010 2:30 pm |
|
|
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
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 |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 15, 2010 4:43 pm |
|
|
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.
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". |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sat May 15, 2010 9:16 pm |
|
|
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](images/smiles/icon_wink.gif) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 15, 2010 9:43 pm |
|
|
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 ? |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sun May 16, 2010 3:08 pm |
|
|
The problem is that I don't see where the output will be printed if I do a printf with proteus... |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun May 16, 2010 3:15 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19366
|
|
Posted: Sun May 16, 2010 3:30 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sun May 16, 2010 4:42 pm |
|
|
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](images/smiles/icon_wink.gif) |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sun May 16, 2010 5:12 pm |
|
|
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... |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sun May 16, 2010 5:22 pm |
|
|
Ooops sorry it works now !
Sorry for any inconvenience |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sun May 16, 2010 5:50 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun May 16, 2010 5:54 pm |
|
|
Post your test program that shows how you get those values. |
|
![](templates/subSilver/images/spacer.gif) |
vever001
Joined: 15 May 2010 Posts: 21
|
|
Posted: Sun May 16, 2010 5:57 pm |
|
|
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](images/smiles/icon_wink.gif) |
|
![](templates/subSilver/images/spacer.gif) |
|