1

I have trouble reading out an button matrix with my raspberry pi zero w.
I am using pigpio for reading out the gpios, but I don't think this is a software issue.

This is my source code:

#include <stdio.h>
#include <pigpio.h>
#include <unistd.h>

int main() {

    // 2, 3, 4, 14, 15, 18, 17
    int gpio_colums[] = {15, 18, 17};
    int gpio_rows[] = {2, 3, 4, 14};

    if (gpioInitialise() < 0) {
        fprintf(stderr, "pigpio initialisation failed\n");
        return -1;
    }

    for (int i = 0; i < 3; i++) {
        gpioSetMode(gpio_colums[i], PI_OUTPUT);
    }

    for (int i = 0; i < 4; i++) {
        gpioSetMode(gpio_rows[i], PI_INPUT);
        gpioSetPullUpDown(gpio_rows[i], PI_PUD_DOWN);
    }

    while (1) {
        // power every colomn
        for (int i = 0; i < 3; i++) {
            gpioWrite(gpio_colums[i], 1);

            // find pressed button
            for (int j = 0; j < 4; j++) {
                //printf("gpioRead retunrned %d\n", gpioRead(gpio_rows[i]));
                if (gpioRead(gpio_rows[j]) == 1) {
                    printf("column gpio pin %d, row gpio pin %d\n", gpio_colums[i], gpio_rows[j]);
                    printf("column %d row %d\n", i, j);
                    usleep(200);            
                }
            }

            gpioWrite(gpio_colums[i], 0);
        }
    }

    return 0;
}

As ouput i get an endeless output.

column 1 row 2
column gpio pin 18, row gpio pin 14
column 1 row 3
column gpio pin 15, row gpio pin 2
column 0 row 0
column gpio pin 15, row gpio pin 3
column 0 row 1
column gpio pin 15, row gpio pin 4
column 0 row 2
column gpio pin 15, row gpio pin 14
column 0 row 3
column gpio pin 18, row gpio pin 2
column 1 row 0
column gpio pin 18, row gpio pin 3
column 1 row 1
column gpio pin 18, row gpio pin 4
column 1 row 2
column gpio pin 18, row gpio pin 14
column 1 row 3
column gpio pin 15, row gpio pin 2
column 0 row 0
column gpio pin 15, row gpio pin 3
column 0 row 1
column gpio pin 15, row gpio pin 4
column 0 row 2
and so on ...

This is the button matrix i am using:

I conneted it from left to right with the gpio pins 2, 3, 4, 14, 15, 18, 17.

I checked for electrical continuity and the button matrix and found with the folloring result.

Button matrix pins (from 0 to 6) continuity if button pressed:
Afer the '|' are the gpios that should be active

0 + 6 = '3' | 2 + 17
1 + 6 = '6' | 3 + 17
2 + 6 = '9' | 4 + 17
3 + 6 = '#' | 14 + 17

0 + 5 = '2' | 2 + 18
1 + 5 = '5' | 3 + 18
2 + 5 = '8' | 4 + 18
3 + 5 = '0' | 14 + 18

0 + 4 = '1' | 2 + 15
1 + 4 = '4' | 3 + 15
2 + 4 = '7' | 4 + 15
3 + 4 = '*' | 14 + 15

To compile the source gcc -o key main.c -lpigpio -lrt -lpthread

What am i doing wrong?
Thx for your help.

  • Is if (gpioRead(gpio_rows[i]) == 1) a typo? Should that be if (gpioRead(gpio_rows[j]) == 1) (with a j). – joan Jul 6 at 15:14
  • You are right, I fixed it. – Ace of Spade Jul 6 at 15:17
  • Hello. Just to clarify, is the problem that column 2 is being missed or that the button logic is wrong? If I compile a cut-down copy of your code (without the gpio stuff) I get output that includes column 2 row 0 etc.etc. Do you get any compilation errors? Can you post a more complete source listing that can be compiled? – Roger Jones Jul 6 at 16:23
  • I added the complete code and instruction how to compile. – Ace of Spade Jul 6 at 18:42
1

I fixed it by using configuring the gpios as pullups instead of pulldowns. The api didn't return an error, but it seams like is not possible to configure the used pins as pulldown. To avoid short circuit if two buttons are pressed at the same time I also had to set the not used OUTPUT gpio pins to inputs.

This is my working code example:

#include <stdio.h>
#include <pigpio.h>
#include <unistd.h>

int main() {

    // 2, 3, 4, 14, 15, 18, 17
    int gpio_colums[] = {15, 18, 17};
    int gpio_rows[] = {2, 3, 4, 14};

    if (gpioInitialise() < 0) {
        fprintf(stderr, "pigpio initialisation failed\n");
        return -1;
    }

    for (int i = 0; i < 3; i++) {
        gpioSetMode(gpio_colums[i], PI_INPUT);
        gpioSetPullUpDown(gpio_colums[i], PI_PUD_UP);
    }

    for (int i = 0; i < 4; i++) {
        gpioSetMode(gpio_rows[i], PI_INPUT);
        if (gpioSetPullUpDown(gpio_rows[i], PI_PUD_UP) < 0) {
            fprintf(stderr, "pigpio initialisation failed\n");
            return -1;
        }
    }

    while (1) {
        // power every colomn
        for (int i = 0; i < 3; i++) {
            gpioSetMode(gpio_colums[i], PI_OUTPUT);
            gpioWrite(gpio_colums[i], 0);
            usleep(10); // give the electronic components a bit time
            // find pressed button
            for (int j = 0; j < 4; j++) {
                //printf("gpioRead retunrned %d\n", gpioRead(gpio_rows[i]));
                if (gpioRead(gpio_rows[j]) == 0) {
                    printf("column gpio pin %d, row gpio pin %d\n", gpio_colums[i], gpio_rows[j]);
                    printf("column %d row %d\n", i, j);
                    usleep(200000);         
                }
            }

            gpioWrite(gpio_colums[i], 1);
            gpioSetMode(gpio_colums[i], PI_INPUT);
        }

        usleep(10000);          
    }

    return 0;
}

Hope will help somebody.

0

Part of the problem is you are using GPIO 2/3. They have external hard wired 1k8 pull-ups to 3V3. That means they will always read high as the internal pull-downs you set are too weak to pull them down to ground.

Please use alternative GPIO and retest.

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.