ad space

How to Read and Display Temperature Using ATmega32A Microcontroller

This program reads the ambient temperature using an LM35 sensor connected to the ATmega32A microcontroller and displays it on a 16x2 LCD. The LM35 Temperature sensor outputs an analog signal, which is fed into the analog input pin PA0 (ADC channel 0) of the ATmega32A. Below is the schematic showing the connections for the LCD, LM35 temperature sensor, and necessary circuitry for the ATmega32A.

atmega32a LM35 temperature sensor

This tutorial provides the wiring diagram and programming code for setting up the temperature sensor with ATmega32 and an LCD. For hands-on implementation on a breadboard, refer to the LM35 Temperature Sensor with ATmega32 and LCD tutorial.

The program consists of several parts. The main code is in main.c, with additional files adc.c and adc.h for the ADC module and lcd.c and lcd.h for the LCD. In this setup, we use the polling method to read temperature data from the ADC module.

Here is the main.c code:

#ifndef F_CPU
#define F_CPU 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) / 10.0; // Convert ADC value to Celsius
f = (c * 9) / 5 + 32; // Convert Celsius to Fahrenheit

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

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


 

Below is the code for the LCD module (lcd.c and lcd.h):

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() {
DDRB |= (1<<PB3) | (1<<PB2) | (1<<PB1) | (1<<PB0);
DDRA |= (1<<PA7) | (1<<PA6) | (1<<PA5);

latch();
_delay_ms(2);
lcdcmd(0x33);
_delay_us(100);
lcdcmd(0x32);
_delay_us(100);
lcdcmd(0x28);
_delay_us(100);
lcdcmd(0x0C);
_delay_us(100);
lcdcmd(0x01);
_delay_ms(20);
lcdcmd(0x06);
_delay_ms(500);
}

void latch(void) {
PORTA |= E;
_delay_us(500);
PORTA &= ~E;
_delay_us(500);
}

void lcdcmd(uint8_t cmd) {
PORTB = (PORTB & 0xF0) | (cmd >> 4);
PORTA &= ~RW;
PORTA &= ~RS;
latch();
PORTB = (PORTB & 0xF0) | (cmd & 0x0F);
latch();
}

void lcdchar(uint8_t data) {
PORTB = (PORTB & 0xF0) | (data >> 4);
PORTA &= ~RW;
PORTA |= RS;
latch();
PORTB = (PORTB & 0xF0) | (data & 0x0F);
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 ADC module code (adc.c and adc.h) is as follows:

adc.c

#include "adc.h"

void adcinit() {
DDRA &= ~(1<<PA0); // Set PA0 as input for ADC
ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Enable ADC with prescaler of 128
ADMUX = 0b01000000; // AVCC as reference, ADC0 as input
}

int adcread(char channel) {
ADMUX = 0x40 | (channel & 0x07); // Select ADC channel
ADCSRA |= (1<<ADSC); // Start conversion
while (!(ADCSRA & (1<<ADIF))); // Wait for conversion to complete
ADCSRA |= (1<<ADIF); // Clear interrupt flag
_delay_ms(1);
return ADCW; // Return ADC result
}


adc.h

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

void adcinit();
int adcread(char);


Program Overview

The program reads the ADC value from PA0 (ADC channel 0), which provides a 10-bit value (0-1023). By multiplying this ADC value by 4.88 and dividing by 10, it converts it to Celsius, then further to Fahrenheit. Using dtostrf(), these temperature values are formatted as strings and displayed on the LCD. The LCD and ADC functions are organized in separate header files for modularity.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Post a Comment

Previous Post Next Post