PDA

View Full Version : Seven segment Interfacing code



buntyshubho
11-08-2008, 10:17 AM
Hello everyone,
I'm a beginner to uC and I am trying to build a temperature display using LM35D and atmega32L.
Some notes:
LM35D is a temperature sensor whose output voltage is directly proportional to surrounding temperature.

In LM35D, if surrounding temperature is 100C(celcius) then o/p voltage would be 1V. If surrounding temperature is 32.5C, o/p voltage would be 0.325V. Hope you understand the relationship between temperature and o/p voltage.

The Idea is to take output of LM35D, and put it into the ADC port A0 of atmega32. Then transfer this data to three seven-segment displays connected to the three ports(B,C,D) of atmega32L.

For example,
If surrounding temperature is 32.5C, I want "5" to be displayed on seven segment connected to port B. "2" on seven segment connected to port C and "3" on seven segment connected to port D.

Also, I am using a bcd to seven segment decoder IC MC 7447.
So all I need to do is:
After getting the voltage from ADC, reconvert it to decimal format, split up the digits, and put them into the three respective ports. And only the lower four bits (Eg:B0,B1,B2,B3) are used for this purpose.

The code I made isnt working. Please tell me where have I made a mistake????I have used codevision for programming.

the code is as shown below:



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

unsigned int read_adc()
{
unsigned char temp;
int i;
unsigned int value;
do
{
temp=ADCSRA & 0x40;
}
while(temp);//loop to disregard the 1st read.

ADCSRA=0xC4;
for(i=0;i<5;i++) //more reads for greater accuracy
{
do
{
temp=ADCSRA & 0x40;
}
while(temp) ;
}

value=ADCW;

return value;


}

void display(unsigned int a)
{
unsigned int x=0;
x=a%10;
a=a/10;
PORTB=x;//I'm especially not sure about this step

x=a%10;
a=a/10;
PORTC=x;

x=a%10;
a=a/10;
PORTD=x;
}


void main(void)
{
unsigned int adc;
unsigned int vin;
PORTA=0x00;
DDRA=0x00;

PORTB=0x00;
DDRB=0xFF;

PORTC=0x00;
DDRC=0xFF;

PORTD=0x00;
DDRD=0xFF;



ADCSRA=0xC6; //start conversion with internal prescalar of 64
ADMUX=0xC0; //using internal reference voltage of 2.56v

while (1)
{
adc=read_adc();
vin=((adc*2.56)/1024)*1000; //reconverting it to decimal format and multiplying by 1000.

display(vin);
delay_ms(5000);



};
}





Please tell me what is my mistake????? :(

ashish_agarwal123456
11-08-2008, 12:08 PM
1) i am not sure whats in ADCW. i mean 10bits or 16bits and in which form. check it????
2) make sure you have a voltage divider at input of A0.

most probably above two will correct your problem. After that try to optimize your code. there are many procedures you dont need. like taking the first reading and then throwing it. taking multiple readings in the name of higher accuracy.
also the way you provided the delay for conversion kept me thinking for 5minutes. but that depends on programming habit. i generally use
while(ADCSRA!=0b1001xxxx); //replace xxxx with your settings

avinash_g
11-08-2008, 12:41 PM
Hi
as Ashish said your code need some "hand optimization". No problem with voltage divider as LM35 does not need such. The o/p is directly proprotional to voltage.

I suggest following.

1) You are using so many lines of MCU to drive the displays the proper way is multiplexing see
http://extremeelectronics.co.in/avr-tutorials/multiplexed-seven-segment-displays/

2) You are using external ICs (decoders) even if u have such powerfull mcu.

3) Try to be modular check each modules separatly. I suggest go for

First Understand basics of Seven Segments
http://extremeelectronics.co.in/avr-tutorials/interfacing-seven-segment-displays/

Second Try out multiplexing
http://extremeelectronics.co.in/avr-tutorials/multiplexed-seven-segment-displays/

Then go learn and test ADC
http://extremeelectronics.co.in/avr-tutorials/using-the-analog-to-digital-converter/

After that mix both and create ur dream thermometer
http://extremeelectronics.co.in/avr-tutorials/interfacing-temperature-sensor-lm35/

For further help ask me

buntyshubho
11-08-2008, 07:54 PM
Hey, thanks for your replies guys. I finally found the solution to the problem:D, I'll post it here for reference.

Suppose the temperature is 25C, then i/p to PA0 is 0.25V
then using the formula adc=Vin*1024/2.56, i got the adc value which I put in the following equation:


vin=((adc*2.56)/1024)*1000; //(say equation 1)

the above mentioned line is present in the infinte while loop in main().

When adc value is put in above equation, the answer comes out to be 250
If i/p to adc is 0.227C, then o/p of above equation would be 227 (I hope you understand this)

Now consider this, if temperature is 32.5C, then i/p to PA0 is 0.325v
Therefore o/p of above equation is 325.
Now closely look at what kind of a variable "vin" is.....in my code I mentioned it as "unsigned int"..which can hold values only from 0 to 255.

Thats why, in this case, "vin" did not store any values calculated by the above formula(equation 1).
So we needed an int variable with more bit storing capacity and hence changed it to "unsigned long int". This enabled us to store values above 255 in the variable "vin"

Also in the function display(), change the variable "a" to "unsigned long int"

Hope this clears the matter!!!!
I never thought this would be the problem, but spending an entire night with this code helped a lot!!!
Thanks again for all your help!!! :)

docel
11-08-2008, 11:40 PM
Since we have SOoo many links on this thread, Let me add one more......

Clikie here (http://debusinnovations.blogspot.com/) .....like debu says!!!