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()