I have a Raspberry Pi 0 W, connected with both a WaveShare Battery HAT and a WaveShare 1.44" LCD screen with joystick and three buttons.

The screen works, the joystick works partially and the three buttons do not work at all.

The hardware uses SPI, five GPIO pins for the joystick and three GPIO pins for the three button keys.

I see GPIO pins GPIO.21 and GPIO.22 (physical pins 29 and 31) at V=1 using command-line gpio command, and if I move the joystick up or left, they do change to V=0 as expected.

This does not happen for the other GPIOs, which are shown as V=0 by gpio; therefore the software "sees" e.g. the keys as permanently pressed.

Since I soldered the GPIO header myself, my first hypothesis was a massive soldering fault. I verified that the resistance between the PCB pins of button 1 is above 4 MOhm with button at rest, decreases to zero when button is pressed. Resistance between + pin of button 1 and LCD HAT header is zero as expected. Resistance between LCD HAT header and Pi solder pad is also zero. This is physical pin 40 on the header, or GPIO.29, but gpio doesn't see it at all.

But I can't see what could explain the Pi seeing two pins and not seeing others. The initialization routine is the same for all the pins, so this answer should not apply.

I have checked a possible interference between the two HATs by checking their schematics on the WaveShare Wiki; no joy. Nobody else seems to have had this problems on the forums, which tells me it isn't a software issue. The same problem emerges using gpio, Python and the C source.

The physical position on the board could be a red herring, and yet...

The same code does work flawlessly on a Raspberry Pi 3B without the battery HAT, but this has lots of possibility of actually being a red herring since OS, configuration and power supply are all different. Also, on the full Pi I have installed lots of libraries and code in the past months, so the WaveShare autoconfigure creates a different binary, which doesn't run at all if I copy it on the Zero (an issue for another day).

At this point I have to provisionally conclude that either my Pi is badly broken - only in the GPIO section (!) - or that I forgot to check/setup something really basic.

So, I'm posting a question - I've found that whenever I forget something really stupid, it immediately pops on my mind as soon as I make myself ridiculous by asking for help.


Okay, the lightbulb went off as expected. What if...?

So first I tried running a Python test explicitly setting the GPIO pin to pull-up to verify if this is, under the hood, a duplicate of the question I had referred and there's simply some software issue on top of that.

import RPi.GPIO as GPIO

GPIO.setup(36, GPIO.IN, pull_up_down=GPIO.PUD_UP)    
    while True:
        print GPIO.input(36)
except KeyboardInterrupt:

and lo and behold!, now button 3 works. So why doesn't the sample program?

I checked on BCM2835 library, and found how to do this in C language

// Set RPI pin P1-15 to be an input
bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT);
//  with a pullup
bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP);

So in the end I found a bug in the WaveShare Raspberry code, precisely in obj/DEV_Config.c, where it doesn't set the pin to pull-up, but only when the BCM2835 library is used (WiringPi apparently would have worked).

void DEV_GPIO_Mode(UWORD Pin, UWORD Mode)
#ifdef USE_BCM2835_LIB
    if(Mode == 0 || Mode == BCM2835_GPIO_FSEL_INPT){
        bcm2835_gpio_fsel(Pin, BCM2835_GPIO_FSEL_INPT);
    }else {
        bcm2835_gpio_fsel(Pin, BCM2835_GPIO_FSEL_OUTP);
    printf("Pin %d using WIRINGPI\n", Pin);
    if(Mode == 0 || Mode == INPUT){
        pinMode(Pin, INPUT);
        pullUpDnControl(Pin, PUD_UP);
        pinMode(Pin, OUTPUT);
        // printf (" %d OUT \r\n",Pin);

Armed with this knowledge, I modified the file and re-ran make

if(Mode == 0 || Mode == BCM2835_GPIO_FSEL_INPT){
    bcm2835_gpio_fsel(Pin, BCM2835_GPIO_FSEL_INPT);
    // Set GPIO pin to pull-up
    bcm2835_gpio_set_pud(Pin, BCM2835_GPIO_PUD_UP);

...and now it works.

| improve this answer | |
  • Please accept your own answer with a click on the tick on its left side. Only this will finish the question and it will not pop up again year for year. – Ingo Apr 26 at 17:56

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.