NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » coding pushbuttons

April 14, 2010
by fdlkid2
fdlkid2's Avatar

In order to learn more about switches, i decided to create a "simple" counter with momentary pushbuttons. i have 3 switches, 1 for player "a", 1 for player "b", and one for a reset. I push the button for player "a" and it goes up by one every time i push the button.

Right now when i run the code the Player "a" and Player "b" continuously scroll through the screen. I do believe the switches are working though because every time i hit player "a"'s or player "b"'s switch the screen changes into some jibberish, and when i press the reset it goes back to its normal output. anyway, wheres the code.

uint8_t button1; uint8_t button2; uint8_t button3; int16_t a1; int16_t a2; int main() {

// start up the LCD lcd_init(); lcd_home();

DDRC &= ~(1<<PC0); // set PC0 as input DDRC &= ~(1<<PC1); DDRC &= ~(1<<PC2);

// turn on the internal resistors for the pins PORTC |= (1<<PC0); // turn on internal pull up resistor for PA0 PORTC |= (1<<PC1); PORTC |= (1<<PC2);

while(1){

button1 =(PINC & (1<<PC0)) >> PC0; button2 =(PINC & (1<<PC1)) >> PC1; button3 =(PINC & (1<<PC2)) >> PC2; if(button1>0) { a1 = a1+1;

 }
 if(button2>0)
 {
 a2 = a2+1;
 }
 if(button3>0)
 {
 a1=0;
 a2=0;
 }

  lcd_write_string(PSTR("Player a "));
  lcd_write_int16 (a1);
  lcd_write_string(PSTR("          "));
  lcd_write_string(PSTR("Player b "));
  lcd_write_int16 (a2);

} return 0; }

April 14, 2010
by bretm
bretm's Avatar

What sort of jibberish are you seeing?

There's no code to wait for a button release, so the values will keep incrementing as long as the button is held down. Is jibberish just numbers that are larger than what you expected? The Player b total is also going to run into the next "Player a" string because there are no spaces following it.

Some general comments:

DDRC &= ~(1<<PC0); // set PC0 as input 
DDRC &= ~(1<<PC1); 
DDRC &= ~(1<<PC2);

Doing this is optional since DDRC starts out at zero (all pins as input) anyway. But it doesn't hurt, and it's documentation of which pins need to be hooked up.

// turn on the internal resistors for the pins 
PORTC |= (1<<PC0); // turn on internal pull up resistor for PC0 
PORTC |= (1<<PC1); 
PORTC |= (1<<PC2);

A shortcut for that would be

PORTC = 0xFF;

because this turns on all the pull-up resistors, and therefore you know that includes the ones you care about. But once again, doing each one explicitly doesn't hurt anything.

button1 = (PINC & (1<<PC0)) >> PC0; 
button2 = (PINC & (1<<PC1)) >> PC1; 
button3 = (PINC & (1<<PC2)) >> PC2;

A less error-prone way to do it, because you don't have to be careful to match the pin names in two occurances on each line, would be this:

button1 = (PINC >> PC0) & 1;
button2 = (PINC >> PC1) & 1;
button3 = (PINC >> PC2) & 1;

Another advantage to doing it this way is that the avr-gcc compiler seems to use 8-bit operations this way, but pads it out to 16-bit operations the original way which results in unnecessary extra machine instructions.

a1 = a1+1;

This can be written as

a1++;

If you do add code to wait for button release, you might also consider "debouncing" the buttons. Just writing to the LCD might slow things down enough that bouncing won't be an issue, but if you replace that with something faster later then you might get multiple increments with each press because the button mechanism both phsyically bounces, and transitions through ambiguous voltages which can also generate false signals.

April 25, 2010
by fdlkid2
fdlkid2's Avatar

well, after taking a little break from this, i tried making the program onto the chip but i got an error:

avrdude -c avr109 -p m168 -b 115200 -P COM3 -U flash:w:dip_arithmetic.hex:a

Connecting to programmer: . Found programmer: Id = "ba("; type = ╕ Software Version = . ; Hardware Version = . avrdude: error: buffered memory access not supported. Maybe it isn't a butterfly/AVR109 but a AVR910 device? make: *** [dip_arithmetic-upload] Error 1

i find it weird that it just started to do that when ive had no problems at all. I checked all connections and they are in the right spots. any ideas?

April 26, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi fdlkid2,

This error points to your chip not being in programming mode when you boot it up, or possibly a dying battery. The "ba" are things sent by the bootloader down the serial port "b" means entering bootloader, and "a" means it is jumping to the application code. If your switch was properly in programming mode, you would not see the "a" and your bootloader would wait to accept the new program. Let us know if you find the issue.

Humberto

April 26, 2010
by fdlkid2
fdlkid2's Avatar

oops i guess the ground wire fell out leaving the programmer ungrounded..

anyways the "jibberish" that im seeing is the "player a 0 player b 0" being repeated over and over again. pressing "player a" or "player b" buttons make random pixels scroll on the screen. the good news is when sometimes push "player b"'s button enough times it will start counting and then will stop after i let go of the button. and then reset will reset it back to the scrolling "player a 0 player b 0" crap

i hope this post makes sense haha.

also... i dont think this will matter at all but... here the buttons im using

April 27, 2010
by Rick_S
Rick_S's Avatar

The link you provided is for the normally closed version of the switches. If those are what you have, they will make contact until you press the button. When the button is pressed, they will "disconnect" the connection and then re-establish the connection upon release.

For most projects, people use a normally open switch, or one that only makes contact when pressed.

I'm not sure if the link is right, but if it is, that could be causing some of your woe's.

Rick

April 27, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi fdlkid2,

I think bretm has the answer for why you are seeing this behaviour in his earlier post. Notice that in your while loop, you are not waiting for a button press before continuing on with the loop. This means that the while loop is going to loop over and over as fast as it can, incrementing its counter while the button is pressed. What you want to do is add some code to wait for a button press, then do something when the button gets pressed, then wait for a little bit to allow the user to let go of the button. Let us know if that doesn't make sense.

Humberto

April 29, 2010
by JKITSON
JKITSON's Avatar

Hi fdlkid2,

Here is how i "deboucned" the sensor that counts the teeth on a sprocket...

NOTES: b3 is the input signal coming in to the mcu. The signal is normally high (1). When the signal goes low (0) I add one the the counter and set the latch to a 1. As long as latch is a 1 i skip the count part When b3 goes back to a 1 i set the latch to 0 and start over. This way i only get 1 count added to the total for each tooth seen no matter how fast or slow the sprocket rotates..

if(latch) goto latch_test; //latch ckt is to allow only 1 count per tooth
                           //from the magnetic sensor on drive line.

if(b3) count = count; //if input is high leave count same
    else {count++;
      gear_count++; //if input is low add "1" to count
      latch = 1;}

latch_test:

if(b3) latch = 0;
April 30, 2010
by bretm
bretm's Avatar

I wouldn't call that debouncing so much as "correctly counting high-to-low transitions". Debouncing usually refers to addressing the situation where the digital input switches back and forth between 0 and 1 multiple times even when the physical input device was only switched once.

An easy way to watch for pin transitions in a loop when you're not using interrupts would be something like

uint8_t pin = PINB & _BV(PB3);

if (pin != oldPin)
{
    oldPin = pin;

    if (pin)
    {
        // pin just went high
    }
    else
    {
        // pin just went low
    }
}

But in this particular case I think they should add actual debouncing. Since they have multiple buttons they can use something like Listing 3 from here (PDF).

Post a Reply

Please log in to post a reply.

Did you know that you can read diagnostic data from some cars with a NerdKit? Learn more...