April 14, 2010 by fdlkid2 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; button2 =(PINC & (1<> PC1; button3 =(PINC & (1<> 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; } 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; button2 = (PINC & (1<> PC1; button3 = (PINC & (1<> 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. 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? 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 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 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 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 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; `````` 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).