Maker Pro
Maker Pro

Programming of MUC

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
Hi everyone. :)
I am working on a code where i need to display messages on LCD depending on the input to MUC(Atmega32A).

Below is the program where i need to display messages based on PortA input.

First. i'll read the pin0 of PORTA (continously). Depending on the value of that pin i'll control LCD messages. I know i have made lot of mistakes in programming. This is my first program so i am unaware of what to use.
Is this programming method correct ? or do i need to use some other method ?:confused:
Please help me.



int main()
{
DDRA = 0x00; //configure portA as input
while(1) // To run the program continuously
{
if(PORTA&=1<<PINA0) //Check high on pin0 of portA
{
DDRB=0xff; // Configure PORTB as output for data bus
DDRD=0x07; //Configure PORTD as output for control lines
init_LCD(); // initialization of LCD
_delay_ms(50); // delay of 50 mili seconds
LCD_write_string("ABC");
}
else
{
DDRB=0xff;
DDRD=0x07;
init_LCD();
_delay_ms(50);
LCD_write_string("Thank you");
}

}

return 0;
}
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
What does your program actually do (does it work)? Are there any bugs?
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
What does your program actually do (does it work)? Are there any bugs?

Thanks for replying.:)
Bro there was a mistake in if(PORTA&=1<<PINA0). I corrected it by changing to if(bit_is_clear(PINA,0)) //Check pin0 of portA.

The program reads the values from input port. If it is high then message A is displayed else message B is displayed. The program now works.:)
My doubt is since i am reading the value from a sensor in real-time continuously. Is this the best way to read the values or are there any other way like using interrupts etc ?
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,743
Joined
Nov 17, 2011
Messages
13,743
i am reading the value from a sensor in real-time continuously
This is called polling. Not an unusual method and not bad if your µC has enough time for it.

Whether you need to monitor the sensor continuously depends on your application. If you need to react very fast to a change in sensor signal, you need to poll often. If you can tolerate a small delay in the reaction to the sensor signal, you can reduce the poll rate and do other things in between.
You could, for example, use a timer to trigger readout of the sensor every fes milliseconds. But then again that usually means you have the timer generate an interrupt to start the sensor-read routine. It is more logical to use the sensor as interrupt source in the first place.
Using a direct interrupt is suitable if your sensor signal is digital (as it is here). Your µC can now perform any other operations and will be alerted to a change in the sensor signal by an interrupt. Good if you have to perform other tasks than monitoring the sensor.
An interrupt would not be suitable if for example your sensor is analog and you need to A/D-convert the input signal. A change in analog level will generally not trigger an interrupt, so you need to poll. Unless, that is, your analog input has a programmable comparator (see e.g. here). This feature is not typically available.
 
Last edited:

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
This is called polling. Not an unusual method and not bad if your µC has enough time for it.

Whether you need to monitor the sensor continuously depends on your application. If you need to react very fast to a change in sensor signal, you need to poll often. If you can tolerate a small delay in the reaction to the sensor signal, you can reduce the poll rate and do other things in between.
You could, for example, use a timer to trigger readout of the sensor every fes milliseconds. But then again that usually means you have the timer generate an interrupt to start the sensor-read routine. It is more logical to use the sensor as interrupt source in the first place.
Using a direct interrupt is suitable if your sensor signal is digital (as it is here). Your µC can now perform any other operations and will be alerted to a change in the sensor signal by an interrupt. Good if you have to perform other tasks than monitoring the sensor.
An interrupt would not be suitable if for example your sensor is analog and you need to A/D-convert the input signal. A change in analog level will generally not trigger an interrupt, so you need to poll. Unless, that is, your analog input has a programmable comparator (see e.g. here). This feature is not typically available.

Thank you sir.:) This is what i wanted to know.
My application is not crucial so delay of milliseconds won't bother me. I'll got with the easy method
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
Bear in mind that you should not update the LCD from within an interrupt handler, for several reasons: it probably takes a significant amount of time to update the LCD, and interrupt handlers should take as little time as possible, and other parts of your program may need to update the LCD now or in the future, and interrupting them with other LCD programming commands will break the command in progress so when the interrupt handler returns, the LCD will be in the wrong state to continue the command that was being sent (that was interrupted).

Beyond that, first, you should be initialising the DDR (and any other registers) for communicating with the LCD only at the start of your program; there's no need to repeat the initialisation within the conditional section of your code, and there is also no need to update the LCD if the input state hasn't changed. I would structure the program like this:

main() {
// initialise DDRs, etc
while (1) {
update_lcd_from_port_status();
// do other stuff
}//while
}//main

void update_lcd_from_port_status(void) {
static int last_port_status = -1;
int new_port_status;
new_port_status = bit_is_set(PINA, 0);
if (new_port_status != last_port_status) { // Port status has changed
last_port_status = new_port_status;
LCD_write_string(new_port_status ? "ABC" : "Thank you");
}//new!=last
}//update_lcd_from_port_status

This design has a separate function, update_lcd_port_status(), which is called repeatedly from the while(1) loop in the mainline. This function keeps a record of the last known input port status in static variable last_port_status and only updates the LCD when the port status changes.
 
Last edited:

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
Bear in mind that you should not update the LCD from within an interrupt handler, for several reasons: it probably takes a significant amount of time to update the LCD, and interrupt handlers should take as little time as possible, and other parts of your program may need to update the LCD now or in the future, and interrupting them with other LCD programming commands will break the command in progress so when the interrupt handler returns, the LCD will be in the wrong state to continue the command that was being sent (that was interrupted).

Beyond that, first, you should be initialising the DDR (and any other registers) for communicating with the LCD only at the start of your program; there's no need to repeat the initialisation within the conditional section of your code, and there is also no need to update the LCD if the input state hasn't changed.

Thanks a lot sir.:) I got the correction done. It worked. I added a line to clear the LCD on it's each update.

void update_lcd_from_port_status(void) {
static int last_port_status = -1;
int new_port_status;
new_port_status = bit_is_set(PINA, 0);
if (new_port_status != last_port_status) { // Port status has changed
LCD_cmd(0x01); //To clear the lcd
last_port_status = new_port_status;
LCD_write_string(new_port_status ? "ABC" : "Thank you");
}//update_lcd_from_port_status

Sir which command is used to clear the cursor on LCD ? I have attached the picture wherein i need to remove the cursor.
 

Attachments

  • DSC_6318.JPG
    DSC_6318.JPG
    57.7 KB · Views: 127

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
Sir which command is used to clear the cursor on LCD ? I have attached the picture wherein i need to remove the cursor.

I don't know. You haven't even told us the part number of the LCD display! My crystal ball is having its 10,000 km lube and oil change this week!

You have the data sheet for it, right? You should be able to figure out what command to use, if there is one.
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
I don't know. You haven't even told us the part number of the LCD display! My crystal ball is having its 10,000 km lube and oil change this week!

You have the data sheet for it, right? You should be able to figure out what command to use, if there is one.

Okay sir. I am new to these stuff so i didn't had much idea about it. I'll try to find it in datasheet.
 

gorgon

Jun 6, 2011
603
Joined
Jun 6, 2011
Messages
603
To turn the cursor off you need to reset bit1 in the displaycontrol command to '0'

The format for this command is 00001DCB - where bit0(B) is the blink control, bit1(C) is the cursor control, an bit2(D) is the display on/off control.

I suppose this is done in the init_LCD(); function, so you need to look it up there.

Note that this is the command for the HD44780 LCD controller, the one normally used for these displays.
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
To turn the cursor off you need to reset bit1 in the displaycontrol command to '0'

The format for this command is 00001DCB - where bit0(B) is the blink control, bit1(C) is the cursor control, an bit2(D) is the display on/off control.

I suppose this is done in the init_LCD(); function, so you need to look it up there.

Note that this is the command for the HD44780 LCD controller, the one normally used for these displays.

Thank you sir. I followed the same steps you mentioned . I got it.
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
void update_lcd_from_port_status(void) {
static int last_port_status = -1;
int new_port_status;
new_port_status = bit_is_set(PINA, 0);
if (new_port_status != last_port_status) { // Port status has changed
last_port_status = new_port_status;
LCD_write_string(new_port_status ? "ABC" : "Thank you");
}//new!=last
}//update_lcd_from_port_status

Sir what do you mean by
static int last_port_status = -1;
I could not understand that portion.I mean why have you assigned it to -1 ?
Please reply.
 

gorgon

Jun 6, 2011
603
Joined
Jun 6, 2011
Messages
603
-1 is the same as FFh.
static tell you that it will only set this variable to -1 the first time, and then keep the current value, whatever it is.
 
Last edited:

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
I assigned -1 (equal to 0xFFFF for a 16-bit integer) initially so that the first time update_lcd_from_port_status() is called, it will unconditionally update the LCD. This is guaranteed because the actual port status is 0 or 1 (FALSE or TRUE), and the first time the function is called, this will necessarily be different from the value in last_port_status, so the LCD will be updated.

Once the function has been called once, last_port_status will be either 0 or 1 and the LCD will only be updated if the port status changes from its previous value.

To put it another way, assigning -1 to last_port_status is equivalent to saying that the last known port status is "neither high nor low", so the first time the new port status is tested, it will always be detected as "different from the last port status" and the LCD will be necessarily be updated.

I could have used 2 instead of -1. Any value that isn't 0 or 1 will ensure this behaviour.
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
I assigned -1 (equal to 0xFFFF for a 16-bit integer) initially so that the first time update_lcd_from_port_status() is called, it will unconditionally update the LCD. This is guaranteed because the actual port status is 0 or 1 (FALSE or TRUE), and the first time the function is called, this will necessarily be different from the value in last_port_status, so the LCD will be updated.

Once the function has been called once, last_port_status will be either 0 or 1 and the LCD will only be updated if the port status changes from its previous value.

To put it another way, assigning -1 to last_port_status is equivalent to saying that the last known port status is "neither high nor low", so the first time the new port status is tested, it will always be detected as "different from the last port status" and the LCD will be necessarily be updated.

I could have used 2 instead of -1. Any value that isn't 0 or 1 will ensure this behaviour.

Thank you so much sir. That was clear to the point. I understood it.:)
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
LCD update

I assigned -1 (equal to 0xFFFF for a 16-bit integer) initially so that the first time update_lcd_from_port_status() is called, it will unconditionally update the LCD. This is guaranteed because the actual port status is 0 or 1 (FALSE or TRUE), and the first time the function is called, this will necessarily be different from the value in last_port_status, so the LCD will be updated.

Once the function has been called once, last_port_status will be either 0 or 1 and the LCD will only be updated if the port status changes from its previous value.

To put it another way, assigning -1 to last_port_status is equivalent to saying that the last known port status is "neither high nor low", so the first time the new port status is tested, it will always be detected as "different from the last port status" and the LCD will be necessarily be updated.

I could have used 2 instead of -1. Any value that isn't 0 or 1 will ensure this behaviour.

Sir i have got an issue now. I added another condition to be checked on Pin1 of PortA before checking Pin0 of PortA. So the very first time when the Pin1 goes high and the Pin0 goes high ,the LCD won't get updated.
The code is as shown below.

Code:
while(1)
	{
		update_lcd_from_port_status();
		if(bit_is_set(PINA,1))       [COLOR="DarkOrange"]//Check high on pin1 of portA[/COLOR]
		{
			if(bit_is_clear(PINA,0))	 [COLOR="DarkOrange"]//Check low on pin0 of portA[/COLOR]
			{
				PORTC&=~(1<<PINC0);      [COLOR="DarkOrange"]//Turn off buzzer[/COLOR]
				update_lcd_from_port_status();
				//LCD_write_string("Thank you");
   			 }
			else
			{
				PORTC|= 1<<PINC0;    	 [COLOR="DarkOrange"]//Turn on buzzer[/COLOR]
				update_lcd_from_port_status();
				//LCD_write_string("Buckle up");
			}
		}
		else
		{
		LCD_cmd(0x01);			[COLOR="DarkOrange"] //CLear the LCD[/COLOR]
		PORTC&=~(1<<PINC0);     [COLOR="DarkOrange"] //Turn off buzzer[/COLOR]
		}
	}
		 
	return 0;
}

void update_lcd_from_port_status(void) 
{
	static int last_port_status = -1;
	int new_port_status;
	new_port_status = bit_is_set(PINA, 0);
	if (new_port_status != last_port_status) 
	{                               [COLOR="DarkOrange"]// Port status has changed[/COLOR]
		LCD_cmd(0x01);
		last_port_status = new_port_status;
	LCD_write_string(new_port_status ? "Buckle up" : "Thank you");
	}
}									[COLOR="DarkOrange"]//Update_lcd_from_port_status
[/COLOR]
 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
The purpose of keeping last_port_status is to avoid updating the LCD each time through the loop. The program remembers the last state of the input and detects whether the input has changed. If it has, it updates the "last known value" variable and updates the LCD to reflect the change.

If you are now monitoring two pins of the port, you can still use the same idea to avoid updating the LCD continuously. In that case it's probably best to keep a variable that reflects the last information displayed on the LCD. You can use an enum to define the values for this variable:

typedef enum {
LCD_SHOWING_NOTHING,
LCD_SHOWING_THANK_YOU,
LCD_SHOWING_BUCKLE_UP
};

You initialise your "last known state" variable to LCD_SHOWING_NOTHING, because at program startup the LCD is blank or showing unknown text, then each time through the loop you calculate what the LCD _should_ say. After you've decided what the LCD should say, you compare that value to the last known LCD state variable. If they're different, update the last known state to the new state, and send the appropriate string to the LCD.

All of those calculations should be done in the update_LCD_from_port_status function, which can then be called every time through the while (1) loop in main(). Each time it is called, it calculates what the LCD _should_ show, compares that to what the LCD _is_ showing, and updates if they're different.

I hope that answers the question you have. If not, explain your question clearly.
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
The purpose of keeping last_port_status is to avoid updating the LCD each time through the loop. The program remembers the last state of the input and detects whether the input has changed. If it has, it updates the "last known value" variable and updates the LCD to reflect the change.

If you are now monitoring two pins of the port, you can still use the same idea to avoid updating the LCD continuously. In that case it's probably best to keep a variable that reflects the last information displayed on the LCD. You can use an enum to define the values for this variable:

typedef enum {
LCD_SHOWING_NOTHING,
LCD_SHOWING_THANK_YOU,
LCD_SHOWING_BUCKLE_UP
};

You initialise your "last known state" variable to LCD_SHOWING_NOTHING, because at program startup the LCD is blank or showing unknown text, then each time through the loop you calculate what the LCD _should_ say. After you've decided what the LCD should say, you compare that value to the last known LCD state variable. If they're different, update the last known state to the new state, and send the appropriate string to the LCD.

All of those calculations should be done in the update_LCD_from_port_status function, which can then be called every time through the while (1) loop in main(). Each time it is called, it calculates what the LCD _should_ show, compares that to what the LCD _is_ showing, and updates if they're different.

I hope that answers the question you have. If not, explain your question clearly.

Thanks for helping me out sir.
I followed your explanation and have understood the use of separate routine to update LCD. However, i am unable to work on the syntax. Also to give you a clear idea of my problem, i made a small video of 2 minutes. Below is the link to it please watch it sir.

 

KrisBlueNZ

Sadly passed away in 2015
Nov 28, 2011
8,393
Joined
Nov 28, 2011
Messages
8,393
I'm at my partner's house and I don't have fast internet access, so I'm afraid I cannot watch your video until Tuesday. Can ANYONE ELSE help before then? Otherwise, I will reply on Tuesday.

BTW, please don't call me sir!
 

rabhishek91

Feb 15, 2013
41
Joined
Feb 15, 2013
Messages
41
I'm at my partner's house and I don't have fast internet access, so I'm afraid I cannot watch your video until Tuesday. Can ANYONE ELSE help before then? Otherwise, I will reply on Tuesday.

BTW, please don't call me sir!

No problem bro. I'll wait till tuesday. :)
 
Top