Introduction: RaspberryPi: Multiple Buttons on One Digital Pin

About: Jack passed away May 20, 2018 after a long battle with cancer. His Instructables site will be kept active and questions will be answered by our son-in-law, Terry Pilling. Most of Jack's instructables are tuto…

If you ever find yourself running out of GPIO pins on a RaspberryPi you can put multiple pushbutton switches on a single pin using this method. It sets a variable by timing the charging of a capacitor through a series of resistors with the switches between them.

You will need a RaspberryPi, a breadboard, and a way to run wires from the RaspberryPi to the breadboard. You can use male/female jumper wires but one of the Pi Cobblers listed on this page from Adafruit will make it a lot easier: http://www.adafruit.com/search?q=cobbler

You will also need:

* This is a very handy assortment of resistors https://www.sparkfun.com/products/10969

.

This project uses the wiringPi libraries, written by Gordon Henderson, for programming the GPIO in C in a style similar to the Arduino IDE.

wiringPi must be installed.

Instructions for download, install and use are located at http://wiringpi.com

wiringPi uses it's own pin numbering scheme. All pin numbers mentioned in the program or in the text are wiringPi numbers unless otherwise specified.

After installing wiringPi you can obtain a list showing the pin numbering for your specific model of RaspberryPi by opening a command terminal and typing:

gpio readall

Step 1: Build the Circuit

Build the circuit as shown in the diagram.

Step 2: The Program

I wrote this on a new Raspberry model 2. If you are using an older model some re-calibration will be necessary. The numbers in the case statements will need to be higher. Comment out the whole switch statement and temporarily replace it with

printf("%ld\n", ButtonReading);

This will make it easier to find the new numbers if you need to re-calibrate it for any reason.

And it should work if you add or subtract buttons.

If you try to press more than one button at a time only the higher numbered button will register.

This program contains a new improved version of the RCtime() function that I used in this instructable:

https://www.instructables.com/id/Simulated-analogdigital-converter-for-RaspberryPi/

/***********************************************************************
 * Filename: Switches.c
 * This program demonstrates a way to simulate an analog read by measuring 
 * the time it takes to charge a capacitor through a resistance. It uses
 * resistors in series and buttons between them.
 ***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>

int ButtonPin = 0;   // Resistors in series and capacitor connected to pin zero.

/***********************************************************************        
 * RCtime() - Function, uses a digital pin to measure resistance by first 
 * discharging capacitor then measuring the time it takes to charge the
 * capacitor through the resistance. When the voltage rises to Vcc/2 the 
 * pin will go high.
 ***********************************************************************/
long RCtime(int RCpin)
{
  pinMode(RCpin, OUTPUT);             // Set pin to output,
  digitalWrite(RCpin, LOW);           // and pull to low.    

  delay(4);                           // Allow time to let capacitor discharge.

  long time = micros();
                          
  pinMode(RCpin, INPUT);              // Now set the pin to an input,
  pullUpDnControl(RCpin, PUD_OFF);    // turn off internal pull down resistor,
  while (digitalRead(RCpin) == LOW);  // and wait for it to go high.

  long PinVal = micros() - time;
  
  return PinVal;                                 
}

/**************************************************************************        
 * loop() - function runs in a continuous loop until program is stopped.
 **************************************************************************/
void loop(void)
{
  long ButtonReading = RCtime(ButtonPin); // Read Buttons into ButtonReading.

  switch(ButtonReading)
  {
    case 6200 ... 8000:
    {
      printf("%ld - No button pressed.\n", ButtonReading);
      break;
    }
    case 5500 ... 6199:
    {
      printf("%ld - button one pressed.\n", ButtonReading);
      break;
    }
    case 4500 ... 5499:
    {
      printf("%ld - button two pressed.\n", ButtonReading);
      break;
    }
    case 3000 ... 4499:
    {
      printf("%ld - button three pressed.\n", ButtonReading);
      break;
    }
    case 2000 ... 2999:
    {
      printf("%ld - button four pressed.\n", ButtonReading);
      break;
    }
    case 1000 ... 1999:
    {
      printf("%ld - button five pressed.\n", ButtonReading);
      break;
    }
  }
  delay(100);
}

/***********************************************************************        
 * setup() - function is run by main() one time when the program starts.
 ***********************************************************************/
void setup(void)
{
  wiringPiSetup();   // Required.

  RCtime(ButtonPin); // Throw out first reading.
}

/***********************************************************************        
 * main() - required
 ***********************************************************************/
int main(void)
{
  setup();

  while(1)
  {
    loop();
  }
}


Download the program and compile it with the command:

gcc -o Switches Switches.c -lwiringPi

And run the program with the command:

sudo ./Switches