ad space

Reading and displaying temperature with ATmega32A

Here the environment temperature is read by ATmega32A microcontroller and displayed on 16x2 LCD(Liquid Crystal Display). To get the environment temperature the LM35 Temperature sensor has been used. It is connected to the ATmega32 microcontroller analog input pin PA0(ADC channel 0). Below shows the schematic diagram of connecting LCD, temperature sensor LM35 and other essential circuitry to run the ATmega32A microcontroller MCU.

atmega32a LM35 temperature sensor

 

In this temperature sensor tutorial with ATmega32, only the wiring diagram and programming code are provided, for actual implementation of the circuit on breadboard see LM35 Temperature Sensor with ATmega32 and LCD.

The C program code are given below. The main.c contains the main code and there are other C program code for ADC(adc.c and adc.h) and for LCD(lcd.c and lcd.h).  In this code we have used the polling method to get the temperature reading from ADC module.

The main.c code is below.


#ifndef F_CPU
#define FCPU 4000000UL
#endif


#include <avr/io.h>
#include <util/delay.h>

int main()
 { 
    lcdinit();
    adcinit();

    char Ctemp[10], Ftemp[10];

	float c, f;
	lcdstr("***Temperature***");

   while(1){
		c = (adcread(0)*4.88);
		c = (c/10.00);
        f = (c*9)/5 + 32;

		dtostrf(c, 6, 2, Ctemp);
		dtostrf(f, 5, 2, Ftemp);

		lcdgoto(0,2);
		lcdstr(Ctemp);
		lcdchar(0xDF); 
	    lcdstr("C");
	    lcdstr("(");
	    lcdstr(Ftemp);
		lcdchar(0xDF); 
	    lcdstr("F)");
      }
   return 0;
 }
 

 

The code for LCD(lcd.c and lcd.h) are below. 

lcd.c 

//  lcd.c
#include <avr/io.h>
#include  <util/delay.h>
#include "lcd.h"


#define E (1<<PA7)
#define RW (1<<PA6)
#define RS (1<<PA5)


void lcdinit(){
   
   //initialize PORTs for LCD
   
   DDRB |= (1<<PB3) | (1<<PB2) | (1<<PB1) | (1<<PB0);
	DDRA |= (1<<PA7) | (1<<PA6) | (1<<PA5);		
   
   //Send Pulse to Latch the data
   latch();
   _delay_ms(2);  //delay for stable power
   // Command to set up the LCD
   lcdcmd(0x33);
   _delay_us(100);
  lcdcmd(0x32);
  _delay_us(100);
   lcdcmd(0x28);	// 2 lines 5x7 matrix dot, 4 bit data
   _delay_us(100);
   //lcdcmd(0x0E);  // display ON, Cursor ON
    lcdcmd(0x0C);  // display ON, Cursor ON
  _delay_us(100);
   lcdcmd(0x01);	//clear LCD
   _delay_ms(20);	//wait
   lcdcmd(0x06);	//shift cursor to right
   _delay_ms(500);
   
   }
   
 void latch(void){
      PORTA |= E;		//send high
      _delay_us(500);		//wait
      PORTA &= ~E;		//send low
      _delay_us(500);		//wait
    }
   
void lcdcmd(uint8_t cmd){
      
     PORTB = (PORTB & 0xF0) | (cmd>>4);	//send low nibble 
      PORTA &= ~RW;	//send 0 for write operation
      PORTA &= ~RS;	//send 0 to select command register
      latch();			//latch the data
       PORTB = (PORTB & 0xF0) | (cmd & 0x0F);  // send high nibble
      
      latch();			//latch the data
      }
      
  void lcdchar(uint8_t data){
      
      PORTB = (PORTB & 0xF0) | (data>>4);  // send high nibble
      PORTA &= ~RW;	//send 0 for write operation
      PORTA |= RS;	//send 1 to select data register
      latch();
     PORTB = (PORTB & 0xF0) | (data & 0x0F);  // send high nibble
      
      latch();
      
      }
      
 void lcdstr(char *str){
    uint8_t k=0;
    while(str[k] != 0){
	 lcdchar(str[k]);
       k++;
       }
    }
 
 void lcdgoto(uint8_t x, uint8_t y){
      uint8_t firstcharadr[] = {0x80, 0xC0, 0x94, 0xD4};
      lcdcmd(firstcharadr[y-1] + x-1);
      _delay_us(10);
    }

lcd.h

#include <avr/io.h>

void lcdinit();
void lcdcmd(uint8_t);
void lcdchar(uint8_t);
void lcdstr(char *);
void latch(void);
void lcdgoto(uint8_t , uint8_t );

 

The code for ADC are below. 

adc.c


#include "adc.h"

void adcinit(){	
	//make PA0 an analog input
	DDRA &= ~(1<<PA0);	        /* Make ADC port as input */
	//enable ADC module, set prescalar of 128 which gives CLK/128 	
	ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
	//set the voltage reference using REFS1 and REFS0 bits and select the ADC channel using the MUX bits
	ADMUX = 0b01000000;      // set REFS1 = 0 |REFS0 = 1 (Vref as AVCC pin) | ADLAR = 0(right adjusted) |  MUX4 to MUX0 is 0000 for ADC0
}

int adcread(char channel)							
{
	/* set input channel to read */
	ADMUX = 0x40 | (channel & 0x07);   // 0100 0000 | (channel & 0000 0100)
	/* Start ADC conversion */
	ADCSRA |= (1<<ADSC);      
    /* Wait until end of conversion by polling ADC interrupt flag */
	while (!(ADCSRA & (1<<ADIF)));    
   /* Clear interrupt flag */
	ADCSRA |= (1<<ADIF);               
	_delay_ms(1);                      /* Wait a little bit */
    /* Return ADC word */
	return ADCW;                      
}
adc.h
#include <avr/io.h>
#include <util/delay.h>

void adcinit();
int adcread(char);

What the program basically does is that it reads the ADC channel 0 value from the pin PA0 which ranges from 0 to 1023 because the ATmega32A microcontroller ADC is 10 bit analog to digital converter(2^10-1=1023). Once we have the quantized value from the ADC we multiple by 4.88 and divide by 10 to get scale and convert the quantized value(0 to 1023) to Celsius and then to Fahrenheit. We convert the temperature value in float to string using the dtostrf() function. Then we display the values on the LCD. The LCD and ADC are implemented with two separate include files.

Post a Comment

Previous Post Next Post