What's the correct way to wire buttons?

I’ve been working on my thing (:flushed:) and I got the buttons working by connecting the other pin to GND and I’m just checking for a LOW signal on that pin to make the buttons do stuff, but looking at physical/manual/not-on-the-board pull-up resistors, it seems some people actually wire their buttons so rather than GND, they connect the buttons to VCC? Makes more sense in my opinion; 1 should be pressed, 0 should not be pressed, but… why? Like, is there a reason some people use VCC/HIGH and other people use GND/LOW? Does it matter?

Doesn’t really matter. And it’s a good practice to put a current limiting resistor in the circuit as well, but obviously not necessary as even the Arduboy itself doesn’t do that.

Once you get extremely technical there may be some advantageous reasons one way or the other due to electrical engineering reasons but for someone working on their own project you just need to consider how you are writing the code.

Having the circuit built with an internal pull up and having the other side of the switched tied to ground is nice for a PCB design as you will usually have a ground fill available to tie the other side of the circuit. Otherwise you have to run a second trace for VCC if you don’t have another layer, even then that costs a via.

1 Like

In the case of the Arduboy, the ATmega32U4 (as well as many other microcontrollers) has the ability to enable an internal pullup resistor on its GPIO pins but not a pulldown. Therefore, to have buttons tied between VCC and the inputs would require an external pulldown resistor for each button. Using the internal pullups saves components and it’s easy to handle in software “button pressed” reading as a 0.

4 Likes

Then I think I’ll connect the buttons to VCC instead of GND then; I’m much more comfortable (and it feels righter) with 1 as pressed and 0 as not pressed.

Then if whatever input you use to read the buttons doesn’t have an internal pulldown resistor capability, you’ll have to add one external pulldown resistor for every button.

1 Like

I’m using the ESP32 which (I believe) has internal pullups and pulldowns for every GPIO except 4 of them—which is why I started looking for actual manual resistor pullups then fell into this rabbit hole.

Keep in mind that having pulldowns and buttons that pull the inputs high could make it more difficult to port software to hardware that follows the more common practice of buttons pulling low.

2 Likes

While sometimes people equate 1 to true and 0 to false (mainly due to historical precedent), there’s another (stricter, more type-safe) way of looking at it: that 1 and 0 are integers (and only integers) and that true and false are booleans (and only booleans), and thus you must have some kind of mapping between them.

You can map 1 to true and 0 to false, or you can map 0 to true and 1 to false, it doesn’t really matter. As for how you do that: bit != 0 maps 0 to false and all non-zero values (including 1) to true, while bit == 0 gets you the opposite: true for 0 and false for all non-zero values.

Either way, you can just hide hardware details behind functions - that’s the whole point of abstraction: that the way in which something is achieved may be differentiated from the ‘contract’ by which it is promised. (Where a function’s type signature and restrictions as specified by comments form the ‘contract’, and the actual implementation is the means by which that contract is fulfilled.)

E.g.

constexpr bool usePullup = true;

inline bool isButtonPressed(Button button)
{
	auto value = readPinForButton(button);
	return (usePullup) ? (value == 0) : (value != 0);
}

(Not the most sophisticated solution, but one that should be easy to understand.)

2 Likes

Oh, yeah that’s true I guess.

What’s bit?

An object/variable with a possible value of 0 or 1 (and hence equivalent to a bit’s worth of information).
E.g. a value read from a digital pin.
(After all, a digital pin is basically just a carrier for a bit worth of information.)

2 Likes