LM35 issue

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Guys,

I'm trying to read values from my lm35 temp. sensor. I've written a code, but I always get a still value, which is too high, in my opinion. It's 1023. I'm assuming a lower value, because it's ADC/2=temperature, in Celsious. According my readings.

I use atmega128. And the lm35 is on the PF0;
What should I change in the code?

Plus, in the ISR, if I devide the ADC_val by 2, I see nothing on the LCD. oO

#include 
#include "lcd_head.h"
#include 

#define F_CPU 16000000UL

void ADC_Init(void);
void ReadADC (void);

volatile unsigned int  ADC_val=0;
volatile unsigned char a=0;

void main()
{
	DDRF=0x00;
	DDRB=0xF0;
	ADC_Init();
	LCD_Init();
	LCD_SendCommand(0x01);

	while(1)
	{
		ReadADC();
		LCD_SendCommand(0x80);

		a=(ADC_val/1000)+48;
		LCD_SendData(a);

		a=(ADC_val%1000/100)+48;
		LCD_SendData(a);

		a=(ADC_val%100/10)+48;
		LCD_SendData(a);

		a=(ADC_val%10)+48;
		LCD_SendData(a);
	}

}

void ReadADC(void)
{
   //Start Single conversion
   ADCSRA|=(1<<ADSC);

   //Wait for conversion to complete
   while(!(ADCSRA & (1<<ADIF)));

   //Clear ADIF by writing one to it
   ADCSRA|=(1<<ADIF);

}

void ADC_Init(void)
{
	ADCSRA|=(1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
	//prescaler 128

	ADCSRA|=(1<<REFS0);
	//ref V AVCC

	ADMUX|=(1<<MUX0);

	ADCSRA|=(1<<ADFR);
	//free running mode

	ADCSRA|=(1<<ADEN);
	//enable ADC

	ADCSRA|=(1<<ADIE);
	//enable ADC interrupt
	sei();
	ADCSRA|=(1<<ADSC);
	//conv. start
}

ISR(ADC_vect)
{
	
   ADC_val=(ADCL);
   ADC_val+=(ADCH<<8);
   ADC_val/=2;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
//Start Single conversion
ADCSRA|=(1<<ADSC);

ADCSRA|=(1<<ADFR);
//free running mode

You will have to choose either single conversion or free running mode (continual conversions).
I would recommend the former.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You seem to have a mixture of polled code and interrupt code. Pick a method and go with it.

For instance, in your ReadADC function, you wait for conversion complete. If you are going to wait for the ADC conversion to finish, then why not just read the ADC result register after the ADIF flag is set ? Then clear the flag as you have have already done. This is an example of polled code.

For your limited application, polling should work just as well.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you guys! :)

But I still get the same 1023 value. :(

#include 
#include "lcd_head.h"

#define F_CPU 16000000UL

void ADC_Init(void);
void ReadADC (void);

volatile unsigned int  ADC_val=0;
volatile unsigned char a=0;

void main()
{
	DDRF=0x00;
	DDRB=0xF0;
	ADC_Init();
	LCD_Init();
	LCD_SendCommand(0x01);

	while(1)
	{
		ReadADC();
		LCD_SendCommand(0x80);

		a=(ADC_val/1000)+48;
		LCD_SendData(a);

		a=(ADC_val%1000/100)+48;
		LCD_SendData(a);

		a=(ADC_val%100/10)+48;
		LCD_SendData(a);

		a=(ADC_val%10)+48;
		LCD_SendData(a);
	}

}

void ReadADC(void)
{
   //Select ADC Channel ch must be 0-7
   ADMUX|=(1<<MUX0);

   //Start Single conversion

   ADCSRA|=(1<<ADSC);

   //Wait for conversion to complete
   while(!(ADCSRA & (1<<ADIF)));
   
   ADC_val=(ADCL);
   ADC_val+=(ADCH<<8);
   ADC_val/=2;

   //Clear ADIF by writing one to it
   ADCSRA|=(1<<ADIF);

}

void ADC_Init(void)
{
	ADCSRA|=(1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
	//prescaler 128

	ADCSRA|=(1<<REFS0);
	//ref V AVCC

	ADMUX|=(1<<MUX0);

	ADCSRA|=(1<<ADFR);
	//free running mode

	ADCSRA|=(1<<ADEN);
	//enable ADC

	//ADCSRA|=(1<<ADIE);
	//enable ADC interrupt
	//sei();
	//ADCSRA|=(1<<ADSC);
	//single conversion
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

ADCSRA|=(1<<REFS0);
//ref V AVCC


Reference selection is not done in that register.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch:
Good shot!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've changed it to ADMUX, but nothing changes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
ADCSRA|=(1<<ADFR);
//free running mode

I do not know if it helps, but you are still mixing "single conversion" and "free running" mode together.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Doesn't help. :S

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I've changed it to ADMUX, but nothing changes.

So, then, what is the actual, simplest, complete program that you are now using?

Tell about AVR model, supply voltage level, clock speed, and connections. Are all Vcc and AVcc hooked up, and all Gnd, and properly bypassed? What is connected to AREF pin? What voltage level is >>rignt on the AVR pin<<? Confirm which pin this is.

Quote:

//Select ADC Channel ch must be 0-7
ADMUX|=(1<<MUX0);

Why are people so on love with |= ? Yes, it may work in this simple test program. Now work through changing channels...
https://www.avrfreaks.net/index.p...

How can you say you are always getting 1023 when you divide the ADC result by 2? So you hare having 1023 displayed? Have you verified your display "routine" such as it is? (usually high-level work is done with e/g goto/position, put char, put string. And not with the binary of a particular command.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, so first of all I get 1023 all the time. The devide by 2 thing was my fault. Now, if I divide it by 2, I get the half ot 1023. My LCD works fine, I've tested it. :)

I'm using this code, right now:

#include 
#include "lcd_head.h"

#define F_CPU 16000000UL

void ADC_Init(void);
void ReadADC (void);

volatile unsigned int  ADC_val=0;
volatile unsigned char a=0;

void main()
{
	DDRF=0x00;
	DDRB=0xF0; //11011111
	ADC_Init();
	LCD_Init();
	LCD_SendCommand(0x01);

	while(1)
	{
		ReadADC();
		LCD_SendCommand(0x80);

		a=(ADC_val/1000)+48;
		LCD_SendData(a);

		a=(ADC_val%1000/100)+48;
		LCD_SendData(a);

		a=(ADC_val%100/10)+48;
		LCD_SendData(a);

		a=(ADC_val%10)+48;
		LCD_SendData(a);
		}

}

void ReadADC(void)
{
   //Select ADC Channel ch must be 0-7
   ADMUX|=(1<<MUX0);

   //Start Single conversion

   ADCSRA|=(1<<ADSC);

   //Wait for conversion to complete
   while(!(ADCSRA & (1<<ADIF)));
   
   ADC_val=(ADCL);
   ADC_val+=(ADCH<<8);
   //ADC_val/=2;

   //Clear ADIF by writing one to it
   ADCSRA|=(1<<ADIF);

}

void ADC_Init(void)
{
	ADCSRA|=(1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
	//prescaler 128

	ADMUX|=(1<<REFS0) | (0<<REFS1);
	//ref V AVCC

	ADMUX|=(1<<MUX0);

	//ADCSRA|=(1<<ADFR);
	//free running mode

	ADCSRA|=(1<<ADEN);
	//enable ADC

	//ADCSRA|=(1<<ADIE);
	//enable ADC interrupt
	//sei();
	//ADCSRA|=(1<<ADSC);
	//single conversion
}

|= is a bad habit. :) The curcuit is this: http://i48.tinypic.com/2dijddu.png Vcc=5V
Clock speed is 16Mhz, and I use atmega128.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you tested lm35 ? what's the o/p voltage you get at o/p pin of it? I was having issue with the same.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't have my multimeter here, so I can't measure it unfortunately. Yeah, it's a devboard, which I'm using, and it had a test program, when I bought it, it tested the temp sensor, too. So, it should work fine.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why are you dividing by 2 when you can multiply by 0.5 so much quicker ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I don't have my multimeter here

LM35 does not have a totem-pole (push-pull) output.

What about your debugger?

No RSTDISBL, no fun!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How should I check that? I've not done that before. :$

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good Plan B might be to hook up a 10K pot from 5V to gnd and run the wiper to where the LM35 goes. Should see smooth 0 to 1023 as you turn it up.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

May be a faster solution, (if one does not have a 10k potentiometer) would be to try with 0v (connecting what would be the LM35 output to the ground : this is trivial) , 1.4v (a biased red LED) and voltage dividers made of the resistors Monsieur OP has...