Go Down

### Topic: Switch Matrix (a newbie question) (Read 5118 times)previous topic - next topic

#### p.h.howells

##### Feb 19, 2011, 10:35 pmLast Edit: Feb 19, 2011, 11:56 pm by Paul Howells Reason: 1
I would like to detect the state of a set of momentary SPST switches. (There would be more of these switches than Arduino pins and several might be closed at once).

I am considering arranging the switches into a matrix, so that with for example 14 digital pins divided into 7 outputs and 7 inputs I could read 49 switches (inputs corresponding to matrix columns and outputs to matrix rows).  I can see how (with Processing) to detect if an input pin is getting a signal, and I am wondering how best to determine which output pin is connected to an input.

My proposed solution is to turn on each output pin, one at a time, and to continuously cycle through the set of output pins (turning off each last and turning on each next).  My hope is that this would run so fast that there would be no (humanly discernible) problem detecting any set of switches being briefly pressed (closed).

Is this a good way to do it or are there better ways?

(I have looked through the forum and found references to shift registers and multiplexers that I don't understand yet -- and I'm hoping are unnecessary at this point. I can imagine de-bouncing and pulling signals up or down might be issues).

Thanks

Paul

p.s.
I'm new to digital electronics and Arduinos but I have some experience in programming (although I'm still new to Processing). This is my first post on this forum :-)

#### fliggygeek

#1
##### Feb 20, 2011, 02:37 am
You can debounce signals with hardware.

#### nickgammon

#2
##### Feb 20, 2011, 04:43 am
How many switches? Do you actually need 49 or that an example of what might be possible with a 7x7 array?

Wiring and tips about a matrix here:

http://www.dribin.org/dave/keyboard/one_html/

You may need diodes as mentioned in that post, particularly if you are expecting multiple switch presses at once.

If you only need 16 switches I did a post about that recently:

http://www.gammon.com.au/forum/?id=10945

You could double the number of MCP23017 chips to handle 32 switches. After that I'm not sure whether or not there would be a problem with handling multiple interrupt lines.

Another possibility would be something like the Centipede shield:

http://macetech.com/ (look under Shields).

At the expense of only your I2C pins (A4 and A5) you have access to 64 pins, which you could wire to switches individually. They also have cables and breakout thingummies for connecting to wherever you have your switches.

With that shield you could at least poll the 64 switches - I'm not totally sure about the interrupt side, but polling may be adequate for you. Since each one has its own "bit position" you could readily detect if more than one was pushed at once.

Judging by my copy of the shield, you have access to the interrupt pins on the MCP23017 but you would have to manually run a wire to pins 2 and 3 to actually use them. And even then that would only give interrupt access to 32 of the pins, not 64. Still, that may be enough, or simple polling might do it.
Please post technical questions on the forum, not by personal message. Thanks!

#### nickgammon

#3
##### Feb 20, 2011, 06:09 am
Further to my earlier reply, I did some experimenting and worked out that you can indeed connect multiple MCP23017 chips together, provided you give them different addresses. My interrupt-driven technique works with multiple chips as well, provided you configure the interrupt port as "open drain". Thus the Centipede shield could do exactly what you want - handle 64 switches, provided you just run a wire from the four interrupt pads on the board to pin D2. The code on this page shows how you could handle 32 switches:

http://www.gammon.com.au/forum/?id=10945

A minor modification and you could handle up to 64. And then with two Centipede shields, 128.
Please post technical questions on the forum, not by personal message. Thanks!

#### macegr

#4
##### Feb 20, 2011, 11:47 am
I don't have support for interrupts written into the Centipede library yet, but the interrupt pin chosen can be "mirrored" with the other pin. That is...the single INTA pin can trigger when any of the 16 pins on a single chip experience a valid condition.
Unique RGB LED Modules and Arduino shields: http://www.macetech.com/store

#### p.h.howells

#5
##### Feb 20, 2011, 05:22 pm
Thanks for the replies folks!

@Nick Gammon
thanks especially for the dribin.org link, that was exactly what I was trying to describe and the explanation there of using diodes to avoid ghosting and masking will have saved me some time :-)

I will take the dribin.org link as confirmation that my suggested approach was thankfully already a well used one, and thus its an okay idea.

I did quite a bit of searching and reading faqs before posting and after not finding anything was a bit worried that I was proposing something really stupid.

I'm still wondering however if there is a better approach.  I can see that your use of an MCP23017 would be better because it uses less Arduino pins, and similarly that using the Centipede could be an improvement if I wanted more switches for less Arduino pins.

If I'm happy using up the 14 pins though, is the dribin.org approach the simplest, and most practical on an Arduino?
or are there other issues with it that might have me working on another solution or perhaps using extra chips or buying a shield?

To answer your question about the number of switches, I do indeed need about 48 or 49 switches (maybe 64 eventually) but you are correct -- I am trying to learn what is possible, and start my Arduino learning with simple examples and concepts.  I'm sure I will soon be learning about things like multiplexers, shift registers and interrupts.

@fliggygeek
thanks, if I find I need de-bouncing I will research hardware as well as trying out software solutions.

@macegr
thanks for chipping in. If I find I need more switches and/or need to use less pins the Centipede looks like a good solution.  I hope it won't be too long before I understand your conversation with Nick ;-)

#6
##### Feb 20, 2011, 07:46 pm
You could also wire up a set of shift-in registers, and periodically clock in whatever is on the input pins, shift it in and act on the resulting 1s & 0s.
Using SPI to read them all in would bring the data in really quick too as its hardware controlled and not software controlled.

There is another thread here
http://arduino.cc/forum/index.php/topic,52383.0.html
discussing that but addressing outgoing data at the moment.
Incoming would be similar - supply a load clock grab the data, SPI.transfers to bring it in
http://arduino.cc/en/Reference/SPI
or just use shiftin() as a pure software approach.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### p.h.howells

#7
##### Feb 20, 2011, 08:03 pm
thanks CrossRoads, its great to hear of another way to do it.

Please could you mention the advantage of this over the method I suggested -- I'd like to learn if I came up with a bad idea!  It seems there are quite a few ways to do this and I would like to learn their relative merits and disadvantages. I'm new to this so I'm hoping to make an informed decision and set off in roughly the right direction if possible.

#### nickgammon

#8
##### Feb 20, 2011, 08:46 pm

I don't have support for interrupts written into the Centipede library yet, but the interrupt pin chosen can be "mirrored" with the other pin. That is...the single INTA pin can trigger when any of the 16 pins on a single chip experience a valid condition.

Yes, exactly. That is what I did with the demo program I gave in the link. Plus connected all the INT pins together and configured them as open drain. In fact what would be useful would be if future versions of the Centipede brought out the INT pins next to each other (if possible) and adjacent to the D2 Arduino pin. Then a small bit of wire could jumper them together and the D2 pin, thus enabling interrupts without having to run wire everywhere.
Please post technical questions on the forum, not by personal message. Thanks!

#9
##### Feb 21, 2011, 12:08 am
Momentary switches - why not look into the keypad tutorial as well?
I would suggest wiring it up like this with the diodes so you would only go out & read the keys when a press somewhere creates in interrupt.
Expand it to 7x7. Uses up 15 pins this way, and need 7 diodes. The code goes out & figures out which key was pressed. I'm not sure what it does for multiple keys pressed together.
The other way, using discrete parts or a Shield like the centipede, uses less arduino pins.
Or 3 chips like this
or 6-7 of these
Do you need 49, or will 48 be enough?
Functionally, you want to end up like this if you want to use interrupts to capture each switch and be sure to multiples pressed at the same time.
I show an 8-pin shift register for clarity. There are 16 input versions also, and the centipede documentation indicates it has weak internal pullups (100K) and Nick was mentioning interrupts that could be connected. The advantage of shift register is that you can latch the state of the pins as soon as any one is pressed - its gonna be keypress, interrupt, latch signal - so simultaneous presses really need to be simultaneous. Take your same shifting in, you've already captured the keypress, any others are locked out.
The other way with a port expander: you get an interrupt, you go out and start reading. Reads will happen pretty fast, but "simultaneous" time is a lot longer.

The other option is just latch & read every millisecond or so as part of a loop of whatever else you have going on and don't bother with interupts.

Lots of options, you need to decide how much time to you want to spend building, or spend money buying, or the performance you can live with.
You're not locked into anything, you can always rebuild things later.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### p.h.howells

#10
##### Feb 26, 2011, 08:15 pm
Thanks CrossRoads for the links and advice. You are quite right about figuring out the trade offs between different approaches.

and thanks to everyone who replied to my post!

In order to learn I'm going to start by having a go at making a 'low-tech' switch matrix, and write something in Processing that does a LOT of reading every second. :-)

Then when I have that working, I will have a go at the more advanced methods you have mentioned, I can see a real advantage to knowing how to set up a switch matrix without using up all of my pins.  I can imagine that in the future I will end up using something like the Centipede or a MUX shield to save myself time, but I'm going to try these other things first for the sake of my education.

As a newbie posting for the first time I have appreciated the response, I'm getting the impression that there really is a community forming around the Arduino and Processing and I hope it won't be too long before I'm able to contribute too.

Cheers, Paul

Go Up