1
\$\begingroup\$

I ask for the "best" way, but a "typical" way or a "better" way will be appreciated.

A great way to detect a single keypress among a bunch of buttons is to use a resistor ladder. But this (to my knowledge) cannot detect multiple keypresses. This is a single example of a resistor ladder. The output voltage for B1 and B3 is identical to B3 and B4 (0.8462Vin)

Perhaps if the resistors were in parallel, then each combination of keypresses will produce a unique resistance. for instance, if a 1 kΩ and a 4 kΩ resistor are both pressed, the equivalent resistance will be 0.8 kΩ. But with many pins, the resistance difference between each combination shrink considerably. With 4 buttons and resistors of 1,2,4,8 kΩ the combination of 1, 2, 4 (1/(1/1 + 1/2 + 1/4) = 0.57142k) is really close to 1, 2, 4, 8 (1/(1/1 + 1/2 + 1/4 + 1/8) = 0.533333k) difference of 38 ohm.

What is the best way to detect any combination of keypresses with few pins? (not just single key presses). I plan on using an ATTINY85 that will have 3 free ADC pins. It will only need to measure 4 buttons at max, and for most cases it will only be connected to 3 buttons. I plan on using one pin to read 3 buttons. But I would like to know the best way to measure it for the future.

\$\endgroup\$
8
  • \$\begingroup\$ Are any of your free pins connected to an ADC? \$\endgroup\$
    – Hearth
    Commented Oct 11, 2021 at 1:57
  • \$\begingroup\$ oh, yes I believe that all 3 free pins will be able to convert Analog to digital. Ill edit that in \$\endgroup\$
    – Zeno
    Commented Oct 11, 2021 at 2:34
  • \$\begingroup\$ best way means different thing to different people ... what if someone's best way is your worst way? \$\endgroup\$
    – jsotola
    Commented Oct 11, 2021 at 3:35
  • 1
    \$\begingroup\$ you could use a parallel load shift register \$\endgroup\$
    – jsotola
    Commented Oct 11, 2021 at 3:36
  • 1
    \$\begingroup\$ @henros What is a C/O pushbutton? \$\endgroup\$ Commented Oct 11, 2021 at 20:29

2 Answers 2

6
\$\begingroup\$

As people have commented, "best way" is subjective, or at least depends on your requirements and priorities.

I will suggest a few approaches here, and give some pros and cons for each:

ADC method

In the comments, Dave Tweed suggests a circuit like the following:

schematic

simulate this circuit – Schematic created using CircuitLab

Where "VM1" represents the single required pin of your ADC. Obviously, the resistance values and current are just sample values, and should be scaled to your specifications.

This circuits main advantage is that it only uses a single pin on your MCU. However, it has a few disadvantages:

  • It will produce a constant power drain. This can be mitigated somewhat by only turning on the current when you wish to measure the buttons, but this would require a second MCU pin.
  • It requires a constant current source, giving you at least a few extra components, extra cost, and extra power use.
  • Depending on the number of buttons you have, it can be error-prone, especially if the resistances drift with temperature, or if the constant current source is non-ideal. Careful design can probably solve these issues, and allow you to detect a large amount of buttons with the 10-bit ADC in the ATtiny85.

A note: you can also design this sort of circuit without needing a constant current source by simply using a resistor in place of "I1". The current will now vary, meaning that the ADC reading is no-longer linear with the resistance, but using the correct threshold-values in the software will still enable you to detect the configuration, albeit with reduced noise-margin.

Shift register

Another, maybe more standard method, would be to use a paralell-in serial-out shift register, such as the 74HC165. This will allow you to sample a practically unlimited number of buttons, with only 3 MCU pins (SHIFT/LOAD, QH [serial out], and CLOCK, in the datasheet linked).

This has the advantage of being fully digital, leaving a minimum amount of room for errors due to accuracy. However, you will need a (large) extra component for every eight buttons (each with associated cost and power draw). Additionally, you will need a software routine to latch the button states and read the data back serially, although this can probably still be done quicker than taking an ADC measurement.

Row/Column scanning

Row/Column scanning is a very common solution. You arrange your switches in a grid, and have one wire for each column, and one for each row. Then the MCU will apply a signal to each row in sequence, and monitor which columns the signal appears on.

This method is common, simple, and, if you include a diode with each switch, able to detect any combination of keys. However, with only three pins available, it is of limited use.

Charlieplexing

A variant of row/column scan is to use charlieplexing. This technique is most commonly used for controlling LEDs, but can also be used for inputs (using the internal pull-up resistors). The circuit design and software method for reading varies between configuration, depending on number of buttons, number of pins, and the required number of simultanious buttons, so I won't go into specific circuits.

Advantages include no ADC, minimal quiescent current draw, and a small number of pins. Disadvantages include high complexity (both SW and HW), and many extra passive components.

Final note

There are more considerations that might be relevant, such as ability to detect switches that has failed open or closed, ability for the MCU to trigger of interrupts, and how debouncing is handled.

\$\endgroup\$
0
\$\begingroup\$

if you want to use resistors. perhaps a serial setup like this:

schematic

simulate this circuit – Schematic created using CircuitLab

at some poinmt you hit the precision limit of the resistors, this is why I'm not using exact powers of 2, but instead using "E3"

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.