ADC + lm335

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

Good evening everyone!
Like always, I apologize about my english :D

I'm a newbie and i'm trying to measure temperature with a lm335, but after read a lot of posts and the ADC tutorial post by penquissciguy and following the instructions I couldn't.

this is the code I'm using:

ISR(ADC_vect)
{
   int _ADC=ADCL;
   temp=((_ACD * 500) >> 10) - 273; //temp in ºC

}

int main(void)
{
... more settings

   ADCSRA|= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); 
   ADMUX|=(1<<REFS0);
   ADCSRA|=(1<<ADEN);
   ADCSRA|=(1<<ADIE);
   sei();
   ADCSRA|=(1<<ADSC);
   while(1);
}


I suppose that doing this, in the "temp" variable I have the temperature in ºC. And I send it with the USART converting it to short like this:

bOut[3]= (((temp/10) & 0x000f)+48);
bOut[4]= (((temp%10) & 0x000f)+48);

For the first tries I don't consider the possibility that the temperature can be over than 100 ºC and under 0ºC.

I apologize about the big mistakes I could done.

Thanks to everyone.

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

Sorry! I forget to say that I'm using an arduino duemilanove board with an atmega 328p

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ISR(ADC_vect) 
{ 
   int _ADC=ADCL; 
   temp=((_ACD * 500) >> 10) - 273; //temp in ºC 
} 

I'm astonished the compiler didn't throw an error here? At the top of the function you define _ADC then you access _ACD ??

Anyway you can NEVER read only ADCL. You are either using ADLAR (8bit, left shifted) mode in which case it's enough to read just ADCH, otherwise ADCH/L must both be read and it must be in the right order. GCC allows you to use ADCW to access the whole thing as a single 16 bit quantity.

By the way, never prefix your own function/variable names with '_'. The rules are '_' for "library" functions/variables and "__" for internal compiler functions/variables.

Cliff

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

Well, I'm feeling a bit ashamed :P
It's obvious that I didn't read enough about the ADC and GCC.
Thanks for the answer.

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

Hi,
Try this

// reference voltage  = AVCC = 5000 mV
#define REFERENCE 5000UL   

int main(void)
{
int8_t temperature;
uint16_t adc_value, voltage;

// ADC enable, prescaler = 128
   ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);

// reference voltage = AVCC
// input = ADC0 (portc.0)
   ADMUX = (1<<REFS0);

   while(1)
   {
// start conversion
      ADCSRA |= (1<<ADSC);       
// wait for conversion complete
      while(ADCSRA & ADSC){};    
// read adc_value
      adc_value = ADCW;          
// count voltage in [mV]
      voltage = (adc_value * REFERENCE) / 1024;

// count temperature 
// 25 degreeC = 3000 mV, 10mV/degree  
      temperature = ((int16_t)voltage - 2750) / 10; 
   }
}

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

Hi Visovian, and thanks for the answer.
I tried the code but I couldn't make it work correctly. After reading one more time the ADC description at the 328p datasheet I tried this:

ISR(ADC_vect)
{
	temperatura=ADCW;
}

int main (void){
//Select the prescaler at 128 and set the ADATE
//that enable de ADC auto trigger
ADCSRA|= (1<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); 
//Set voltage reference=AVCC
ADMUX|=(1<<REFS0);
//Enable the ADC interrupt
ADCSRA|=(1<<ADIE);
ADCSRA|= (1<<ADEN);

//Because I want to run the free running mode
//I don't need to set the ADTS[2:0] bits

//Enable global interrupts
sei();

ADCSRA|= (1<<ADSC);

while(1){};

}

Well, doing this I have the ADC working correctly. But I don't understand something.
Before setting the ADATE bit, I tried to start a conversion setting de ADCS bit and waiting to it to being a zero, but the program blocked at the while... Why?

Thanks for the help!

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

Excuse me a mistake.

In my code
instead of
while(ADCSRA & ADSC){};
should be
while(ADCSRA & (1<<ADSC)){};