Thursday, February 7, 2013

Binary Buttons

This week I managed to get buttons working after lots of research for debouncing buttons. I went with hardware debouncing as was far easier to do. So this is a small circuit that takes input from four buttons and outputs them on a LCD as binary and decimal numbers. Here's a video of what I mean. My fingers are quite big compared to the PCB buttons so you can't really see me pressing the buttons.

The circuit and code for this is quite simple. I had numerous idea on how to make software debounce as mentioned previously but decided it simpler and neater to use hardware. If any time in the future this is unreliable I can swap over then. So here is the schematic of what I did, note that I have not included the programming wires as it makes the drawings quite messy.
The only real things to note about the schematic is that the capacitors are used for debouncing the switches and the serial connection goes to the LCD screen. The switches are on the left simply because it was easier to attach them to the breadboard like that. Programming wise it would have been easier to have then all connected on the other side as the pins are more in sequence. I have also changed the switch symbol from the one used in previous posts to match the Australian Standards of AS 1102.101.

Now the code that ties everything together. Here are the individual files: ATmega88-LCD-Serial-Buttons.c, LCDSerialDriver.h and LCDSerialDriver.c. In ATmega88-LCD-Serial-Buttons.c, here are the things to note:
• I've used the "Pin Change" interrupts for the buttons. I couldn't find any documentation outside the manual on how these worked so I had to work it out for myself. I got confused at first as the manual had how to set the normal external interrupts to use rising or falling edges on the switch for detection but soon realised that the pin change interrupts did not need this as the trigger when there is a pin change - pretty obvious when you think about it.
• Next I had to set up the input pins to firstly be inputs (the default state but good to make sure), turn on the pull ups, tell the controller which pins of pin change interrupts we want turned on and then turn on the the pin interrupts themselves. I also put in a line that made sure the global disable of pull up resistors was not set. We then turned on global interrupts.
• The interrupt code was the hardest bit as I got confused with the state of the button and how the controller read this. This is because a logic one or 5V on a pin was actually a button not being pressed rather than the opposite which is what my brain was telling me. This took me ages to debug but I eventually got there. I made a logic table to show what the conditions were. N/A means no action to take. Pressed and unpressed are the new state that caused the interrupt to be called.
The plus and minus mean whether we turn on or off the bit of our count number. The underlined names mean which ones we have as the positive value in the code.
• To change the bit of the count number stored, I simply added or subtracted the number each button represented as earlier from when I was confused about when to change the number wasn't working and was changed to make it easier to read. It could easily be set with logical XORs or ANDs and ORs and using binary numbers (eg: ^=0b0001 or & 0b1110 and |= 0b0001).

The LCD function names need to be fixed as they are still named after the examples I followed to get the LCD working in the first place. The other two files are my driver for control of the LCD03 screen via serial. They aren't commented very well as I haven't received my book on Doxygen which is what I'm going to use for a guideline on how to layout my comments. Even so, all functions are pretty self explanatory.

Hope that explains what I did for this circuit and others if they want can copy it.