Reading Buttons with GPIO

One of the better things to do with a GPIO bus is read inputs. The Raspberry PI can only read digital inputs directly, i.e. on or off. Conveniently, that's also the modes of a momentary switch.

There aren't any new gpio functions here. The biggest difference is that we're setting one of our pins (pin 22 in this case) to be an input.

The setup for reading buttons

The Code

Momentary button input is a tricky beast. The button will be pushed for a variable amount of time. The program will poll the state of the button very rapidly. To make each button push count only once, we need to keep track of the state of the button on each poll, and only take action when:

  1. The state has changed.
  2. The pin is high.

I have also introduced some slight delays. When the state of the button changes, we're pausing for a tenth of a second to make sure that we get a chance for the light to change state. At the end of each loop we're pausing for a 100th of a second just because polling more frequently doesn't really do any good.

button.c
/**
 * Button pushing demo
 */
 
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <libgpio.h>
#include <time.h>
 
const struct timespec one_hundredth = { 0, 10 };
const struct timespec one_tenth = {0, 1000};
 
int main(int argc, char **argv)
{
	gpio_handle_t handle;
	int led_pin = 19;
	int button_pin = 22;
	int ledstate = GPIO_PIN_LOW;
	int buttonstate;
	int lastbuttonstate;
 
	handle = gpio_open(0);
 
	gpio_pin_input(handle, button_pin);
	gpio_pin_output(handle, led_pin);
	gpio_pin_low(handle, led_pin);
	gpio_pin_low(handle, button_pin);
 
	while(1) {
		buttonstate = gpio_pin_get(handle, button_pin);
		if (lastbuttonstate != buttonstate) {
			lastbuttonstate = buttonstate;
			if (GPIO_VALUE_HIGH == buttonstate) {
				switch(ledstate) {
				case GPIO_PIN_LOW:
					gpio_pin_high(handle, led_pin);
					ledstate = GPIO_PIN_HIGH;
					break;
				case GPIO_PIN_HIGH:
					gpio_pin_low(handle, led_pin);
					ledstate = GPIO_PIN_LOW;
					break;
				}
				printf("TOGGLE %d\n", ledstate);
				nanosleep(&one_tenth, NULL);
			}
		} else {
			lastbuttonstate = buttonstate;
		}
 
		nanosleep(&one_hundredth, NULL);
	}	
}