Maker Pro
Maker Pro

LCD with pushbutton

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
I made code, that when you push the button it will count. But when you press it for a long time, it still increments and still counts.How can I make it such that if I press it even too long, it only counts once? Thank you very much in advance.

Code:
[#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include "lcd.h"


int main (void)
{
    
    hw_lcd_init();
    DDRB &= ~(1 << PINB0); 
    PORTB |= (1 << PINB0); 
    //int PRESSED = 0;
    int COUNT = 0;
    char buffer [16];
    lcd_clrscr();
    while(1) {
        sprintf(buffer,"%d",COUNT);        
        lcd_puts_wrap(buffer);
        
        if ((PINB & (1<<PINB0))){
            //BUTTON IS NOT PUSH        
    
        }else{
            //BUTTON IS PUSHED
            COUNT=COUNT+1;
        }
        _delay_ms(100);
    }        
    return 0;
}
 
Last edited by a moderator:

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
You don't tell us which MC you use. From your code it should be an Atmel AVR. I do not have the LCD.h, but anyway: you introduce a state variable (button_state) to keep track of whether the button has already been pressed or not. This varaible is set when a first change from not-pressed to pressed occurs. Also in that case the counter is incremented by 1.
If during the next pass of the loop the button is still pressed, this will be detected since the state variable is already set. Therefore the count will not be incremented.
When in one pass of the loop it is detected that the button is not pressed, the state variable is reset. See my code example.

Note that you have made no provisions for debouncing the pushbutton. So you may occasionally see the count increment by more than one. If you're lucki the rest of the loop takes so long that debouncing is not necessary.
[edit]: I didn't see the 100ms delay loop immediately. This will suffice to suppress any bouncing. Sorry

Code:
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
/* #include "lcd.h" */


int main (void)
{
int button_state;
button_state = 0;	/* set button state to not pressed */ 

hw_lcd_init();
DDRB &= ~(1 << PINB0); 
PORTB |= (1 << PINB0); 
//int PRESSED = 0;
int COUNT = 0;
char buffer [16];
lcd_clrscr();
while(1) {
sprintf(buffer,"%d",COUNT); 
lcd_puts_wrap(buffer);

if ((PINB & (1<<PINB0))){
//BUTTON IS NOT PUSH 
   button_state = 0;   /* set button state to not pressed */ 
}else{
	if (button_state == 0) { /* button not yet pressed */
//BUTTON IS PUSHED
		button_state = 1;   /* set button state to pressed */
		COUNT=COUNT+1;
	}
}
_delay_ms(100);
} 
return 0;
}
 

CocaCola

Apr 7, 2012
3,635
Joined
Apr 7, 2012
Messages
3,635
You can also insert a conditional WHILE LOOP after the COUNT=COUNT+1 put the program in a "WHILE Pressed" loop waiting until the button is released before it continues...
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
The advantage of CocaCola's approach is that you do not need a state variable. Useful if you run out of memory.
The disadvantage is that you can't do anything else useful during the waiting time (unless you put it into the WHILE loop, too).

In my approach both aspects are reversed.

It's up to you to decide which approach suits your application more. From the code fragment you've shown us it wouldn't make a difference.
 

foTONICS

Sep 30, 2011
332
Joined
Sep 30, 2011
Messages
332
I agree with both these guys, although Harolds approach would be beneficial if you ever wanted to add options to your program later on
 

CocaCola

Apr 7, 2012
3,635
Joined
Apr 7, 2012
Messages
3,635
As Harald said it's all about what you need or want the program to do in the end... I use flags all the time just like he suggested when it's beneficial to the overall program and I will use conditional 'pauses' when it works for that program... There are plenty of times when a program doesn't need to be doing anything when the button it pressed (and many times when I prefer it just wait) and there are plenty of other times when it needs to do things, it just depends on the program...
 

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
Thank you sirs', I learned much. I also did the flag similar Harald yesterday but it didn't work. But when I saw his code, I fully understand how to use flag, and it worked. I will also try to do CocaCola's approach...
 

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
In connection with this code, i connect a pulse generator that when I turn it on, it will count and also will display the same count in the LCD. And the pushbutton was programmed that when it is pressed it should reset the display on the LCD.

Code:
int buffer [16];
int main void
sprintf(buffer, "Count:%d", count); 
lcd_puts(buffer);

...in the main routine,
a) the pulse generator was set to on, the lcd display start to count
COUNT = COUNT + 1;
b) When the button is pushed,
COUNT = 0;

...I am expecting that the output will be like this:
COUNT:0

But it shows like this:

COUNT:236 //if LCD display counts
COUNT:036 //it will reset only one digit

What am I lacking?
 
Last edited by a moderator:

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
I put memset and initialize that the buffer like this:
buffer [0]= '\0'
...but it doesn't clear the display back to zero.
 

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
yes, I used char but it doesn't work. Here is my code:

Code:
 int main (void)
{
	int button_flag;
	button_flag = 0;
	
	int button_flag2;
	button_flag2 = 0;

	hw_lcd_init();
	DDRB &= ~(1 << PINB1); //counter
	PORTB |= (1 << PINB1);
	DDRB &= ~(1 << PINB0); //pushbutton
	PORTB |= (1 << PINB0);
	
	
	int COUNT=0;
	char buffer [16]= {0};
	buffer [0] = '\0';
	

	lcd_clrscr();
	
	while(1) {
		
		sprintf(buffer,"%d",COUNT);
		lcd_puts_wrap(buffer);
		
		if ((PINB & (1<<PINB0))){
			button_flag2 = 0;   // set button to not pushed
		}else{
			if (button_flag2 == 0) { 
			//button IS PUSHED
			button_flag2 = 1;   //set button to pushed
			COUNT =0;
			memset(&buffer[0],0,strlen(buffer));
		}
	}
	
		if ((PINB & (1<<PINB1))){
			//COUNTER IS NOT PUSH
			button_flag = 0;   // set counter to not pushed
		}else{
			if (button_flag == 0) { 
			button_flag = 1;   //set counter to pushed
			COUNT = COUNT+1 ;
		}
	}
		}
		
		return 0;
	}
 

dahhal

Jul 17, 2012
58
Joined
Jul 17, 2012
Messages
58
you might want to try to bring back the 100 ms delay you had before.

The delay would have helped to debounce the circuit,

Have you got the code for lcd_puts_wrap()? I would guess you don't need all that memset jazz. A routine like that should print every character until a null chararcter '\0' or carriage return '\r' depending on the established protocol.
 

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
delay just slows down the display in the LCD and would not much the count in the counter or pulse generator. lcd_puts_wrap came from a customize library of Fluery. And was made by my boss.
 

dahhal

Jul 17, 2012
58
Joined
Jul 17, 2012
Messages
58
seems your logic is more complex then the first time you posted it.

The logic is confusing, as the varible names are not great. It would be best to use variable names that make sense to the application. Are you counting all the times that the pulsegenerator goes from a low to high transition, and when the pushButton does a low to high transition. If so the names should reflect it.

is the issue that you have some sort of overflow in what you want printed on the LCD? In your situation I would try to find some usage of the r lcd_puts_wrap() function. In my last post I wasn't saying it was bad code, I was just trying to understand the input that the sub routine expects. If you don't have access to the code, try to find spec, or working examples from other projects that use the code.
 
Top