Tuesday 31 March 2015

Sensing Temperature Using AVR

In this new tutorial, we will be interfacing a LM35 based temperature sensor with ATMEGA32. The 3 main types are thermometers, resistance temperature detectors, and thermocouples. All three of these sensors measure a physical property (i.e. volume of a liquid, current through a wire), which changes as a function of temperature. In addition to the 3 main types of temperature sensors, there are numerous other temperature sensors available for use.





However the LM35 based sensors are precision-integrated temperature sensors, with an output voltage linearly proportional to the Centigrade temperature. The main advantage is these types of sensors don’t require any external calibration. They are internally calibrated and simply generate the output with respect to the temperature they detect. The device is used with single power supplies, or with plus and minus supplies. As the LM35 draws only 60 μA from the supply, it has very low self-heating of less than 0.1°C in still air. The LM35 is rated to operate over a −55°C to +150°C temperature range, while the LM35C is rated for a −40°C to +110°C range (−10° with improved accuracy).LM35 series of temperature sensor was initially manufactured by the National Instrument but in the current scenario, almost every semiconductor company manufacture LM35 based temperature sensor.
Before starting with the coding part, make sure you have a fair knowledge about using ADC of AVR. Since we will be displaying the temperature on a character LCD, make sure you have gone through the LCD tutorial posted on the website.
The sensitivity of LM35 is 10 milivolts per °C.  Sensitivity, in layman terms, is the ratio of output by input. So if the temperature of the surrounding is 1°C then it’s output will be 10mv or if the temperature is 31°C then the output will be 310mv. These small voltages can easily be detected by the AVR after converting them into ADC and by doing a certain amount of calculation; we can get back the temperature. Again the LM35 series of sensors are available in both analog and digital form. We will be using the analog temperature sensor.
Since we are using the ADC in 10 bit mode with a reference voltage of 5V supplied externally, the maximum ADC value can be 1023 and minimum can be 0. The resolution in terms of voltage can be:-
5/1023=4.88mV
If the ADC reading is 10 it means the input voltage is 48.8mV. With a sensitivity of 10mv °C, this accounts to 4.8°C temperature of the surrounding. So for a particular ADC value we will just have to divide by 2.04 (10/4.88) to get the temperature. For the sake of simplicity we will be dividing by 2.
Also, I am using the AVR on a 16MHz clock crystal, and the ADC prescaler have been set accordingly. So if you decided to use some other crystal frequency, or even internal ADC make sure you make the necessary changes in the ADC prescalar.
Circuit Diagram:

CODE:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef F_CPU
#define F_CPU 1600000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"
void adc_init()
{
    // AREF = AVcc
    ADMUX = (1<<REFS0);
    // ADC Enable and prescaler of 128
    ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
// read adc value
uint16_t adc_read(uint8_t ch)
{
    // select the corresponding channel 0~7
    ch &= 0b00000111;  // AND operation with 7
    ADMUX = (ADMUX & 0xF8)|ch;    
    // start single conversion
    // write '1' to ADSC
    ADCSRA |= (1<<ADSC);
    // wait for conversion to complete
    // ADSC becomes '0' again
    while(ADCSRA & (1<<ADSC));
    return (ADC);
}
int main()
{
    uint16_t adc_result0;
     int temp;
    char buffer[10];
    // initialize adc and lcd
    adc_init();
    lcd_init(LCD_DISP_ON_CURSOR);
    lcd_clrscr();
    lcd_gotoxy(0,0);
    _delay_ms(50);
    while(1)
    {
        adc_result0 = adc_read(0);      // read adc value at PA0
        temp=adc_result0/2.0;   // finding the temperature
     lcd_gotoxy(0,0);       
     lcd_puts("Adc=");
     itoa(adc_result0,buffer,10);   //display ADC value
     lcd_puts(buffer);
   lcd_gotoxy(0,1);
   itoa(temp,buffer,10);
    lcd_puts("Temperature=");   //display temperature
    lcd_puts(buffer);
    _delay_ms(50);
    }