logo
background
 Home and Links
 Your PC and Security
 Server NAS
 Wargames
 Astronomy
 PhotoStory
 DVD making
 Raspberry Pi
 PIC projects
 Other projects
 Next >>

Controlling the Pi photoframe from a GPIO button

Pi GPIO button

Controlling (pausing) the photoframe display with a button (or switch)

The first thing you are likely to want is the ability to 'pause' your 'photo slide show' so you can talk about a photo. This requires a button or switch be fitted to one of the GPIO pins .. and then 'sensed' in software .. and then (somehow) used to 'pause' the display ... let the fun begin !

Fitting the button turns out to be the 'easy' part. Problems start when you discover that the 'pi' user has 'insufficient permissions' to access the gpio /sys/class path (so can't set up the pin) and, after solving that, you discover that the fbi utility is unable to run in 'background mode' (adding '&' to the end of the command just results in the dreaded 'ioctl error') so the script 'stops' on the fbi command and never reaches the 'check the button' code

Fitting the button

Assuming the button will be 'removable' (i.e. optional), we would ideally like to 'plug' it into the GPIO pin strip using a multi-pin wiring socket.


If you want Power (3v3) and Gnd as well as some i/o pin, and restrict yourself to 'uncommitted' io pins (and want to stick to the 'top half' of the header, which is identical across all Pi's), the minimum 'in one row' you can get away with are the 5 pins at GPIO header pin9 to pin17 inclusive (pin9 is Gnd, pin11,13,15 i/o 17,27 and 22 with pin17 3v3 power)

If the button is at the end of a 'long' cable wired direct to an i/o pin, any RFI 'pick up' on the cable could be injected into the i/o pin and damage to the Pi. To avoid problems it's a 'good idea' to use an opto-isolator (as well as UTP or co-ax cable).

Needless to say, the button should 'ground' the opto-isolator input, thus avoiding the possibility of RFI pick-up being injected into the Pi 3.3v line

Reading and writing GPIO pins from the Command Line Interface (CLI) is easy but very 'non-intuitive'. For one, you must have 'root' permissions to actually 'enable' (or disable) the GPIO pins

Alternatively, just install the Wiring Pi library from https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/- once installed, the new command 'gpio' can be used at non-root level to control the GPIO pins and will save you a lot's of time (but introduces more confusion by re-numbering the pins yet again):-)

Testing the button from the command line (PuTTY)

Needless to say, the 'pi' user account has no 'permission' to access the gpio 'system class', so you can't 'test' things are working manually. The ONLY thing I found to work was to actually log-in as 'root' (putting 'sudo' in front of the commands gets you past the 'Permission denied' but then you get locked into a 'No such file or directory' error)

If you installed Wiring Pi, you need to add the 'pi' user to the 'gpio' user group (sudo usermod -aG gpio pi) - others have suggested giving another group that pi is a member of (eg the dial-out user group) permission to access gpio, however I never got that to work

So, to access /sys/class/gpio from PuTTY (eg test the button is working), you must log-in as 'root'. If you have not already created a root password, login as 'pi' then type 'sudo -i'. When you get the 'root@raspberrypi:-#' prompt, type 'passwrd root'. Then, in response to 'Enter new UNIX password:' respond with whatever you want the password to be (eg 'root') and confirm.

Then CLOSE PuTTY, launch it again and this time log-in as root / {your password}. The commands below (echo "17".., cat /sys/class.. etc) will now just work 'OK'

The following will 'work' from PuTTY ONLY if you are logged in as 'root' (if you are logged in as 'pi', even if you prefix 'echo' with 'sudo', you will get a 'Permission denied' error)

# Enable GPIO 17 ('export' it), set it to input mode (actually, it defaults to that) :- echo "17" > /sys/class/gpio/export echo "in" > /sys/class/gpio/gpio17/direction# if your button circuit has no pull-up, to enable the GPIO internal 'pull up' resistor :- echo "high" > /sys/class/gpio/gpio17/direction# Read the button state from GPIO17 tot he command line (0 = pushed or 1 = not pushed)) cat /sys/class/gpio/gpio17/value# When finished, disable the input again echo "17" > /sys/class/gpio/unexport

Modify the Photoframe display sequence

Of course, having a shell script set up a gpio input runs straight into the 'permission denied' error problem.

Changing the owner of the script to root (chown root:root myscript.sh) and giving it root permissions (chmod 4755 myscript.sh) had no effect on the dreaded 'Permission denied' error.

In the end, the ONLY thing that worked is to prefix each gpio setup command with "sudo sh -c" as follows :-

# clear any current setting (gpio remains set after the script crashes) sudo sh -c 'echo "17" > /sys/class/gpio/unexport' sudo sh -c 'echo "17" > /sys/class/gpio/export' sudo sh -c 'echo "in" > /sys/class/gpio/gpio17/direction' # show the button status and give the user a chance to see it (allows test at power-on) echo "Button detect - 'blank' = gpio didn't program, 1=default (not pressed, not plugged in), 0 = pressed" cat /sys/class/gpio/gpio17/value sleep 3

Once the gpio pin has been setup as an input, it can be monitored by the script (using 'cat /sys/class/gpio/gpio17/value') and used to control the Photoframe display. All the script has to do is check that the button is 'released' after copying the new photo and before updating the display 'alias' to point at the new buffer.

The go-button.sh script

The go-button.sh script replaces the 'go-photo.sh' script. For more information, see below :-