LM35 Temperature Sensor with Atmega328P
Contents
LM35 is a precision integrated-circuit temperature sensor. It’s output voltage linearly proportional to centigrade temperature. For example, 250 mV means 25°C. It does not require any external calibration circuitry. TheLM35 device is rated to operate over a -55°C to 150°C temperature range. In this post we will interface LM35 with Atmega328P 8-bit micro-controller.
Reference: http://www.electronicwings.com/sensors-modules/lm35-temperature-sensor You can find the C code, which is compiled with AVRGCC.
//LM35.c
//Written for atmega328P
//PC0(ADC0) is used for the ADC conversation...
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#ifndef BAUD
#define BAUD 9600
#endif
#define MYUBRR (F_CPU/(16UL * BAUD)) - 1
//ADC channels for more information see Atmega328p datasheet.
#define ADC0 0x00
#define ADC1 0x01
#define AVCC 5000 //5V = 5000mV
#define PRECISION 1024
#define T (AVCC/PRECISION)
//##################################
#include <avr/io.h>
#include <util/delay.h>
void initUSART(void);
void usart_Transmit(uint8_t data);
void usart_Message(uint8_t* msg);
uint8_t usart_Receive(void);
void initADC(void);
uint16_t readADC(uint8_t ADCchannel);
//########################################
void initUSART(void){
/*Set baud rate */
UBRR0H = (uint8_t)(MYUBRR>>8);
UBRR0L = (uint8_t)MYUBRR;
//Enable receiver and transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8N1 */
UCSR0C|=(1<<UCSZ00)|(1<<UCSZ01); // 8bit data format
// UCSR0C = (3<<UCSZ00);
}
void usart_Transmit(uint8_t data){
while (!( UCSR0A & (1<<UDRE0))) ; // wait while register is free
UDR0 = data; // load data in the register
}
uint8_t usart_Receive(void){
while(!(UCSR0A & (1<<RXC0)));
return UDR0;
}
void usart_Message(uint8_t* msg){
while(*msg){
usart_Transmit(*msg);
msg ++;
}
}
//###########################################################################
void initADC(void)
{
// AV CC with external capacitor at AREF pin
ADMUX |= (1<<REFS0);
//set prescaller to 128 and enable ADC
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN);
}
uint16_t readADC(uint8_t ADCchannel){
ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
ADCSRA |= (1 << ADSC);//start conversation
//Wait until ADC converstain complete. ADSC will be ZERO after completion.
while(ADCSRA & (1<<ADSC));
return ADC;
}
void main (void){
uint16_t voltage;
uint8_t val1, val2,val3,temperature;
//DDRD |= (1 << PD1); //TX as an output (PD1)
//DDRD &= ~(1 << PD0);
//DDRB |= (1 << PB0);
initUSART();
initADC();
_delay_ms(500);
usart_Message("LM35 Temperature Sensor\n\r");
// usart_Init();
while(1){
voltage = readADC(ADC0);
voltage = ((T*voltage)/10) + 2;
if (voltage >= 100){
val1 = voltage / 100;
val2 = voltage % 100;
val3 = val2 % 10;
val2 = val2 / 10;
}
else{
val1 = 0;
val2 = voltage / 10;
val3 = voltage % 10;
}
//Decimal 48=0 Decimal 49=1 Decimal 50 =2 For more information see ASCII table.
usart_Transmit(val1 + 48);
usart_Transmit(val2 + 48);
usart_Transmit(val3 + 48);
usart_Transmit('C');
usart_Transmit('\n');
usart_Transmit('\r');
_delay_ms(2000);
}
}
}
Creating a Makefile for compiling and flashing the code into the microcontroleer. Create a file named Makefile and paste the below contents.
#Makefile
help:
@echo 'Help details:'
@echo 'hex: compile hex file'
@echo 'flash: install hex file'
@echo 'program: compile hex and install'
hex:
avr-gcc -Os -DF_CPU=8000000 -mmcu=atmega328p -c LM35.c
avr-gcc -DF_CPU=8000000 -mmcu=atmega328p -o LM35.elf LM35.o
avr-objcopy -O ihex LM35.elf LM35.hex
rm LM35.o
rm LM35.elf
flash:
#stk500v1; when you used arduino uno as a ISP programmer.
#avrdude -c stk500v1 -p attiny2313 -P /dev/ttyACM1 -D -b 19200 -vv -U flash:w:blink_avr.hex
#Working one
#avrdude -c stk500v1 -F -p attiny2313 -P /dev/ttyACM1 -b 19200 -vvv -U flash:w:blink_avr.hex
avrdude -c usbasp -p atmega328p -P usb -b 19200 -vv -U flash:w:LM35.hex -U lfuse:w:0xff:m
Usage: Compiling: make hex Flashing: make flash