View previous topic :: View next topic |
Author |
Message |
adison.mhanna
Joined: 03 Jun 2013 Posts: 3
|
LM35 with PIC16F877A - getting wrong values |
Posted: Mon Jun 03, 2013 9:25 am |
|
|
hello guys.
I really get stuck!!!
I am designing a temperature logger on the PC. I am using LM35 with PIC16F877A microcontroller with its built-in ADC
I want to send the value of the temperature to the PC using MAX232 to log it somewhere in my database
I don't need to display the temperature on an LCD, all I need is to get the value from the LM35 and send it through the RS232 serial port
I tried so many times with the same wrong result: I am getting values that is always changing even if I am putting a fixed voltage instead of the LM35 sensor.
I have only one analog input.
this is the code that I am using:
Code: | #include <16f877a.h>
#device adc=10
#fuses XT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
unsigned int temp;
void main()
{
set_tris_a(0x01);
SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(ALL_ANALOG);
SET_ADC_CHANNEL(0);
delay_ms(100);
output_a(0x00);
while(1) // infinite loop
{
temp = read_adc();
delay_ms(1000);
printf("%u C\n",temp);
}
} |
here is a sample of the output:
34 C
32 C
75 C
11 C
64 C
32 C
25 C
63 C
73 C
32 C
18 C
73 C
4 C
32 C
44 C
9 C
38 C
19 C
.
.
.
.
In this case, i left the A2 and A3 not connected to anything, is that true? or should I do something else?
i need to solve this as an urgent issue !!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 03, 2013 9:42 am |
|
|
Quote: | void main()
{
set_tris_a(0x01);
SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(ALL_ANALOG);
SET_ADC_CHANNEL(0);
delay_ms(100);
output_a(0x00);
|
In the line in bold above, you have set all pins on PortA to be outputs.
Look at the .LST file below. It shows what the compiler is doing:
Code: |
.................... output_a(0x00);
0090: BSF STATUS.RP0
0091: CLRF TRISA <=== Set TRISA to 0x00 (all outputs)
0092: BCF STATUS.RP0
0093: CLRF PORTA
|
Here is what the 16F877A data sheet says:
Quote: |
11.3 Configuring Analog Port Pins
The ADCON1 and TRIS registers control the operation
of the A/D port pins. The port pins that are desired as
analog inputs must have their corresponding TRIS bits
set (input). If the TRIS bit is cleared (output), the digital
output level (VOH or VOL) will be converted. |
The data sheet says the analog pin must have the TRIS set as an input.
You are violating this specification with the output_a() statement.
CCS is designed to be easy for newbies. Most of the built-in functions
automatically set the correct tris for you. This is the standard default
mode of the compiler. If you want to control the TRIS yourself, then
you need to tell the compiler to use Fast I/O mode. See the CCS manual.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Jun 03, 2013 10:40 am |
|
|
Hi,
If you use the "Search" function of this forum you will find a driver I posted some time ago for the LM35.
http://www.ccsinfo.com/forum/viewtopic.php?t=48525&highlight=lm35
Use the updated version on my second post.
Things you should know:
- the circuit for the LM35 is as per Figure7 on the datasheet.
- if you are powering your circuit with 5V you do not need the Charge pump.
- the driver uses 2 (TWO) ADC channels for +/- temperatures.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
adison.mhanna
Joined: 03 Jun 2013 Posts: 3
|
|
Posted: Mon Jun 03, 2013 11:37 am |
|
|
Quote: |
Quote:
void main()
{
set_tris_a(0x01);
SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(ALL_ANALOG);
SET_ADC_CHANNEL(0);
delay_ms(100);
output_a(0x00);
In the line in bold above, you have set all pins on PortA to be outputs.
Look at the .LST file below. It shows what the compiler is doing: |
I got your idea and I removed it... the same problem
now I am working using this code:
Code: | #include <16f877a.h>
#device adc=10
#fuses XT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
unsigned int temp;
void main()
{
set_tris_a(0x01);
SETUP_ADC(ADC_CLOCK_INTERNAL);
SETUP_ADC_PORTS(ALL_ANALOG);
SET_ADC_CHANNEL(0);
delay_ms(100);
while(1) // infinite loop
{
temp = read_adc(ADC_START_AND_READ);
delay_ms(500);
printf("%u C\n",temp);
}
}
|
I am getting this result:
76 C
55 C
27 C
77 C
114 C
130 C
115 C
141 C
13 C
27 C
51 C
55 C
13 C
110 C
76 C
.
.
.
.
PLEASE can anyone provide me with a simple code in how to get the real adc value and how to implement the circuit diagram?
maybe I should set the VREF + and VREF- values ??
please I am getting crazy about this small project !!!
I've been working on it for more than 10 days with no result !!!
what should I do ? |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Jun 03, 2013 1:28 pm |
|
|
Code: | void main()
{
SETUP_ADC_PORTS(sAN0); // I like to select *Ports first
SETUP_ADC(ADC_CLOCK_INTERNAL); // WRONG ADC TIME CONSTANT FOR 4MHZ
SET_ADC_CHANNEL(0);
delay_ms(100);
while(1) // infinite loop
{
temp = read_adc();
temp *= 0x1E8; // Ive added the ADC const
printf("%u C\n\r",temp);
delay_ms(500);
}
} |
try that... but first, check what is the correct TAD for a 4MHZ clock
also, you are not "scaling" your ADC reading... the ADC give you a count of how many steps it took to the closest value you where reading... NOT the voltage.
you need to multiply your ADC value (temp) by a constant which is dependent on voltage...
for 1023 bit res @5V i use:
ADC_Const = ((5/1023)*100,000)
Which basically reduces to: 0x1E8
Ive added this to your code...
now temp should contain Volts... which for the LM35 equal Temp in C.
since you apparently are only interested in positive temps, you only need 5v, GND, and Vout to AN0.
EDIT: MOST IMPORTANTLY
Temp is an 8 int variable... it cant hold a 10 bit number thus what you are seeing are only the last 8 bits of your reading...
Make temp an int16.
G _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Mon Jun 03, 2013 1:34 pm |
|
|
Several things:
First is ADC_CLOCK_INTERNAL correct for your system?. Read the data sheet. What does it say about this selection, and frequencies above 1MHz?.
Then the count from the ADC, is not going to be in degrees. The ADC is operating from 0 to 5v. Each 'step' is approximately 4.8mV. The sensor gives 10mV per degree. So you need to divide the output by just over 2, to get degrees.
Only setup the channel you are using to feed the ADC. Every extra signal you have connected to the ADC multiplexer increases noise.
Now, the accuracy and repeatability of the result will be dependent on how smooth and stable your 5v rail is.
Best Wishes |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Mon Jun 03, 2013 1:42 pm |
|
|
Gabriel's comment is most important. If you put a 10 bit number in an 8 bit variable you throw out the MOST SIGNIFICANT bits.
Also be sure to get it working with a known voltage or resistor divider first. Those temperature sensors can sometimes oscillate which will give just the sort of noise you are seeing. Do you have an oscilloscope you can put on the temperature wire? _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Jun 03, 2013 3:46 pm |
|
|
what is your CIRCUIT??
care to post it ??
what is your ADC reference voltage and how is it derived?
i have used the LM34 and never the LM35 - as there is more output and better resolution over biologically useful temperature ranges using the LM34 and converting to degrees C in software. if you are in the range of
mammalian temperatures - you will only have a signal of less than .4V to read.
if using a noisy 5V Vdd as the implied ADC reference - you are not going to get spectacularly good resolution or low conversion noise either. In my own work , i would solve your problem by adding clean OP amp GAIN to the LM34, and then using methods like this to get low noise readings:
http://www.ccsinfo.com/forum/viewtopic.php?t=50320
http://www.ccsinfo.com/forum/viewtopic.php?t=50354 |
|
|
adison.mhanna
Joined: 03 Jun 2013 Posts: 3
|
problem solved |
Posted: Mon Aug 05, 2013 5:58 am |
|
|
hello guys again.
first of all thank you for your support, I've been away for a long period due to some force reasons.
regarding the project, it worked finally!!!
The problem was that I was missing some filters for the DC power. I've added a 1000 uf capacitor to the 5 V DC after putting a regulator after the 12 v for having 5 V with 5 A supply power. Before I used to put the power of 5 V only coming from a 700 MA power adapter.
THANK YOU ALL |
|
|
|