0

I'm using RPi.GPIO and making a switch matrix which waits for rising or falling edges caused by switch toggles in the rows, triggering a scan of all the switches. I have one interrupt for each row, so any switch toggle can trigger the scan function in the threaded callback thread.

for i in RowList:
    GPIO.add_event_detect(i, GPIO.BOTH, callback=MatrixScan, bouncetime=100)

Within the MatrixScan function, each column is initially set to input. Then, each column is set low and each row scanned for switch states. Then, everything is set back to the default state of low output.

for i in ColumnList:
    GPIO.setup(i, GPIO.IN)

for i in ColumnList:
    GPIO.setup(i, GPIO.OUT, initial=GPIO.LOW)
    for j in RowList:
        if not GPIO.input(j):
            #do something
    GPIO.setup(i, GPIO.IN)

for i in ColumnList:
    GPIO.setup(i, GPIO.OUT, initial=GPIO.LOW)

Since the interrupt in the main function waits for any row to change state, does the fact that the MatrixScan function will cause state changes in rows mean that another MatrixScan run will be queued to run immediately after this one (ad infinitum)? Or are new operations not queued in this thread while something is running? If this is an issue, what practical solution is there?

EDIT: To be clear, when reading the rows, my rows are set with pull-up resistors, so they should be pulled low when a connection is made to a column (set to output LOW)

EDIT: A perhaps better option, as brought up by Pokebab, for the MatrixScan code is simply:

for i in ColumnList:
    GPIO.output(i, GPIO.HIGH)

for i in ColumnList:
    GPIO.output(i, GPIO.LOW)
    for j in RowList:
        if not GPIO.input(j):
            #do something
    GPIO.output(i, GPIO.HIGH)

for i in ColumnList:
    GPIO.output(i, GPIO.HIGH)

In this situation, to make sure I have my thinking correct, a row pin (with a pull-up resistor) pulled low by a low output column pin will read False on GPIO.input(), right?

  • This looks like it won't work. You either declare your GPIO pin as an input or an output. Here you are setting your GPIOs as outputs, then checking the same GPIO for an input - it's not going to work. – Pokebab Aug 7 at 10:43
  • I'm not sure I understand your comment-- I'm only setting the columns as inputs to clear their state. I only ever practically use the columns as low outputs and read the rows as inputs to see if they are pulled low. I never read the columns and never set the rows as outputs. – hazmathematics Aug 7 at 19:36
  • It looks to me as if you're trying to cycle through each column by pulling each of the outputs low one at a time and the reading which row has an input, this is fine. My problem is that you're using GPIO.setup repeatedly in for loops, which doesn't seem like a stable method of doing this. What you ought to do is define your pins as outputs and inputs at the top of your code. Then you should change your column to low and check for each row and then set the column output as high. – Pokebab Aug 7 at 20:07
  • Ah, got it. The pins are defined at the top of the code, I was just including snippets here. So I could just replace GPIO.setup to flip columns between input and output with GPIO.output to flip columns between low and high while keeping them set as output? My initial rationale was to avoid setting almost all of the columns high at the same time. – hazmathematics Aug 7 at 20:28
  • Yes. You need to keep all but one column high at the same time when checking for inputs or you will not be able to detect which column the input came from. If you're worrying about drawing too much current out of the Pi all at once, so long as you have 10k pull up resistors on the inputs, each column will only have 0.33mA drawn so you have nothing to worry about unless you have hundreds of columns. – Pokebab Aug 7 at 20:42

Your Answer

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

Browse other questions tagged or ask your own question.