I've got a project on my workbench that I was hoping to share, but I met some unexpected difficulty along the way.
If you've built the SparkFun Simon Says kit, you've encountered our silicone rubber keypads. They're cool -- the silicone has a nice texture, and concealing LEDs inside each button adds an interesting interactive touch. SparkFun even has a history of building these button pads into projects.
I was hoping to simply throw the larger four-by-four button pad on a project of my own, and share that project in this post -- instead it turned into a yak-shaving exercise!
GND
don't actually get grounded!). I spoke to several of my colleagues, and learned that it was common to cheat when they built projects with the button pads – cutting traces and wiring directly to the components, rather than setting them up as the intended matrix.So, I've taken this opportunity to write a detailed tutorial for the button pad. It explains the basics of matrix scanning for input and output, and works through several exercises, assembling the pad, then progressively adding features. There's even a wishlist with all the parts I used in the materials section.
Barring any more diversions, maybe next time I can share the underlying project with you. Enjoy!
See our LED page for everything you need to know to start using these components in your project.
(
I wish this could be I2C using PCA9555 for decoding the keys (also handles the Debouncing of said keys, and you don't have to worry about polling), and four PCA9635 to run the RGB leds (you may need to do some hardware tap dancing to drive the LEDs meaning extra resistor and a transistor, also you might need a different RGB led - but I can see why it could not be used). The cool thing is the whole thing becomes 5 wires to run the board- +5V, GND, SCL, SDA, and a INT. The INT is what lets you NOT have to Poll all the switches. When a key is pressed, the INT lets the micro-controller know something happen, then the Micro Controller checks the two ports to see which key has been pressed on the PCA9555. It cuts down on wasting time polling each key, and handles all the timing for the LEDs (which also means you can get the full spectrum of color from your LEDs). Everybody makes out that the coding is hard for the I2C but it really isn't.
I'm thinking that with clever use of shift buffers (both serial to parallel and parallel to serial) one could reduce the pin count on the uP down to the SPI bus and 3 chip select pins (total of 6 pins). This would allow scanning the buttons every time an LED color is written to provide 3x sampling of the buttons for debouncing for every LED refresh.
Would SPI on an UNO be fast enough to avoid flicker? Would there be enough time to do anything else useful between LED refreshes and still have a responsive keypad?
I think one of the things that makes a matrix useful is that it doesn't require very many extra components...but it requires some careful coding to keep the columns and rows straight.
If you're really being frugal with processor pins, then you could use shift registers, as you describe. I think the SPI interface would be plenty fast - it's max rate is fosc/2, or 8 MHz on a 16 MHz Arduino. My scan takes about 2 mSec per column. That's 16,000 bits at the max SPI rate. Seems reasonable.
You could also arrange the SPI bus so the input and output registers are a single shift loop, all with a common chip select. One shift operation would shift in the switch input, while shifting out the next column selection.
Saving chip selects might be useful, because shift registers often need some additional signals to get the data to latch. Off the top of my head, the 74HC595 and 74HC165 are double buffered, and have a signal that needs to be strobed to get the serial data to/from the parallel pins.
Yes, there is always a trade-off between code complexity and external support components.
The nice thing about the 75HC595 is the latch pin is rising-edge triggered. I have a project that uses one on SPI and I have CS on the latch pin. Granted the 595 is constantly "listening" to the MOSI line, it only pushes it's buffer to the output pins when the latch pin goes high. Because CS is actually a low-active signal, deasserting the CS provides the positive edge to push the last 8 bits that the 595 saw on the MOSI line. For the 75HC165 one has to invert the CS signal to function as expected on the SH/LD pin. Throw in a small transistor and a couple resistors and voila the signal is inverted. (If you don't have a spare gate in a hex inverter available from other circuitry...)
Yes, I've recently been thinking about these two chips used in this fashion. My own yak-shaving for a project for my local maker group... (Trying to read 13 inputs, and control 117 RGB LEDs on an inexpensive (and spare from my parts bin) Pro Mini...)