3

I'm trying to make an interrupt based matrix keypad reader that is loosely based off of this library. However, I'm getting some really weird effects when trying to use GPIO.add_event_detect in that:

  • Despite wanting the falling edge, I get the rising edge as well
  • In some cases, the callback continues to fire until I release the key. Weirdly, this seems to only happen on column 3 (GPIO #22) and not the others, usually.

In my code, I'm removing the callback events as soon as I enter the callback because I have to switch the columns that were inputs with callbacks to outputs so that I can read the rows and determine the key that was pressed. It always figures out the correct key, it's just that it either fires off continuously and/or gets another call back on the rising edge (key released)... I've accommodated for the rising edge issue in code but I don't get why it should happen in the first place.

Code below, please excuse my many debug print statements:

#!/usr/bin/python

import RPi.GPIO as GPIO

class keypad():
    def __init__(self):
        GPIO.setmode(GPIO.BCM)

        # CONSTANTS 
        self.KEYPAD = [
            [1,2,3],
            [4,5,6],
            [7,8,9],
            ["*",0,"#"]
        ]

        self.ROW         = [18,23,24,25]
        self.COLUMN      = [4,17,22]

        self.__setInterruptMode()

    def __colRise(self, channel):
        print ""
        print "Chan: " + str(channel)
        print "State: " + str(GPIO.input(channel))
        if GPIO.input(channel) > 0:
            return

        #remove interrupt temporarily
        #GPIO.remove_event_detect(channel)
        for c in range(len(self.COLUMN)):
            print "Remove: " + str(self.COLUMN[c])
            GPIO.remove_event_detect(self.COLUMN[c])

        #get column number
        colVal = -1
        for c in range(len(self.COLUMN)):
            if channel == self.COLUMN[c]:
                colVal = c

        print "ColVal: " + str(colVal)

        if colVal >=0 and colVal < len(self.COLUMN):

            #set rows as intputs
            for r in range(len(self.ROW)):
                GPIO.setup(self.ROW[r], GPIO.IN, pull_up_down=GPIO.PUD_UP)

            #set triggered column as output
            GPIO.setup(channel, GPIO.OUT)
            GPIO.output(channel, GPIO.LOW)

            # Scan rows for pushed key/button
            rowVal = -1
            for r in range(len(self.ROW)):
                tmpRead = GPIO.input(self.ROW[r])
                if tmpRead == 0:
                    rowVal = r

            print "RowVal: " + str(rowVal)
            if rowVal >= 0 and rowVal <= 3:
                print str(self.KEYPAD[rowVal][colVal])
            else:
                print "Invalid Row!"
        else:
            print "Invalid Col!"

        #re-enable interrupts
        self.__setInterruptMode()

    def __setInterruptMode(self):
        #set the first row as output low
        #only first one needed as it will ground to all columns
        for r in range(len(self.ROW)):
            GPIO.setup(self.ROW[r], GPIO.OUT)
            GPIO.output(self.ROW[r], GPIO.LOW)

        #set columns as inputs and attach interrupt handlers on rising edge
        for c in range(len(self.COLUMN)):
            GPIO.setup(self.COLUMN[c], GPIO.IN, pull_up_down=GPIO.PUD_UP)
            GPIO.add_event_detect(self.COLUMN[c], GPIO.FALLING, bouncetime=500, callback=self.__colRise)


    def cleanup(self):
        GPIO.cleanup()
        print "Cleanup done!"

import time     
if __name__ == '__main__':
    key = keypad()
    try:
        while True:
            time.sleep(1)

    except KeyboardInterrupt:
        key.cleanup()
  • I have noticed my hardware sortof works like an antenna also. I dont know what your hardware looks like, but raising the high voltage or lowering the low may be worth trying. – ExploWare Mar 21 '14 at 15:52
  • Kinda thought the voltage was fixed at 0V or 3.3V? – Adam Haile Mar 21 '14 at 16:04
  • depends on your resistor-usage, can you show us your hardware? – ExploWare Mar 21 '14 at 16:06
  • It's a standard 4x3 matrix keypad hooked directly into the GPIO pins as described in the code. The only resistors in use are the built in pull up/down resistors on the chip, also as described in the code. Not really much else to show. – Adam Haile Mar 21 '14 at 16:07
  • ok, I don't know much about the internal resistors and how they influence the 3.3v, and if you maybe would be better off make it a pull-down, instead of pullup circuit. But I'm sure someone else has some better knowledge of this part. – ExploWare Mar 21 '14 at 16:16
1

I've heard of this problem before (How does python GPIO bouncetime parameter work?). I think the best solution in the end was to program around the issue, adding code to detect the extra bounces (button presses).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.