This instructable will show you how to read the number on a binary pushwheel or thumbwheel switch using LED's or an AVR microcontroller (I'm using an ATmega328p but this can be adapted for any AVR or probably another microcontroller of your choice). Multiple thumbwheel switches can be strung together to make an electronic combination lock, protecting your valuable...um....cookies!
Thumbwheel switches have detent buttons (technically called a "pushwheel") or a wheel that you can push to change a number up or down by one. Inside they have switch logic that encodes the number on the dial as, typically, octal, hex, BCD (Binary Coded Decimal) . This encoding is then sourced to or sank from the external pads where it can be read and displayed (as with LED's), decoded with IC's (e.g. 4029,74HC93,and 74HC590), or hooked into input pins of a microcontroller and further processed.
My favorite local electronics shop had a bin full of ones that looked like old SCSI device ID switches so I grabbed a few to see how they worked. The numbers go from 0 to 15 so I think this would traditionally be called a hex switch, but I'll be referring to them as binary because of the output we're working with. Don't confuse binary with BCD; they are not the same thing. Ok, let's go!
pkg_add -r avr-gcc -or- cd /usr/ports/devel/avr-gcc/ && make install clean pkg_add -r avr-libc pkg_add -r avr-gdb
No 1&aposs One 1 Two 1&aposs Three 1&aposs Four 1&aposs ------ ----- ------- --------- -------- 0000 0001 0011 0111 1111 0010 0101 1011 0100 1001 1101 1000 0110 1110 1010 1100
Place --> 8 4 2 1 0 1 0 1
128 64 32 16 8 4 2 1 0 1 1 0 1 1 1 0Find the places that have 1's and add those place numbers together. That would be 64 + 32 + 8 + 4 + 2 = 110. Pretty easy, huh? Knowing this now we are able to take our 4-bit switch and make a matrix of the pin numbers that have a 1 (logical one in digital is a higher voltage than a logical zero, in our case 5V and 0V respectively) against the decimal number they will represent. See the 2nd picture below for a table I made to represent the pads on the switch that would be at a logical 1 depending on the number selected on the front of the dial.
Pick four ports on your MCU that are free and configure them as inputs. I chose PD[2..5] in my setup but it doesn't matter which you choose, just be wary of using PD[0..1] if you are planning to use U(S)ART communication as those pins are usually reserved for that. I'm pretty sure Arduino and other clones map pins 0 and 1 to their USB FTDI port, as well. As an optional measure, you may chose to install diodes (in the pictures below the stripe is to the right). Some boards have protection but if you play around with bare AVR chips on boards it's probably not a bad habit. You do these things after you've smelled enough transistors burning.
Once you've made the connections to your input pins it's just a simple matter of reading your pins and processing the data. You could read the pins and light LED's, setup interrupts to handle serial communication, or if you string several of the switches together, you can use them as an electronic lock, testing the pins to see if the correct combination was entered before you grant access to the microcontroller or whatever it happens to be guarding.
#include <avr/io.h>#include <util/delay.h>#include "uart.h"#define SWITCH_M 0b00111100int main(){ USART_init(BAUD_9600); DDRD = 0x00; // inputs for switches PORTD = 0xFF; // pullup on PD[2..5] (we have negative logic on switch now) uint8_t bcode = 0x00; for (;;) { bcode = (PIND & SWITCH_M); // bcode = 00xxxx00 bcode = (bcode >> 2); // bcode = 0000xxxx bcode |= 0xF0; // bcode = 1111xxxx USART_tx(~bcode); // bcode = 0000xxxx bcode = 0x00; _delay_ms(2000); } }
0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F