Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Mulitplex Keypad Output


  • Please log in to reply
29 replies to this topic

#1 GlenS

GlenS

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationTamworth, UK

Posted 07 March 2012 - 05:42 PM

Hi, Am I on the right lines thinking I can reduce the 8 pin output of a 4x4 matrix keypad, down to a SPI based interface using a 74HC165 mulitplex chip. many thanks

#2 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 07 March 2012 - 07:16 PM

Hi Glen, Unfortunately not. The 74HC165 takes 8 logic level inputs and converts them to serial which can be read using the Netduino's SPI. The problem is that the keypad has a matrix of switches - this matrix needs to be scanned. To do this four of the keypad lines need to be driven, and four need to be monitored. The two sets of lines are usually referred to as rows and columns. Assume the rows are driven and the columns are monitored: The keypad circuitry will typically pull one row low at a time, leaving the other three unconnected. At a high rate, it will cycle between all of the rows, pulling one low at a time. The columns will have pullup resistors such that they are at logic 1 when no key is pressed. When a key is pressed, it connects one of the rows to one of the columns. When the key's row is pulled low, the key's column also goes low - the circuit detects this and is able to determine which key is pressed. There are dedicated matrix keypad chips to this job. I did a quick Google search and found a few, some will even convert to serial. Paul

#3 Nathan Baker

Nathan Baker

    Member

  • Members
  • PipPip
  • 22 posts
  • LocationWisconsin

Posted 07 March 2012 - 07:31 PM

I am just guessing at how this keypad is wired, but I'm fairly certain that you won't be able to do this. If you want to reduce the lines you would need to have to encode the key presses. I currently have a 4x3 keypad with 7 terminals. This is because there are 3 connections for the columns and 4 for the rows. In your case, I'm guessing that there is 4 connections for the columns and 4 for the rows. In order to detect the key presses, you need to scan for them. For very short intervals, you need to bring each of the columns, one at a time, high and scan the rows for their state. This will allow you to detect which key in a column is pressed. The image below shows how the connections on my 4x3 keypad correspond to the buttons.

Posted Image


If you want to connect this directly to the Netduino, you are going to need all 8 connections (less if you dont need every key, but what would be the fun in that?).

If you want to use as few pins as possible on your Netduino, then you are going to have to have some sort of external circuit to do this encoding for you. Personally, I would use a cheap PIC and then have that interfaced to the Netduino, though you could definitely use a Netduino mini for the purpose. There are even chips dedicated to this task.


Image was borrowed from an Arduino example found here.
Posted Image

#4 GlenS

GlenS

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationTamworth, UK

Posted 07 March 2012 - 08:00 PM

Paul / unr34l-dud3 Thanks both for the advice. The wiring is very similar to the 4x3 example, except that there is an extra column of letters on the keypad. I have looked around and seem now to think that I should be able to use a 74C922 interface chip and use that either directly using 5 netduino pins, or have the 4 output pins drive the 74HC165 for SPI compatibility. Downside is the relative expense of the 74C922. I'll investigate the PIC route. Glen

#5 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 07 March 2012 - 08:19 PM

If you really wanted to have fun B) , you could try and make this idea work: (You need to look at the picture as you read this.) Take a 2-bit binary counter, and clock it from the Netduino's SPI enable line. So that each time you read a byte from the SPI, the counter advances by one. Also connect the enable line to the "load" signal on a 74HC165 such that it samples its 8 parallel inputs. Take the 2 bit outputs from the counter and put them into a 2 to 4 line decoder. The decoder "decodes" the binary number and makes one of its four outputs go low at a time. Feed the four outputs to four of the parallel inputs on a 74HC165, and also use diodes to feed them to the rows of your keypad. The diodes are arranged so that they can pull the rows down to ground, but not pull the rows up to Vcc. Take the four columns and connect them to the other four parallel inputs on the 74HC165, and also connect them to pull up resistors. Now each time you use the SPI to read the shift register, the load signal causes the counter to increment so that a new row is scanned. The Netduino will receive an SPI byte with four bits showing the current row being scanned, and another four bits showing if any of the columns are connected to an active row via a switch in the matrix. If all the column bits are 1's, no switch is pressed. If one (or more!) are 0's, the Netduino needs to work out which key(s) are pressed. The Netduino should read the SPI often so that it can continuously scan the keypad. DISCLAIMER :blink: : I have not built this - I only drew it up for fun. If you try and build it, you may have problems with the counter counting on the wrong edge of the load signal. I believe that the load signal to the 74HC165 should go high when the Netduino reads the SPI data. You would want the counter to advance when the load signal goes low (e.g. after the Netduino has finished its SPI read). Paul

Attached Files



#6 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 07 March 2012 - 08:32 PM

Just thinking about row signals - the Netduino does not need to see all of the row signals, it just needs to see one of them so it can tell when the counter resets to zero. Once it sees row zero go low, the Netduino would know where the counter was in its cycle. If we only connect row zero to the 74HC165, that frees up three of the 74HC165 inputs, so they can be used for extra columns. So you could have 7 columns (4x7 switches). Also a bigger counter and row decoder could be used to give more rows: With a 3-bit counter, and a 3 to 8 line decoder, you could decode an 8x7 matrix! (8 rows, 7 columns) With a 4-bit counter, and a 4 to 16 line decoder, you could decode a 16x7 matrix! (16 rows, 7 columns) Paul

#7 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 08 March 2012 - 08:10 AM

As Paul stated, everything is just for having fun! Well, the Paul's solution is elegant, and I'd prefer...but since we're looking for fun, here is an hack using the 74HC595, which is the opposite of the HC165: serial-in/parallel-out. Please, watch at the attached schematic (roughly written, sorry). Basically, you should present the 16 different combinations of row-columns on the '595 outputs. Only one row and one column will have to be high at time, and all the remaining outputs will be low. If you try, you'll notice that the MISO line is taken high only when the correct row-column combination matches the actual key pressed (not shown for clarity). Since the MISO is an input available for "free" in the SPI...that's all. It could be improved, but...is it worthwhile? Also notice that you can't detect more than one key pressed at once. Cheers

Attached Files


Biggest fault of Netduino? It runs by electricity.

#8 GlenS

GlenS

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationTamworth, UK

Posted 08 March 2012 - 12:21 PM

Paul / Mario Cheers Guys. I'm quite new into the micro-electronics field - bit of an evenings hobby, so am certainly looking for the fun aspect. I will have a go at both solutions (Mario's first as I have all the parts in my kit bag already) and report back. Glen

#9 Nathan Baker

Nathan Baker

    Member

  • Members
  • PipPip
  • 22 posts
  • LocationWisconsin

Posted 08 March 2012 - 11:52 PM

I have to do this sometime in the near future (keep putting it off). When I do, I'll be sure to post an example circuit and code for the PIC version for the benefit of all! Posted Image
Posted Image

#10 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 09 March 2012 - 07:12 AM

Glen, Really glad to hear you'll give the ideas a go. I think Mario's idea with only one standard IC it is much more elegant than mine. I think I can improve Mario's original with four more diodes so that you can scan the whole matrix in one 8-bit SPI transfer rather than several. I'll try and draw it up this afternoon (after work). No guarantees it will work! Paul

#11 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 09 March 2012 - 06:51 PM

Hello

When I saw Mario's idea I did not understand how it worked!
Once a friend had explained it I thought it was a great idea since it did not require three ICs as my idea did.

In Mario's original version I believe it is necessary to write many different SPI words to the 74HC595 to poll all of the rows and columns.

Here is my variation of Mario's idea, which I think only requires one 8-bit SPI write to be made to scan the whole matrix.
As with Mario's original, a bigger matrix can be scanned by adding another 74HC595.

The changes are to swap around the existing diodes and resistors, connect the ST_CP and SH_CP signals together, and to add four new diodes.

Before you go any further, you will need to take a copy of the diagram - this will not make much sense otherwise!

Joining the ST_CP and SH_CP lines makes the 74HC595 act more like a normal shift register (the outputs will change bit by bit as the SPI data is clocked into it). Using the 74HC595, there is one slight complication, the first data bit sent by the Netduino will not appear at Q0 until one clock cycle after it was sent. Also the last bit sent will appear at the start of the next transfer. (This is because of the latches in the 74HC595).
If you could get hold of a 74HC164 shift register, the first bit would appear immediately. But I think the 74HC595 is easier to find.

I may have made a mistake with the bit ordering in this part:
The data we send to the 74HC595 is sent MSBit (most significant bit) first. So at the end of the transfer the first bit sent ends up at Q6 (not Q7 due to delay). So I am proposing to send the value 0x01. On the first write this will set all the outputs low, and the '1' will be stuck at the start of the shift register. (We will ignore the return value from this SPI operation). On the next write (and all subsequent writes) when we send 0x01 again, the first clock makes the previous missing '1' appear at Q0, and then move all the way along to Q7 followed by zeros.

This pattern is shown in the yellow note at the top of the circuit.

Lets assume firstly that all of the matrix switches are OFF. (The diagram only shows three of the switches for clarity.)
The SPI data to the Netduino 'MISO' will remain high '1' for all the bits. This is because none of the voltages on the row connections A,B,C,D are LOW '0', so the resistor R1 pulls the MISO data line HIGH '1'.
Sending an SPI word to the 74HC595 will not change this because the diodes D0-D3 can only pull the rows A-D HIGH '1' not LOW '0'.

So when all the switches are OFF we receive 0xFF from the circuit (OFF = 0xFF - that's easy to remember!). This is shown in the yellow note on the left.

Now consider switch switch C-4 (Row C Column 4).
If C-4 is ON, the following happens:
  • When Q7 is LOW '0' AND Q2 is LOW '0', the diode 'C' will conduct through the switch and R7 to Q7, and this pulls the MISO signal down to ground '0'.
  • When Q2 is HIGH '1', diode D2 conducts, this makes diode 'C' turn OFF because the voltage at ROW 'C' is now higher, and so the MISO signal is pulled HIGH '1' by resistor R1.
  • When Q7 is HIGH '1', there is no longer a path to ground through resistor R7, again diode 'C' turns off, and so the MISO signal is pulled HIGH '1' by resistor R1.
The bit patterns that are seen at the MISO signal are shown in the note on the left for each of the switches C-4, D-4 and D-3.

So when C-4 is pressed the data received by the Netduino will be 0x84, D-4 will give 0x88, and D-3 will give 0x48.

Possible mistakes:
  • I may have got the bit ordering back to front (e.g. everything is LSbit first not MSbit),
  • I am assuming that the Netduino samples the MISO signal on a falling clock edge. If I have got this wrong, the data read will be shifted by one bit.

So Glen if you are brave enough to try this, let us know how it goes.
(Use Mario's resistor values R1 = 47K, R4-7 = 4K7.)

I am ready to edit this post when the mistake reports start to arrive. :blink:

Paul

Attached Files



#12 GlenS

GlenS

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationTamworth, UK

Posted 11 March 2012 - 11:19 AM

Paul,

Some early feedback. Having built your circuit on a breadboard, I'm finding that the value I'm getting back from the SPI WriteRead never changes from 0xFF. I'm currently re-working the build to make sure I have everything correct and will report back later this evening.

Software-wise I have this simple test rig .

public class Program
    {
        public static void Main()
        {
            // write your code here
            SPI spiDriver = new SPI(new SPI.Configuration(Pins.GPIO_NONE, false, 0, 0, false, false, 32, SPI.SPI_module.SPI1));
            byte[] readbuffer = new byte[1];
            byte[] writebuffer = new byte[1];

            while (true)
            {
                writebuffer[0] = 0x01;
                readbuffer[0] = 0x00;
                spiDriver.WriteRead(writebuffer, readbuffer);
                Debug.Print(readbuffer[0].ToString());
                Thread.Sleep(100);
            }

        }

    }

Many thanks for your continued support and interest in my quest ..

#13 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 11 March 2012 - 11:28 AM

Hi Glen, I have just built it on breadboard myself. (I thought that "I should put my money where my mouth is".) Did you spot that I forgot to connect the OE line to ground? Sorry about that. Without that the 74HC595 will not drive the outputs - that would explain always getting 0xFF. Thanks for posting the software, I had not got to that stage yet. Maybe this evening before I do now (family birthday outing). Paul

#14 GlenS

GlenS

    Member

  • Members
  • PipPip
  • 23 posts
  • LocationTamworth, UK

Posted 11 March 2012 - 01:26 PM


Did you spot that I forgot to connect the OE line to ground?
Sorry about that.


Hi Paul,

Yes, I had spotted that, I have also tied the MR line high, rather than drive it though the Netduino. Is that correct. One other thing I have thought about as well, and this is probably the clincher. I am using LED's rather than ordinary diodes, mainly as I don't have enough in my kit bag, but also I thought it would be cool to visualise the effect of closing the keypad switches. I'm thinking, and am on very new-be territory now, that the resistor R1 should be a lower value if I'm using LED's.

Glen

#15 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 11 March 2012 - 02:00 PM

Hi Paul,

Yes, I had spotted that, I have also tied the MR line high, rather than drive it though the Netduino. Is that correct. One other thing I have thought about as well, and this is probably the clincher. I am using LED's rather than ordinary diodes, mainly as I don't have enough in my kit bag, but also I thought it would be cool to visualise the effect of closing the keypad switches. I'm thinking, and am on very new-be territory now, that the resistor R1 should be a lower value if I'm using LED's.

Glen


Hello Glen, and hello Paul (when he'll be here).
Hacking is more than a fun...is somewhat an art!...Your supposed failure in the missing diodes is actually an amazing feature of the keypad. (and don't be shy: confess that it was a long awaited project in your mind!)

Anyway, led is also diodes, but they have an higher voltage drop than the ordinary diodes. The circuit should work anyway, but it's better if you power the whole circuit using +5V. The greater drop caused by the led will be compensated by the higher supply voltage.
No matter about the Netduino, 'cos is +5V-tolerant.

I'm here, waiting for news!
Cheers
Biggest fault of Netduino? It runs by electricity.

#16 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 11 March 2012 - 02:28 PM

Hi, I'm at Marwell Zoo eating lunch watching the Emu. (I also tied the MR high.) As Mario says, the LEDs drop more voltage so a higher supply would be needed. Even then, the resistors (47K & 4K7) may be too ig to get them to light. If you change them, you need to maintain the ratio between the resistors R1 and R4-7. The diodes A-D in my diagram will light up when a key is pressed on their row. But, will blink off when the coresponding Q0-3 or Q4-7 goes high. The LEDs D0-3 will only light when Q0-3 are high and a key is pressed. So you should get a light show. (I am writing this from memory on my PDA, so appologies for any errors.) Paul

#17 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 11 March 2012 - 02:32 PM

Hi, I'm at Marwell Zoo eating lunch watching the Emu.


Wish were there!
Have fun!
Biggest fault of Netduino? It runs by electricity.

#18 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 11 March 2012 - 07:33 PM

It works - sort of :blink: I have used normal diodes, and they don't light up - (this is good). I get 0xFF when no switch is pressed. I seem to get a different number for every switch pressed. But, the numbers don't make sense. :( I think the word might be shifted by a bit - I'll keep experimenting. Paul

#19 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 11 March 2012 - 07:51 PM

HELP!

How do I get c# to print in hexadecimal?

e.g.

Glens code:

            byte[] writebuffer = new byte[1];
            byte[] readbuffer = new byte[1];
        
            while (true)
            {
                writebuffer[0] = 0x01;
                readbuffer[0] = 0x00;
                spiDriver.WriteRead(writebuffer, readbuffer);
                Debug.Print(readbuffer[0].ToString());

I think I should be able to write
readbuffer[0].ToString("X")
but I get exceptions.

How do I do this?
(It is too difficult to debug the code in decimal.)

Paul

#20 Paul Newton

Paul Newton

    Advanced Member

  • Members
  • PipPipPip
  • 724 posts
  • LocationBerkshire, UK

Posted 11 March 2012 - 08:09 PM

I still don't know how to print in hex, but I have the matrix scanner working!

I changed the clock edge in Glen's code:
    public class Program
    {
        public static void Main()
        {
            // write your code here
            SPI spiDriver = new SPI(new SPI.Configuration(Pins.GPIO_NONE, false, 0, 0, false, true, 32, SPI.SPI_module.SPI1));
            byte[] readbuffer = new byte[1];
            byte[] writebuffer = new byte[1];
        
            while (true)
            {
                writebuffer[0] = 0x01;
                readbuffer[0] = 0x00;
                spiDriver.WriteRead(writebuffer, readbuffer);
                if (readbuffer[0] != 0xFF)
                {
                    Debug.Print("Col: " + ((readbuffer[0] >> 4) & 0xF).ToString() + " Row: " + ((readbuffer[0]) & 0xF).ToString());
                }
                Thread.Sleep(100);
            }

        }

    }

Now I get:
Col: 1 Row: 1
Col: 1 Row: 2
Col: 1 Row: 4
Col: 1 Row: 8
Col: 2 Row: 1
Col: 2 Row: 2
Col: 2 Row: 4
Col: 2 Row: 8
Col: 4 Row: 1
Col: 4 Row: 2
Col: 4 Row: 4
Col: 4 Row: 8
Col: 8 Row: 1
Col: 8 Row: 2
Col: 8 Row: 4
Col: 8 Row: 8

EDIT: There is one slight issue - the rows and columns are back to front! Q7 seems to be column 1 not column 4, Q3 seems to be row A not row D.
It is as though the order in which the bits are read is backwards.


Thanks Mario for the original idea, and thanks Glen for the code.

I think I should Wiki this.
I'll correct the circuit diagram to show the !OE signal first.

Paul B)




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.