# Matrix of SPST switches and buttons with Arduino

I have a controller that I made out of SPST switch (the type with the "missile cover" type) and momentary buttons (so the ones that are normally closed, until you push them, and once released go back to the closed position). The matrix is a 7x6 using digital pins.

All works fine, as long as I press them one by one, or activate the switches one by one. but if I start to have the switches enabled, like 3 or 4 of them in the open position; and I press a button; instead of getting only the value of the button pressed, I trigger all the buttons that are in the same column/row of the button pressed.

I understand that I should not use SPST toggle switches for these cases; and just use buttons, but I am using this contraption, to play flight sim games, which require some switches to stay on or off (like engine fuel lines, lights and such; which require for realism purposes, to be either in the on or off position, so I can't use momentary toggle switches).

While reading, I discovered about ghosting and masking; and that a diode is used to fix issues with multiple buttons pressed, although I am not sure that this apply to the SPST; so before take apart the controller, I want to understand better what is the issue that I am experiencing.

My hardware is pretty simple: various switches and SPST connected on a 7x6 matrix; which goes to a teensy 3.1 (using all digital GPIO, not the analog ones). I can post the sketch if needed; it is a slightly modified version from this tutorial: https://www.instructables.com/id/How-to-Make-a-Custom-Control-Panel-for-Elite-Dange/

• Ghosting/masking is a limitation of switch matrices; the easiest way to fix it is to use a diode with each switch. Why do you suspect this doesn't apply to your matrix? – immibis Jun 14 '18 at 4:55
• I assumed it was an issue only for buttons. This is fundamentally my first attempt at these things, so I am trying to understand the issue. You would suggest to connect some diodes on the switches, and see if the issue reproduce? In that case, the diode go between the GPIO line and the switch, or the other way around? I suppose I need to stop the current from going back, so the direction should be from GPIO to the switch? – rataplan Jun 14 '18 at 5:07
• For your matrix, there is no difference electrically between a switch and a push-button. – Peter Bennett Jun 14 '18 at 5:13
• A switch is just like a push button that you hold down for a long time. – immibis Jun 14 '18 at 5:14

I'm sure this has been posted at least a million times on the web somewhere. I happened to pick up this image from a PDF manual sitting at a web site that holds documents in order to capture email addresses, etc. So I'm not providing a link to that site. Just the same, it's a good diagram:

Those are all SPST switches. (If you ever want to handle an SPDT, just take up two rows on a single column above for that.)

The diodes above can be wired with opposite polarity. All that does is change the meaning of "active" vs "inactive." As shown above, "active" means "HI".

The above matrix is larger than you specified. But it gets the idea across and is even larger than you need. Just trim rows or columns, as appropriate.

Not shown on the matrix above are the "pull-down" resistors on each of the columns. This is so that when a switch on an active row is not engaged, the value read by the column input will be a definite LOW. But if the switch is engaged on an active row, then the diode will pull up on the column line and it will be read as a definite HIGH by the column inputs.

To scan, you would make all of your rows as outputs, with only one of the rows active at a time. The others would be inactive. The columns would be inputs.

When a row is active, you'd read in the values for all of the columns. It's usually convenient to arrange all of the columns so that they attach to pins on the same I/O port of your MCU. It makes reading them easier/better.

It would be advisable to also do debouncing of these column values. I usually use a small state machine for this purpose, with $8\:\text{ms}$ per sample and using three samples for any switch to complete its state machine and be recognized as a value. An example of the state machine I use is found here, here, and here. So, for me this is $24\:\text{ms}$ per debounced value. You need to work out your own issues, though.

If you look closely at the matrix above, I think you can see that if only one row is active (HIGH in this case) and all of the other rows are inactive (LOW), then only the switches along that row are able to affect the column values you read. The others rows (inactive LOW) will have their diodes reverse-biased and cannot affect the column line. This avoids interference from switches that aren't being scanned at the moment.

There are many other issues you may need to deal with. I've already alluded to one: debounce time. But there are more. How do you want to handle multiple-press events, key roll-over, key combinations, and so on. But that's just software. So have at it.

While reading, I discovered about ghosting and masking; and that a diode is used to fix issues with multiple buttons pressed, although I am not sure that this apply to the SPST; so before take apart the controller, I want to understand better what is the issue that I am experiencing.

Take a simple example of a switch matrix that doesn't use diodes: -

I've shown two switches that are activated and, for this example, I'm assuming normally-open switches. Immedaiately you have a problem because Y1 becomes shorted to Y3 and these are row driver outputs. In other words, without a diode in series with each switch you cannot work out what buttons are being pressed if more than one is activated. Y1 shorts to Y3 and produces an indeterminate logic drive level.

If you want to ascertain the state of each switch you need diodes in series with EVERY switch so that Y1 doesn't short to Y3 (in this example).