RaspberryPi: Multiple Buttons on One Digital Pin

14K367

Intro: RaspberryPi: Multiple Buttons on One Digital Pin

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

6 Comments

Hi, can we use electrolytic capacitor instead of ceramic ones?

Do they have to be 22k resistors, surely any other would be suitable, it just affects the recharge time. Right?

The value of the resistors affects the recharge time, I just picked 22K because I had a lot of them.

Sorry it took so long to answer, this instructable is old enough I don't check it often.

I would like to thank whoever posted a link to this instructable on http://projects-raspberry.com/raspberrypi-multiple-buttons-on-one-digital-pin-2/

is this method comptible with an arduino?