Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Help for interfacing LM35 on atmega16

Status
Not open for further replies.

a4arijit

Newbie level 6
Newbie level 6
Joined
May 16, 2011
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
India
Activity points
1,485
Hi,
I am presently trying to build up a project on a temperature sensor with the help of LM35DZ using an atmega16 uC and trying to display the result on a 16x2 LCD...I have compiled a code but its not working(since I'm a complete noob)...I am posting the code in this thread..Please correct me,any help will be highly appreciated..
____________________________________________________
Code:

#include <mega16.h>
#include <delay.h>
#include <stdio.h>
#include <lcd.h>

#asm
.equ __lcd_port=0x18 ;PORTB
#endasm


#define ADC_VREF_TYPE 0x60

unsigned int i;
unsigned char j;
unsigned char adc_val;
unsigned int adc_volt;


void adc_test()
{



for(j=0;j<3;j++)
{
for(i=0;i<6;i++)
{
adc_val = read_adc(i);
adc_volt = (adc_val * 195.3)/10;

}
delay_ms(500);

}


}



void main()
{

unsigned char rows=2;
unsigned char cols=16;


lcd_init(cols);
lcd_clear();

lcd_gotoxy((cols/2)-6,(rows/2)-1);
lcd_putsf("Temp Reading=");
lcd_gotoxy((cols/2)-3,(rows/2));
lcd_putsf("adc_volt");


}

_____________________________________________________
 

Hi,
I am presently trying to build up a project on a temperature sensor with the help of LM35DZ using an atmega16 uC and trying to display the result on a 16x2 LCD...I have compiled a code but its not working(since I'm a complete noob)...I am posting the code in this thread..Please correct me,any help will be highly appreciated..

Which compiler did you try?
It will not work in AVR-GCC (winavr) , your code is written for codevisionAVR

Alex
 

put the circuit also........
**broken link removed**

http://www.8051projects.net/e107_files/public/1288161733_30870_FT37769_cd.png

---------- Post added at 11:59 ---------- Previous post was at 11:58 ----------

Which compiler did you try?
It will not work in AVR-GCC (winavr) , your code is written for codevisionAVR

Alex



I compiled it with CVAVR...the error its generating is that "pointer to the function 'adc_val = read_adc(i);' must be written"
 

There is no read_adc(); in codevision and you haven't included any such function in your code too.
You also haven't included any initialization code for the ADC (REF source, ADC clock etc.), use the codewizard to generate the initialization file and then add you code.

Alex
 

/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
HP InfoTech, Development Tools for Microcontrollers, C Compilers, In-System Programmers

Project :
Version :
Date : 6/11/2011
Author :
Company :
Comments:


Chip type : ATmega16
Program type : Application
Clock frequency : 16.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/

#include <mega16.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>

#include <delay.h>

#define ADC_VREF_TYPE 0x00

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 250.000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: None
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x86;

// LCD module initialization
lcd_init(16);

while (1)
{
// Place your code here

};
}

---------- Post added at 15:09 ---------- Previous post was at 15:08 ----------

In this code i cant find the integer which the ADC has converted and display it on the LCD..
 

you have to call the function below and the result is returned by the function


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
 
// for example 
unsigned int my_adc_result; // variable to store the result
my_adc_result = read_adc(0);  // make the conversion for channel 0 and read the result




Alex
 
In this code i cant find the integer which the ADC has converted and display it on the LCD..

The integer is ADCW. In the function:

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
 
// for example 
unsigned int my_adc_result; // variable to store the result
my_adc_result = read_adc(0);  // make the conversion for channel 0 and read the result



The integer is returned when called. The returned integer is ADCW. When you do something like this:
Code:
unsigned int my_adc_result; // variable to store the result
my_adc_result = read_adc(0);  // make the conversion for channel 0 and read the result

The integer is assigned to my_adc_result. So, my_adc_result contains the value that the ADC has converted.

Hope this helps.
Tahmid.
 
This is my program using ATmega16 and CodevisionAVRCompiler.
I'm sorry the program explanation using Indonesian language, but this program is work.

Code:
/*
About Program:
Program LM35 AVR ADC 10bit  :)
Program ini akan menampilkan temperature dengan satuan CELCIUS yang didapat
dari sensor temperature LM35. LM35 dihubungkan ke PINA.0 atau ADC 0
dalam aplikasi real, mungkin diperlukan buffer dan bisa dibuat dari
opamp single supply misal LM358. Jangan lupa kalo mo dibuat beneran, PIN AVCC
ADC dihubungkan ke 5V yg stabil, terus PIN AREF dikasih BYPASS CAPASITOR ke GND
100nF sudah cukup.

perhitungan pake 1024 (jumlah total data 10bit) dan bukan 1023 (jumlah maksimal
data dari 10bit). Dibaca aja di keterangan dalam program..

Happy Programming^^

Herlambang Aribowo

#####################################################################
Compiler: CodeVisionAVR V2.03.9
Chip    : ATmega16 X-tall 4Mhz
FUSE: H:C9 L:2F  Brownout@4.5V,WDT ON,BOD ON,SPI EN,X-tall High Freq. 
FUSE: H:C9 L:AF  Brownout@2.7V,WDT ON,BOD ON,SPI EN,X-tall High Freq.
#####################################################################
*/
#include <mega16.h>
#include <delay.h>
#include <stdio.h>

// Alphanumeric LCD Module functions
#asm 
   .equ __lcd_port=0x15 ;PORTC
#endasm
#include <lcd.h>

#define ADC_VREF_TYPE 0xC0 //Internal

unsigned char buffer[16]; //Untuk buffer sprintf
float temperature; //Untuk data perhitungan temperature (float)
unsigned int temporary; //Untuk temporary data ADC (komparasi)

void updatetemp(void);//Fungsi untuk pengolahan data ADC ke temperature
void sett_regs(void); //Fungsi untuk setting register di awal proses
unsigned int read_adc(unsigned char adc_input);//Fungsi baca ADC

// Main function
void main(void){
//--------------- Setting IO and peripheral at startup!
sett_regs();
_lcd_ready();
//--------------- Time for going CRAZY (looping forever)..
for(;;){ //mainloop looping forever until ERROR/POWER SHUTDOWN/RST/WDT ACTIVE
    #asm("wdr") //kick your DOG before DEAD! hwahwa... :D   
    updatetemp();
    #asm("nop")
    };
}

void updatetemp(void){
if (temporary != read_adc(0)){//bila ada data baru, tampilkan
    //ADC = ( Vin * 1024 / Vref )
    //misal, temperature LM35 = 30°C, Vin = 300mV = 0.3V, 
    //jadi nilai ADC = (.3*1024/2.56)=120, 120/30 = 4
    //Persamaan bisa disederhanakan dengan output data ADC/4   
    temperature = read_adc(0)/4; //hanya untuk Vref 2.56 
    lcd_gotoxy(0,0);
    lcd_putsf("WWW.NUBIELAB.COM");
    lcd_gotoxy(0,1);            
    sprintf(buffer,"SUHU: %0.1f%cC  ",temperature,0xDF);
    lcd_puts(buffer); 
    temporary = read_adc(0);
    delay_ms(100);
    }
}

// Function for setting register
void sett_regs(void){
// Port a initialization
PORTA=0x00;DDRA=0x00;
// Port b initialization 
PORTB=0x00;DDRB=0x00;  
// Port c initialization 
PORTC=0x00;DDRC=0x00; 
// Port D initialization
PORTD=0x00;DDRD=0x00;

// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: Free Running
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA2;
SFIOR&=0x1F;

// LCD module initialization
lcd_init(16);

ACSR=0x80;
SFIOR=0x00;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
#pragma optsize-
WDTCR=0x1F;
WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
}

// Routine baca ADC
// Jangan lupa AVCC ke +5V biar ADCnya bekerja :D
// Connected a 0.1uF bypass capacitor at AREF pin as per datasheet, 
// “Internal 2.56V Voltage Reference with external capacitor at AREF pin”. 
unsigned int read_adc(unsigned char adc_input){
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

You can download complete file project and C source and also simulation file (Proteus ISIS) in attached file. You can open the .dsn file using Proteus ISIS Version 7.4Sp3 or later.

Below is an image captured from Proteus ISIS simulation, please click to enlarge.
lm35_Proterus_isis.jpg

source: **broken link removed**

Happy programming.. :D

Regards,

Herlambang Aribowo.
 

Attachments

  • LM35_01.rar
    148.2 KB · Views: 193
Last edited:
#include <mega16.h>
#include <delay.h>
#include <stdio.h>
#include <math.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>

#define ADC_VREF_TYPE 0x00 //Internal

unsigned char buffer[16]; //To the buffer sprintf
int temperature; //For the calculation of temperature data (float)
unsigned int temporary; //ADC for temporary data (comparison)

void updatetemp(void);//Functions for processing the ADC data to the temperature
void sett_regs(void); //Function for setting the registers at the beginning of the process
unsigned int read_adc(unsigned char adc_input);//Fungsi baca ADC

// Main function
void main(void){
//--------------- Setting IO and peripheral at startup!
sett_regs();
_lcd_ready();
//--------------- Time for going CRAZY (looping forever)..
for(;;){ //mainloop looping forever until ERROR/POWER SHUTDOWN/RST/WDT ACTIVE
#asm("wdr") //kick your DOG before DEAD! hwahwa... :D
updatetemp();
#asm("nop")
};
}

void updatetemp(void){
if (temporary != read_adc(1))
{
//ADC = ( Vin * 1024 / Vref )
//example, temperature LM35 = 30°C, Vin = 300mV = 0.3V,
//so the value ADC = (.3*1024/5)=61.44, 61.44/30 = 2.048
//The equation can be simplified by output data ADC/2.048
temperature = read_adc(1)/2.048; //only for Vref 5
lcd_gotoxy(2,0);
lcd_putsf("Temperature=");
lcd_gotoxy(6,1);
sprintf(buffer,"%d%cC",temperature,0xDF);
lcd_puts(buffer);
temporary = read_adc(1);
delay_ms(100);

}
}

// Function for setting register
void sett_regs(void){
// Port a initialization
PORTA=0x00;DDRA=0x00;
// Port b initialization
PORTB=0x00;DDRB=0x00;
// Port c initialization
PORTC=0x00;DDRC=0x00;
// Port D initialization
PORTD=0x00;DDRD=0x00;

// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: Free Running
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA2;
SFIOR&=0x1F;

// LCD module initialization
lcd_init(16);

ACSR=0x80;
SFIOR=0x00;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
#pragma optsize-
WDTCR=0x1F;
WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
}

// Routine baca ADC
// Jangan lupa AVCC ke +5V biar ADCnya bekerja :D
// Connected a 0.1uF bypass capacitor at AREF pin as per datasheet,
// “Internal 2.56V Voltage Reference with external capacitor at AREF pin”.
unsigned int read_adc(unsigned char adc_input){
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

---------- Post added at 14:34 ---------- Previous post was at 14:29 ----------

This is the working program for Lm35 with Atmega16 using its external 16MHz crystal oscillator..The ADC voltage ref is the AREF pin having 5.1v...I've converted the indonesian to english...the program works fine but i am unable to print the value on float point..so i had to assign integer for the variable..when the variable is assigned as a float it tends to print a result "1f"...but can anyone help me on printing the value as a float???

---------- Post added at 14:37 ---------- Previous post was at 14:34 ----------

And really thanx to "herlambang","Tahmid" and "alexan_e" for their help...
 

In this code
Code:
 if (temporary != read_adc(1))
    {
//ADC = ( Vin * 1024 / Vref )
//example, temperature LM35 = 30°C, Vin = 300mV = 0.3V,
//so the value ADC = (.3*1024/5)=61.44, 61.44/30 = 2.048
//The equation can be simplified by output data ADC/2.048
        [B]temperature = read_adc(1)/2.048; //only for Vref 5[/B]  // [B][COLOR="#FF0000"]NOTE1[/COLOR][/B]
        lcd_gotoxy(2,0);
        lcd_putsf("Temperature=");
        lcd_gotoxy(6,1);
        sprintf(buffer,"%d%cC",temperature,0xDF);
        lcd_puts(buffer);
        temporary = read_adc(1);
        delay_ms(100);

    }

NOTE1
The division result is stored in an integer so you will get 0 in almost any result [EDIT I was wrong, I thought you were dividing with 2048, I just noticed it was 2.048], you can either use float to store and show the result or you can multiply the result with a value like 10000 and then store the result to an integer
in your case a simple read_adc(1)/2 can give the temperature (5v reference), take a look Interfacing Temperature Sensor with AVR Microcontrollers - LM35 | eXtreme Electronics

When you want to use the float version of sprintf go to project -> configure -> c compiler and change sprintf features to float,width.precision
The multiplication method is much better because it uses less resources but you can do any of them.

Alex
 
Thanks again alexan_e...It worked.Changing the variable types at project configuration did the job...I am posting the final code which actually works along with all the settings..

Settings::

Chip:Atmega16
Clock:16MHz
ADC Channel:2nd ADC channel is used
ADC frequency:250KHz (Use this frequency for precision)
Reference voltage for ADC:AREF pin (5v)
LCD Port:portB
Compiler:CodeVisionAVR
HEX file burner:eXtreme Burner

Code :

#include <mega16.h>
#include <delay.h>
#include <stdio.h>
#include <math.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>

#define ADC_VREF_TYPE 0x00 //Internal

unsigned char buffer[16]; //For sprintf buffer
unsigned char bufferr[16];
float temperature; //For the calculation of temperature data (float)
float temperaturef;
unsigned int temporary; //ADC for temporary data (comparison)

void updatetemp(void);//Functions for processing the ADC data to the temperature
void sett_regs(void); //Function for setting the registers at the beginning of the process
unsigned int read_adc(unsigned char adc_input);//Read ADC function

// Main function
void main(void){
//--------------- Setting IO and peripheral at startup!
sett_regs();
_lcd_ready();
//--------------- Time for going CRAZY (looping forever)..
for(;;){ //mainloop looping forever until ERROR/POWER SHUTDOWN/RST/WDT ACTIVE
#asm("wdr") //kick your DOG before DEAD! hwahwa... :D
updatetemp();
#asm("nop")
};
}

void updatetemp(void){
if (temporary != read_adc(1))
{
//ADC = ( Vin * 1024 / Vref )
//Example, temperature LM35 = 30°C, Vin = 300mV = 0.3V,
//so the value ADC = (.3*1024/5.1)=60.235, 60.235/30 = 2.007
//The equation can be simplified by output data ADC/2.007
temperature = read_adc(1)/2.007; //only for Vref 5.1
temperaturef = ((9*temperature)/5)+32; // for fahrenheit conversion
lcd_gotoxy(2,0);
lcd_putsf("Temperature");
lcd_gotoxy(1,1);
sprintf(buffer,"%0.1f%cC",temperature,0xDF); //0xDF is for printing degree
lcd_puts(buffer);
lcd_gotoxy(9,1);
sprintf(bufferr,"%0.1f%cF",temperaturef,0xDF);
lcd_puts(bufferr);
temporary = read_adc(1);
delay_ms(100);

}
}

// Function for setting register
void sett_regs(void){
// Port a initialization
PORTA=0x00;DDRA=0x00;
// Port b initialization
PORTB=0x00;DDRB=0x00;
// Port c initialization
PORTC=0x00;DDRC=0x00;
// Port D initialization
PORTD=0x00;DDRD=0x00;

// ADC initialization
// ADC Clock frequency: 250.000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: Free Running
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x86;
SFIOR&=0x1F;

// LCD module initialization
lcd_init(16);

ACSR=0x80;
SFIOR=0x00;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
#pragma optsize-
WDTCR=0x1F;
WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
}

// Routine read ADC
// Do not forget to supply +5 V to AREF to work
// Connected a 0.1uF bypass capacitor at AREF pin as per datasheet,
// “Internal 2.56V Voltage Reference with external capacitor at AREF pin”.
unsigned int read_adc(unsigned char adc_input){
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

---------- Post added at 21:13 ---------- Previous post was at 21:11 ----------

Hope others find this thread useful...Thankyou all..
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top