Reading Switches with using Attiny microcontrollers

There have been several Instructables dealing with outputs from the ATtiny2313 and similar AVR devices. For example,, Working on the latest one from The Real Elliot, which showed how to control stepper motors, I found that it would be really helpful to be able to run alternate sections of code in the same program so I didn’t have to reprogram the ATtiny2313 each time I wanted to try a slight code variation (such as half-stepping or running the stepper in reverse). While it is easy to write code using a switch/case statement to allow selection of alternate variations, some way of selecting the case is needed. That means some sort of input device has to be read to control the case.
Fortunately, the ATtiny2313 has plenty of I/O pins and is well-designed for reading inputs from switches. This Instructable will show how to read inputs and make decisions based on their state. Since that alone would make a pretty boring Instructable, I’ll explain a simple way of using the timer/counter capability of the ATtiny2313 to drive a small speaker as a beeper. There will also be a small digression on simple debugging techniques.

Step: 1 The Input Device

The Input Device
This Instructable builds on the excellent work of The Real Elliot and uses the ATtiny2313 Ghetto development system he describes. The ATtiny2313 data sheet from Atmel is the ultimate reference for all functions, but it is not necessarily easy to read. (Link has all AVR data sheets, locate the 2313.)
The figure shows a simple set of input switches. This is simply a package of four on/off switches; also known as single pole, single throw switches (SPST). Typically, one connection, or pole, of each switch is tied to ground while the other connection is pulled high through a current limiting resistor (10K or so). A microcontroller input is connected to the pole with the resistor. If the switch is open, the microcontroller will read the input as HI. If the switch is closed, the microcontroller will read the input LO. Refer to the schematic for details.
The ATtiny2313 simplifies things by providing programmable pull-up resistors on I/O pins when they are configured as inputs. This means that the switches can simply have one pole tied to ground (LO) and the other pole connected to a processor input. The first example shows only two switches. The switches are read and configured with the following code.
Configure the switches as inputs:
(No code required; this is the default.)
Turn on the pull-up resistors:
PORTB = _BV(PB0) | _BV(PB1) ;
Read the inputs:
but1 = ~PINB & 0x03;
Note use of inversion and masking to get correct value.

Step: 2 Blinkenlights for a Signal

We’ll use these two switches to blink an LED a programmable number of times. The LEDs we’ll use will be the blinkenlights that The Real Elliot made famous. Switches 1 and 2 will be treated as two binary digits, so the combination can represent the numbers 0, 1, 2, and 3. Our program will read the two switches and blink the LED the appropriate number of times, but only if the switch settings have changed. The switches are debounced for 500 milliseconds (not optimized). The debounce algorithm is pretty simple. The switches are read and the reading is noted. If it is different from the oldBut value (the last saved value), then the program is delayed for 500 milliseconds and the switches are read again. If the value is the same as previously read, the value of oldBut will be updated and the LED will blink the number of times implied by the binary value of the two switches. Note the inversion of the value since a switch that is “on” reads LO. The switches will be scanned continuously for further changes.
Please refer to earlier Instructables by The Real Elliot to learn more about blinkenlights. Have a look at this to learn more about debouncing switches.
Here’s the ATtiny2313 code for this example. In operation, this program will blink the LED on PB4 (physical pin 8) twice to show it is initialized. It will then read switches one and two, and blink one to three times depending on the switch setting whenever they are changed. When the switches are not changing, the LED will blink slowly.
To run this code, create a new directory (call it “Basic” if you like) and download the following C code file and makefile into it. Rename Makefile1.txt to just Makefile. Using WinAVR, compile the program and load it into your ATtiny2313.

Step: 3 A Minor Digression On Debugging

A Minor Digression On Debugging
If you’re like me (and every other programmer in the world) you probably have experienced times when the “error-free” code you’ve carefully typed in and compiled doesn’t do what you expect it to do. Maybe it simply does nothing! So what’s the problem? How are you going to find out?
Fortunately, there are several approaches to getting things to work. (Get this book for an excellent treatment of the topic of debugging. I’d like to offer a few simple suggestions pertaining to the topic of debugging microcontroller applications.
Step one is to build on what you know. If you have gotten a blinkenlight to work once, then use it again to see where you are in your program. I like to have the LED blink twice to signal the start of the program. You can put the code in to do this initially at the start of your program. Once you know that nothing is wrong with your hardware, create a function to do the blinking. Here’s the function I use.
** blinkEm – function to blink LED using PD4
** PD4 must be configured as an output.
** ———————————————————————*/
void blinkEm( uint8_t count){
while (count > 0){
PORTD = ~_BV(PD4);
It is now possible to use this function at various points in your code as a signal that the code has executed that far. Knowing the code is running means you can carefully examine each section that has run, but not done what you expected, to find errors.
Changing one thing at a time is a key technique for debugging also (described in the reference above). This classic method works along with “divide and conquer”: taking baby steps to add functionality incrementally. This may seem like a slow approach, but it’s not nearly as slow as trying to debug a large section of non-working code all at once.

Step: 4 More Debugging

There are many times when we want to check a section of code by skipping most of the lines in it, then enabling them one at a time as we verify each one works. Typically, we do this by “commenting out”lines we want to skip. An extension of this technique is to cut and paste a block of code, comment out the original (so we don’t lose it), and hack away at the copy.
C has four easy ways to comment out lines.
Putting “//”in front of a line comments out that line.
Enclosing one or more lines in “/*”and “*/”will comment out an entire section. For this method to work effectively, there must be no other “*/” in the code block (other than the ending one). So an effective discipline is to use // for comments within blocks of code, and reserve the /* */ construct for comment blocks and for commenting out sections of code.
Placing “#if 0” at the start of a block to comment out and ending the section with “#endif”.
More selective control is possible using “#ifdef (identifier)” at the start of a block and “#endif” at the end. If you want the block to be compiled, use “#define (identifier)” earlier in the program. Note the quote marks are for emphasis only and are not to be included.
Combining these techniques should provide a useful approach to debugging your ATtiny2313 programs. You may find these tools useful as we proceed through this Instructable.
For more detail: Reading Switches with using Attiny microcontrollers

About The Author

Ibrar Ayyub

Ibrar Ayyub is an experienced technical writer with a Master's degree in computer science from BZU Multan University. He has written for various industries, mainly home automation, and engineering. He has a clear and simple writing style and is skilled in using infographics and diagrams. He is a great researcher and is able to present information in a well-organized and logical manner.

Follow Us:
Scroll to Top