Pi pins not behaving

I have written a program in C to take over the Pi pins and reset their mode input / output on a Pi4. I had to update the wiringPi library ( details in the code comments).

I was able to set the selected pins to input or output as required and when setting the pins to output was able to set high or low. However when setting as an input pin, I was not able to set the mode for pull up or pull down or tristate.

I tried using the command line interface with commands of:

gpio mode 8 out
gpio mode 8 in

Which worked. Pin 8 was always in pull up mode when configured as input.

I tried:

gpio mode 8 down,
gpio mode 8 up
gpio mode tri

none of these made any difference

Please advise why this is not working and what I need to do to be able to set the pull up/down/tristate mode.

Code is:

/*
wiringpi for Pi 4:
download latest version:
cd /tmp
wget https://project-downloads.drogon.net/wiringpi-latest.deb
sudo dpkg -i wiringpi-latest.deb

display wiring table on pi:
gpio readall
 
 +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 |   IN | 1 |  3 || 4  |   |      | 5v      |     |     |
 |   3 |   9 |   SCL.1 |   IN | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 1 | IN   | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | IN   | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 1 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI | ALT0 | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO | ALT0 | 0 | 21 || 22 | 1 | IN   | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK | ALT0 | 0 | 23 || 24 | 1 | OUT  | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 1 | OUT  | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+---Pi 4B--+---+------+---------+-----+-----+

PinMode:
http://wiringpi.com/reference/core-functions/
void pinMode (int pin, int mode) ;    mode: INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK
  NOTE: only  pin 1   // 12, supports PWM
              pin 7   // 7, supports CLOCK output
        This function has no effect when in Sys mode
void pullUpDnControl (int pin, int pud) ;   should be set as input
  pud:
        PUD_OFF, (no pull up/down)
        PUD_DOWN (pull to ground)     approximately 50KO
        PUD_UP (pull to 3.3v)         approximately 50KO
  This function has no effect on the Raspberry Pi’s GPIO pins when in Sys mode. 
  If you need to activate a pull-up/pull-down, then you can do it with the gpio 
  program in a script before you start your program.
void digitalWrite (int pin, int value) ;
  Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output.
  WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW.
void pwmWrite (int pin, int value) ;
  Writes the value to the PWM register for the given pin. The Raspberry Pi has 
  one on-board PWM pin, pin 1 (BMC_GPIO 18, Phys 12) and the range is 0-1024.
  This function is not able to control the Pi’s on-board PWM when in Sys mode.
int digitalRead (int pin) ;
  This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0)
   depending on the logic level at the pin.

See also:
  http://wiringpi.com/the-gpio-utility/
  https://pinout.xyz/pinout/gpclk
  https://www.raspberrypi.org/forums/viewtopic.php?t=22274
*/




#include <wiringPi.h>

    
// Pi Pin definitions:
#define S91 8   // 3
#define S92 9   // 5
#define S2  30  // 27
#define S3  31  // 28


int main( void) {
  
  wiringPiSetup();
  
  pinMode(S91, INPUT);
  pinMode(S92, INPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  
  pullUpDnControl (S91, PUD_DOWN) ;
  pullUpDnControl (S92, PUD_DOWN) ;
  
  while (1) {
    if ( digitalRead(S91 )) {
      digitalWrite(S3, HIGH);
      delay(100);
    
      digitalWrite(S3, LOW);
      delay(100);
    } else {
      digitalWrite(S3, LOW);
      delay(100);
    }
  }
  
  return 0;
}


/*
gcc toggle2.c -o toggle2 -lwringPi
sudo ./toggle

*/
1 Like

Hi Clem,

It sounds like they are sticking to the default settings of the GPIO, I found this reference over on Pi foundations website for the peripherals of the processor on the Pi 4: https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf - page 67 for the GPIO defaults and alternate functions.

Would using another library such as quick2wire work here?

This sounds like a deep rabbit hole and might be best answered that is very well versed in the silicon itself on the Pi. I had a look through past posts and they are verging on the realm of a fully engineered solution.
The fastest way to get an answer would probably be to take a look through the documentation for the BMC and trying to force the pin into the input mode you want using the registers themselves/some kind of HAL.

3 Likes

Hey Clem,

For compiling and running this, did you mean?

gcc toggle2.c -o toggle2 -lwiringPi
sudo ./toggle2

Just noticed the comments at the end

2 Likes

Regarding the -lwiringpi

I see that I spelled it wrongly in the source code comment but spelled it correctly when i made the compile command - thanks for noticing it. but it is not the problem.

I have skimmed the BMC document you have placed a link to - looks complicated - no example C code, potential to do something dangerous without even knowing exists! Who knows the consequence of writing to memory addresses you are not sure of to give the right result. Not clear even if sequences are required for correct access. I have to get something working in a hurry so may just use lower value resistors to PULL the inputs where they have to go. Ok for immediate but not desirable for long term. Is anyone aware of any C code examples which would set the pull up and pull down mode settings of the OP pins?

1 Like

Hey Clem,

Just to clarify the issue a little more, is it that you are trying to switch the mode between pull-up, pull-down and tristate on a given pin?

Below is the readme for WiringPi-Node Repo, this should be the function from that library that you require to be able to set the pull-up/pull-down resistor for each pin if that’s what you’re after. You simply call:

pullUpDnControl(pinNumber, PUD_OFF) pullUpDnControl(pinNumber, PUD_UP) or pullUpDnControl(pinNumber, PUD_DOWN) respectively, as you have already done for the pins

pullUpDnControl(pin, pud)

>= 0.2.0

This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input.

Unlike Arduino, the BCM2835 has both pull-up and down internal resistors.

The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi.

pud can be one of the following values:

  • PUD_OFF no pull up/down >= 0.2.0
  • PUD_DOWN pull to ground >= 0.2.0
  • PUD_UP pull to 3.3v >= 0.2.0

By the way, for anyone getting started with this library. I highly suggest reading through these pages, they cover just about everything that you need to know and the docs are fairly thoughrough:

2 Likes

Hey Clem,

You would be hard pushed to find any example code for something like this in documentation, this is where some knowledge of the area is required. Yes writing to addresses can be dangerous but very powerful and in this instance it would get you out of trouble probably the fastest.
Long term it might be worth doing a dive into the intricacies of the hardware itself so you have the knowledge there for other projects.
I understand it is a little bit wasteful having to implement the resistors yourself but is there a reason why you couldn’t make a ‘do-it-all’ HAT out a PCB/Perfboard for each project?

A lot of other makers seem to be using the quick2wire library I mentioned before along with admin-GPIO.

2 Likes