How to read 16 buttons

Hi,

if got a display and (atm) 10 buttons to connect to my arduino, if I would connect them 1 pin- 1button, I'll run out of ports.
I think I need a 16 to 4 Mux/Demux, or something else?
What would you recommend me?

Thx,
Astro

Have you seen this?
http://www.arduino.cc/playground/Code/ShiftRegSN74HC165N

Or, use a Mega that has more digital pins.

Or, use a serial LCD that uses only one I/O pin.

I'm allready using a 644p (Sanguino) but I have to use a special 8bit display (see other post). This one consumes (if im right) 13pins :-(, since I also need two PWM, three digital outputs I nearly running out of IOs...

Why is a shifting register better than a Mux/demux (since I've never used a shifting register bevore..)

but I have to use a special 8bit display

It isn't clear here, or there, why this is a true statement.

Why is a shifting register better than a Mux/demux (since I've never used a shifting register bevore..)

Whether or not you've ever used one before is irrelevant. The shift register is not necessarily better. It is just one option whose use is documented to work with the Arduino.

it for a special project and one of the "given things" I have to use is the display

Consider driving the 8 bits of the display with a 74HC595 shift and latch register. That will reduce the i/o pins needed for the display and costs less than $1.

Korman

@PaulS what does happen when a button is pressed but I'm not reading the shift registers? Is the press "saved". e.g. when someone clicks on the button very short an the program has to do something else...

No, the data is not saved. You have to check the shift register fairly often. But, keep in mind that "fairly often" in Arduino terms and in human terms are quite different things.

A human pressing a button for less than a microsecond is unlikely. Even if they do, do you really want to count that as a button press?

For the Arduino, a microsecond is a long time. Each clock cycle on the Arduino (at 16MHz) takes 62.5 nanoseconds.

I suspect, though, that using that particular display will be more challenging than reading a bunch of button presses. If it were me, I'd be spending my energies on the display.

"I have to use a special 8bit display": in that case, you can almost certainly provide for up to 16 buttons without needing ANY extra pins.

wire your (up to) 16 buttons in a 4x4 grid, giving you two sets of 4 wires coming from the grid (4 rows and 4 columns). in series with each of the 8 wires, place a 10k resistor (so 8 resistors in total); connect the other ends of the 8 resistors to the 8 data lines that are ALSO running to the display - lets say you connect the 4 columns to D0 to D3, and the 4 row to D4 to D7.

now, think about the ENABLE (or CLOCK) pin that your display has. when that pin is HIGH, data from D0 to D7 will be clocked into the display, but when that pin is LOW, D0 to D7 are completely ignored by the display - we are going to make use of that fact.

in your code you will need a routine that does something like this:

(note - not real C code, this is just pseudocode)
function readkey
{
configure D0 to D3 as inputs, with internal pulldowns.
set D4 to D7 = low

set D4 = high
read (D0 to D3) -> save as key1
set D4 = low

set D5 = high
read (D0 to D3) -> save as key2
set D5 = low

set D6 = high
read (D0 to D3) -> save as key3
set D6 = low

set D7 = high
read (D0 to D3) -> save as key4

configure D0 to D3 as output

return (key4 shl 12) + (key3 shl 8) + key2 shl 4) + key1
}

the returned value will now contain a set of bits that correspond to the button that is pressed. the display will be none-the-wiser as the lines D0 to D7 were 'reused' while the display was ignoring them (ENABLE pin was LOW), and the pins were returned to all being outputs at the end of our keyboard routine.

the eight 10k resistors are there so that if/when a button is held down while trying to write to the display, the button will have no effect upon the data (output pin vs 10k resistor -> output pin will always win).

cheers,
rob :slight_smile: