0

3x4 Matrix Key pad used with the Raspberry Pi
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

3x4 Matrix Key pad used with the Raspberry Pi

by rainierez on Mon Jun 24, 2013 11:18 am

I recently picked up one of the 3x4 matrix keypads as part of a project with my RPI. There really wasn't any existing code specific for the RPi and or python so I wrote up a script for it. I've included 2 versions. One uses the straight RPi's GPIO pins and then the one I needed was to use the MCP23017 chip. This uses the already existing python library from Adafruit's.

Here is my blog post with some details: http://crumpspot.blogspot.com/2013/05/using-3x4-matrix-keypad-with-raspberry.html

RPi GPIO verion:
Code: Select all | TOGGLE FULL SIZE
# #####################################################
# Python Library for 3x4 matrix keypad using
# 7 of the avialable GPIO pins on the Raspberry Pi.
#
# This could easily be expanded to handle a 4x4 but I
# don't have one for testing. The KEYPAD constant
# would need to be updated. Also the setting/checking
# of the colVal part would need to be expanded to
# handle the extra column.
#
# Written by Chris Crumpacker
# May 2013
#
# main structure is adapted from Bandono's
# matrixQPI which is wiringPi based.
# https://github.com/bandono/matrixQPi?source=cc
# #####################################################
 
import RPi.GPIO as GPIO
 
class keypad():
    # CONSTANTS   
    KEYPAD = [
    [1,2,3],
    [4,5,6],
    [7,8,9],
    ["*",0,"#"]
    ]
     
    ROW         = [18,23,24,25]
    COLUMN      = [4,17,22]
     
    def __init__(self):
        GPIO.setmode(GPIO.BCM)
     
    def getKey(self):
         
        # Set all columns as output low
        for j in range(len(self.COLUMN)):
            GPIO.setup(self.COLUMN[j], GPIO.OUT)
            GPIO.output(self.COLUMN[j], GPIO.LOW)
         
        # Set all rows as input
        for i in range(len(self.ROW)):
            GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
         
        # Scan rows for pushed key/button
        # A valid key press should set "rowVal"  between 0 and 3.
        rowVal = -1
        for i in range(len(self.ROW)):
            tmpRead = GPIO.input(self.ROW[i])
            if tmpRead == 0:
                rowVal = i
                 
        # if rowVal is not 0 thru 3 then no button was pressed and we can exit
        if rowVal <0 data-blogger-escaped-or="" data-blogger-escaped-rowval="">3:
            self.exit()
            return
         
        # Convert columns to input
        for j in range(len(self.COLUMN)):
                GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
         
        # Switch the i-th row found from scan to output
        GPIO.setup(self.ROW[rowVal], GPIO.OUT)
        GPIO.output(self.ROW[rowVal], GPIO.HIGH)
 
        # Scan columns for still-pushed key/button
        # A valid key press should set "colVal"  between 0 and 2.
        colVal = -1
        for j in range(len(self.COLUMN)):
            tmpRead = GPIO.input(self.COLUMN[j])
            if tmpRead == 1:
                colVal=j
                 
        # if colVal is not 0 thru 2 then no button was pressed and we can exit
        if colVal <0 data-blogger-escaped-colval="" data-blogger-escaped-or="">2:
            self.exit()
            return
 
        # Return the value of the key pressed
        self.exit()
        return self.KEYPAD[rowVal][colVal]
         
    def exit(self):
        # Reinitialize all rows and columns as input at exit
        for i in range(len(self.ROW)):
                GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
        for j in range(len(self.COLUMN)):
                GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_UP)
         
if __name__ == '__main__':
    # Initialize the keypad class
    kp = keypad()
     
    # Loop while waiting for a keypress
    digit = None
    while digit == None:
        digit = kp.getKey()
     
    # Print the result
    print digit


RPi with MCP230xx:
Code: Select all | TOGGLE FULL SIZE
# #####################################################
# Python Library for 3x4 matrix keypad using
# the MCP23008 chip via I2C from the Raspberry Pi.
#
# This could easily be expanded to handle a 4x4 but I
# don't have one for testing. The KEYPAD constant
# would need to be updated. Also the setting/checking
# of the colVal part would need to be expanded to
# handle the extra column.
#
# Written by Chris Crumpacker
# May 2013
#
# main structure is adapted from Bandono's
# matrixQPI which is wiringPi based.
# https://github.com/bandono/matrixQPi?source=cc
# #####################################################
 
from Adafruit_MCP230xx import Adafruit_MCP230XX
 
class keypad(Adafruit_MCP230XX):
    # Constants
    INPUT       = 0
    OUTPUT      = 1
    HIGH        = 1
    LOW         = 0
     
    KEYPAD = [
    [1,2,3],
    [4,5,6],
    [7,8,9],
    ["*",0,"#"]
    ]
     
    ROW         = [6,5,4,3]
    COLUMN      = [2,1,0]
     
    def __init__(self, address=0x21, num_gpios=8):
         
        self.mcp2 = Adafruit_MCP230XX(address, num_gpios)
         
    def getKey(self):
         
        # Set all columns as output low
        for j in range(len(self.COLUMN)):
            self.mcp2.config(self.COLUMN[j], self.mcp2.OUTPUT)
            self.mcp2.output(self.COLUMN[j], self.LOW)
         
        # Set all rows as input
        for i in range(len(self.ROW)):
            self.mcp2.config(self.ROW[i], self.mcp2.INPUT)
            self.mcp2.pullup(self.ROW[i], True)
         
        # Scan rows for pushed key/button
        # valid rowVal" should be between 0 and 3 when a key is pressed. Pre-setting it to -1
        rowVal = -1
        for i in range(len(self.ROW)):
            tmpRead = self.mcp2.input(self.ROW[i])
            if tmpRead == 0:
                rowVal = i
                 
        # if rowVal is still "return" then no button was pressed and we can exit
        if rowVal == -1:
            self.exit()
            return
         
        # Convert columns to input
        for j in range(len(self.COLUMN)):
            self.mcp2.config(self.COLUMN[j], self.mcp2.INPUT)
         
        # Switch the i-th row found from scan to output
        self.mcp2.config(self.ROW[rowVal], self.mcp2.OUTPUT)
        self.mcp2.output(self.ROW[rowVal], self.HIGH)
         
        # Scan columns for still-pushed key/button
        colVal = -1
        for j in range(len(self.COLUMN)):
            tmpRead = self.mcp2.input(self.COLUMN[j])
            if tmpRead == 1:
                colVal=j
         
        if colVal == -1:
            self.exit()
            return
               
        # Return the value of the key pressed
        self.exit()   
        return self.KEYPAD[rowVal][colVal]
             
    def exit(self):
        # Reinitialize all rows and columns as input before exiting
        for i in range(len(self.ROW)):
                self.mcp2.config(self.ROW[i], self.INPUT)
        for j in range(len(self.COLUMN)):
                self.mcp2.config(self.COLUMN[j], self.INPUT)
         
if __name__ == '__main__':
    # Initialize the keypad class
    kp = keypad()
     
    # Loop while waiting for a keypress
    r = None
    while r == None:
        r = kp.getKey()
         
    # Print the result
    print r


Here is a demo usage script, just comment and uncomment the import lines to switch between the two versions.
Code: Select all | TOGGLE FULL SIZE
# #####################################################
# Demo script showing the use of the Python
# matrix Keypad library for both the Raspberry Pi
# GPIO and the MSP230xx I2C Chip set.
#
# Librarys needed:
# matrixKeypad_MCP230xx.py or matrixKeypad_RPi_GPIO.py
#
# Also needed is the Adafruit python libraries for the
# MCP230xx chips (Adafruit_MCP230xx.py) and I2C (Adafruit_I2C.py)
#
# Written by Chris Crumpacker
# May 2013
#
# #####################################################
 
from matrixKeypad_MCP230xx import keypad
#from matrixKeypad_RPi_GPIO import keypad
from time import sleep
 
# Initialize the keypad class
kp = keypad()
 
def digit():
    # Loop while waiting for a keypress
    r = None
    while r == None:
        r = kp.getKey()
    return r
 
print "Please enter a 4 digit code: "
 
# Getting digit 1, printing it, then sleep to allow the next digit press.
d1 = digit()
print d1
sleep(1)
 
d2 = digit()
print d2
sleep(1)
 
d3 = digit()
print d3
sleep(1)
 
d4 = digit()
print d4
 
# printing out the assembled 4 digit code.
print "You Entered %s%s%s%s "%(d1,d2,d3,d4)

rainierez
 
Posts: 1
Joined: Mon Jun 24, 2013 11:07 am
Location: Indiana

Re: 3x4 Matrix Key pad used with the Raspberry Pi

by adafruit_support_mike on Tue Jun 25, 2013 7:32 pm

Awesome! Thank you for sharing!
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.

adafruit_support_mike
 
Posts: 59386
Joined: Thu Feb 11, 2010 2:51 pm

Please be positive and constructive with your questions and comments.