Thursday, October 29, 2009

Building LCD Thermometer [Temperature Display in LCD Module]

Here I’ll describe how to display texts in LCD module using AVR Atmega32 and how to connect a temperature sensor to measure the current temperature and display in LCD.
First we describe the LCD we used. There are two kinds of LCD modules.

Ø LCD modules with driver
Ø LCD modules without driver

GDM 1602A is a standard LCD module with driver and controller [S6A0069] [see sample image of the LCD module we used].



Features of GDM 1602A
1. 5x8 dots
2. Built-in controller (S6A0069 or equivalent)
3. +5V power supply (also available for =3.0V)
4. 1/16 duty cycle
5. Easy interface with 4-bit or 8-bit MPU
6. BKL to be driven by pin1, pin2, or pin15, pin16 or A, K
7. 16x2 characters

Know more about your LCD module for example pin connection, what driver it has from corresponding datasheet. If you use GDM1602A see this datasheet.
The secret of success is approaching by eliminating confusions. If you have confusions then make clear your lcd basics. These links will help you very much. I’d like to share them.

http://www.geocities.com/dinceraydin/lcd/intro.htm
http://home.iae.nl/users/pouweha/lcd/lcd0.shtml

Before discussing how to display characters in LCD module let’s have some words about the temperature sensor we used. It’s most popular one which is LM35, a precision integrated-circuit temperature sensor. Let’s begin from the first.

What is a temperature sensor?
Temperature sensor is an electronic device which provides a voltage analogue of the temperature of the surface on which it is mounted.
Example, thermistor.

In other ways, an analog temperature sensor is pretty easy to explain, it's a chip that tells you what the ambient temperature is!

These sensors use a solid-state technique to determine the temperature. That is to say, they don't use mercury (like old thermometers), bimetallic strips (like in some home thermometers or stoves), nor do they use thermistors (temperature sensitive resistors). Instead, they use the fact as temperature increases, the voltage across a diode increases at a known rate. (Technically, this is actually the voltage drop between the base and emitter - the Vbe - of a transistor). By precisely amplifying the voltage change, it is easy to generate an analog signal that is directly proportional to temperature. There have been some improvements on the technique but, essentially that is how temperature is measured.

Because these sensors have no moving parts, they are precise, never wear out, don't need calibration, work under many environmental conditions, and are consistent between sensors and readings. Moreover they are very inexpensive and quite easy to use.

Types of temperature Sensors
There are big differences between different kind of temperature sensors. They may be classified into two groups:
Ø Contact
Ø Non-contact

Contact Sensors
Contact temperature sensors measure their own temperature.
One infers the temperature of the object to which the sensor is in contact by assuming or knowing that the two are in thermal equilibrium, that is, there is no heat flow between them.

Noncontact Sensors
Most commercial and scientific noncontact temperature sensors measure the thermal radiant power of the Infrared or Optical radiation that they receive from a known or calculated area on its surface, or a known or calculated volume within it (in those cases where the obect is semitransparent within the measuring wavelength passbad of the sensor).

One then infers the temperature of an object from which the radiant power is assumed to be emitted (some may be reflected rather than emitted). Sometimes the inference requires a correction for the spectral emissivity (NB: the two words, spectral & emissivity, are used together in correcting IR Thermometer readings -the "emissivity", unspecified, is a big trap which even some of the suppliers of devices and calibration equipment fall into unwittingly for a variety of reason about which one can only speculate ) of the object being measured.

Knowing how and when to apply a spectral emissivity correction is part of the inference, too, and can introduce significant errors if not done correctly. See our Trip down the E-missivity Trail to help you understand that aspect a little better.

Notes
The truism that all sensor have errors in their readings - all the time. One key secret to high quality measurement results is to have confidence in the error estimates. Neglecting to make a careful error analysis can result in error much larger than the assumed values.

A figure of the temperature sensor we used is given below.



Features of LM35

1. Calibrated directly in ° Celsius (Centigrade)
2. Linear + 10.0 mV/°C scale factor
3. 0.5°C accuracy guaranteeable (at +25°C)
4. Rated for full −55° to +150°C range
5. Suitable for remote applications
6. Low cost due to wafer-level trimming
7. Operates from 4 to 30 volts
8. Less than 60 μA current drain
9. Low self-heating, 0.08°C in still air
10. Nonlinearity only ±1⁄4°C typical
11. Low impedance output, 0.1 W for 1 mA load

To know more information on lm35 view this datasheet. Others follow your corresponding datasheet. Simply search in google with terms “datasheet” followed by your temperature sensor model.


How lm35 works?
If you are wondering how lm35 works here's it. As the temperature increases, the voltage across diode increases at a known rate. As lm35 has diodes inside it happens same there. So what lm35 does is adjusting the output voltage per oC in real.
So if lm35 outputs 10mV it means 1 oC. If it outputs 20mV then it is 2 oC.

We’ve attached the Vout of LM35 in PA0 of Atmega32. We use Atmega32 to do the analog to digital conversion. See the complete pin connection of the circuit in the image below.


Fig: Circuit Connections


If you only want to test the LCD module ignore the lm35 part and respective pin connection.
Here comes the coding part that you’re waiting for. If you’ve connected the LCD correctly with Atmega32 and provided power supply then the following code will display “Welcome to Matrices!”.

#include <mega32.h>
#include <stdio.h>
#include <delay.h>

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

// Declare your global variables here

void main(void)
{
    int i;

    // 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=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 
    PORTB=0x00;
    DDRB=0x00;

    // 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: 125.000 kHz
    // ADC Voltage Reference: AVCC pin

    // my code here
    for (i=0; i<500; i++)
   delay_ms(1);

    // LCD module initialization
    if (lcd_init(16))
        PORTC = 1;
    for (i=0; i<200; i++)
       delay_ms(1);

    lcd_gotoxy(0,0);
    lcd_putsf("    Welcome to");
    lcd_gotoxy(0,1);
    lcd_putsf("    Matrices!");

    while (1);
}


This code should be compiled in codevision avr compiler[If you don’t have download codevision from here]. Remember it is a tested code. So if it doesn’t work think again if your hardware connections are okay. Remember if lcd is not dectected lcd_init function returns 1. So you can check it by writing like this

if (lcd_init(16))
    PORTC = 1;

And you can connect a led to PC0 pin to check if led is lit. If LED is not lit then checkout lcd connections again.
After compiling the c code, burn the hex code of your program into your atmega MPU using atmel burning tools. After programming MPU is done place the it on the circuit. Now connect the power supply. I think you’ll have some fun.
To use this code with atmega16 change this line


“#include <mega32.h>”
To
“#include <mega16.h>”

In the same way, change to mega8.h for atmega8 mpu. You can download the whole project code and proteus simulation files which works perfectly for atmega32 from here.


Attaching Temperature Sensor for Displaying Temperature

If you want to know how atmega ADC works follow here.
With codevision you might be in confusion how to do a simple adc read. Don’t wonder I was worried too. But I’ve found it easy finally.

The function to read the analog data is like this one:

// if you are using AVCC as reference, to set internal voltage as reference // you need to set it to 0xC0
#define ADC_VREF_TYPE 0x40
// Read the AD conversion result 
unsigned int read_adc(unsigned char adc_input) 

    // Set ADMUX register to let it know which is your reference voltage
    ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); 
    // Delay needed for the stabilization of the ADC input voltage 
    delay_us(10); 
    // Start the AD conversion, set ADSC bit in Status register
    ADCSRA|=0x40; 
    // Wait for the AD conversion to complete, check if ADIF bit is 1, wait
    // until it is set to one
    while ((ADCSRA & 0x10)==0); 
    ADCSRA|=0x10; 
    return ADCW; 
}


Assuming this code is in top of your main function a simple call to this function will return value for analog input.

int temp;
temp = read_adc(0); // 0 means 1st input of PortA

Some images of the final project has been attached below. Click on the images to view in high resolution.


Fig: Atmega32 MPU in a Project Board


Fig: LCD connection with MPU


Fig: A Power supply of 5V has been attached





Fig: The Illumniated LCD (GDM1602A)

Download this document as doc file from here.

2 comments:

  1. Bux.to is a scam. After 3 years of bull, I still haven’t been paid. Day in and day out I used them. That is why I started my own site for those that want to legitly get paid. I pay users out of pocket and will be lowering the cashout limit to $5 and paying users $0.10 per click. That is much more than bux.to can or will ever offer since they are cheapscapes to begin with.

    Regards,
    Jake
    Owner, Lersner.com

    ReplyDelete
  2. good work. the download link is outdated thanks

    ReplyDelete