My use case is:
A garage with 3 rollerdoors, one per bay.
One light per bay.
There are four vertical pillars encapsulating the openings (rollerdoors).
I use a box with 4 momentary switches on each pillar between the rollerdoors.
That is: two boxes with 4 buttons each. One for light one for rollerdoor on the left and one for light and one for rollerdoor on the right.
One button box is connected via Cat6 cable to the Arduino, using only 3 wires (of eight).
My initial solution was five 10k resistors in series on Vcc to ground, with each button connected between the resistors, like so:
The diagram
R1..R5 = 10 kOhm
sw1..sw4 all momentary push buttons
Vcc ---- ------ Analog in
| |
|R| |
|1| |
|___sw1___|
| |
|R| |
|2| |
|___sw2___|
| |
|R| |
|3| |
|___sw3___|
| |
|R| |
|4| |
|___sw4___|
|
|R|
|5|
|
Ground_|
I then use code to firgure out which button is being pressed:
/*!
* ---------------------------------------------|-------------------------------
* Translate switch id per set (1..4) to consecutive numbers (1..n) across all
* switch sets (groups)
* @param button_voltage is the meassured analog input value
* @param button_group is the switch set
* @return the button id of the pressed switch
* ---------------------------------------------|-------------------------------
*/
uint8_t which_button_has_been_pressed(uint16_t button_voltage, uint8_t button_group)
{
uint8_t button_pressed = 0;
// off on switch (order from closer to farther from V in)
// 1018 840 1
// 1018 673 2
// 1018 497 3
// 1014 291 4
if (button_voltage < 890 && button_voltage > 790)
{
// ~840
switch (button_group)
{
case 1:
button_pressed = 1;
break;
case 2:
button_pressed = 5;
break;
case 3:
button_pressed = 9;
break;
}
}
else if (button_voltage < 730 && button_voltage > 620)
{
// ~673
switch (button_group)
{
case 1:
button_pressed = 2;
break;
case 2:
button_pressed = 6;
break;
case 3:
button_pressed = 10;
break;
}
}
else if (button_voltage < 550 && button_voltage > 450)
{
// ~497
switch (button_group)
{
case 1:
button_pressed = 3;
break;
case 2:
button_pressed = 7;
break;
case 3:
button_pressed = 11;
break;
}
}
else if (button_voltage < 350 && button_voltage > 250)
{
// ~291
switch (button_group)
{
case 1:
button_pressed = 4;
break;
case 2:
button_pressed = 8;
break;
}
}
return button_pressed;
} // which_button_has_been_pressed()
This code selects a voltage range to figure out the respective button.
So far so good. This is actually working. ![]()
However, I was wondering why the digital values per button are not equally spaced.
It might be clear for most, Vcc may not be the same at each button collection (box) due to difference in cable length, and contact resistances along the way; or the resistors have tolerances, thus have different voltages across them.
My question:
Is there a better way to identify the button that has been pressed, without relying on voltages (ideally without using more pins)?
I could use a voltage reference, which would reduce the range around the ideal value.
As for "(ideally without using more pins)"; I have since replaced the Arduino UNO with a MEGA (as it does more than buttons), and do have more input pins I could use one pin per button.
Plus Vcc and ground would lead to six wires being used ion the Cat6 cable.
The other (self-imposed) constraint is to have a simple solutions, as in less components or even a circuit board.
Any hints appreciated.


