The Green Shed

GPIO Button Handling on RaspberryPi in Ruby

I’ve working on adding some physical controls to my kitchen status display. The setup is very simple, and for a first-run all I wanted to be able to do was detect a button press, and run a script somewhere on the system.

I couldn’t find any existing code that does this (please point some out if you know of any), though there’s plenty of code out there for button handling in general.

Also, most of the code out there for doing GPIO work is either in C or Python, and I was hoping for a Ruby solution, or at least a solution that would be easy to wrap in Ruby.

In the end I learned about how to interface with the GPIO system on RPi via the filesystem.

From there, I found this code from Aaron Patterson using epoll to monitor for changes in the level on the monitored pin. That seemed like it would work, but the epoll gem seems to be unmaintained at this point. Instead, I went with the Sleepy Penguin gem, which provides an interface to the same underlying Linux filesystem events.

Lastly, I wanted my pin pulled high by default, and there’s no way to do that via Sysfs, so I ended up using the gpio utility to set the pin state and pull up resistor.

From there, I was able to run this little script, which will output the current state of the pin when it changes.

# install gpio command line tool
# gpio -g mode 16 up
require 'sleepy_penguin'

def watch pin, on:

  puts "Setup Export"
  File.binwrite "/sys/class/gpio/export", pin.to_s

  puts "Setup Edge"

  retries = 0

    File.binwrite "/sys/class/gpio/gpio#{pin}/edge", on
    raise if retries > 3
    sleep 0.1
    retries += 1

  puts "Read Value"

  fd = "/sys/class/gpio/gpio#{pin}/value", 'r'

  puts "Setup epoll"

  epoll =
  epoll.add fd, SleepyPenguin::Epoll::PRI

  puts "Start loop wait"
  loop do 0, IO::SEEK_SET
    epoll.wait do
      # yield
      value =
      p value

  File.binwrite "/sys/class/gpio/unexport", pin.to_s

pin = 16

watch pin, on: 'both' do |value|
  p value

Still to come: debouncing, better handling of a change event, and hopefully wrapping it all up into something much easier to work with.