Introduction: Digital Art Installations With Processing and Raspberry PI
The raspberry pi provides a convenient and unobtrusive means to run digital art made with Processing et al. in a public space.
Specifically the goal of this Instructable is to efficiently run a full-screen processing sketch with basic control from physical buttons, avoiding the need for attached peripherals.
This project will involve access to 3d-printed materials, basic wiring/soldering, and basic Linux scripting.
Step 1: Running Processing
Processing sketches can be run from the Processing environment, or as an exported application. This step will cover both methods, as you'll likely want to run it from the sketch while testing and making changes, and export it for the final result.
The processing download for Linux includes a program called processing-java, which allows the Run, Present, and Export functions of the IDE to be used from the command line.
We'll be running these programs from a script. Our setup uses the following folder organization in the home directory:
/home/pi /screen /sketch /sketch_exported /scripts /pins
The sketch should be launched from a script called 'runprocessing', in the scripts folder (replace 'sketchName' where applicable):
#!/bin/bash if pgrep "sketchName" > /dev/null then # Prevents more than one instance of the sketch from running. Both unwanted and will often badly slow things down. echo "Sketch already running" else #processing-java requires the absolute path to the --sketch and --export folders, so you can't use ~/ DISPLAY=:0 /path/to/processing-java --sketch=/home/pi/screen/sketch --present & fi
If you've already exported the application, the next-to-last line can instead simply read:
DISPLAY=:0 /home/pi/screen/sketch_exported/sketchName &
The variable 'DISPLAY=:0' lets Java know to use the first display on the local system (our screen), when the script isn't called from a graphical terminal (as will be our situation).
While a normal exit of your sketch should be written into the sketch itself, in case there are any network / file / sound connections to close, we'll also want a method of killing the sketch in case it freezes or otherwise crashes.
This can be accomplished simply in another script we'll call 'killprocessing'
#!/bin/bash if pgrep "sketchName" > /dev/null then pkill "java" fi
This will of course kill all java processes running on the system, so be wary if you plan on having other java programs running simultaneously.
Step 2: Watching the GPIO Pins
The GPIO pins can be accessed from various programming languages (python, processing, scratch etc).
Here we'll cover the usage of the program gpio-watch, which will be run at startup of the Pi, and will call our earlier scripts as necessary.
gpio-watch can be found at 'https://github.com/larsks/gpio-watch'. It can be installed with the following commands:
git clone https://github.com/larsks/gpio-watch.git cd gpio-watch make
gpio-watch works by calling scripts within a specified 'pins' directory, named according to the pin number (i.e. the scripts themselves will be named "17", 27", etc. You can write the 'runprocessing' and 'killprocessing' scripts directly into these files if you wish, but for clarity's sake we've chosen to symlink them in instead (this essentially creates an alias of the file in another location). We can execute this as so (the specific pins numbers to use are up to you of course):
cd ~/screen/scripts ln -s runprocessing pins/17 ln -s killprocessing pins/27
We'll then create a new script 'start_gpiowatch' in the scripts folder:
/opt/gpio-watch/gpio-watch -s /home/pi/screen/scripts/pins -e 'switch' 17 27 &
This -s variable specifies the directory gpio-watch will look in for scripts to call, and the 'switch' option uses basic debouncing, necessary for physical buttons.
Step 3: Begin When the PI Boots
Finally, we want the gpio-watch program to run when the pi boots, without any other input. We use the scheduler utility cron for this.
First, run 'crontab -e'.
This will open an editor with the currently scheduled commands loaded. Add this line at the end:
@reboot /home/pi/screen/scripts/start_gpiowatch >/home/pi/logs/cronlog 2>&1
This will also send any errors from to the specified cronlog file, as well as all output from print/println in the processing sketch.
Step 4: Hardware Setup
Most modern monitors have screws holes conforming to the VESA standard for use with wall mounts, and this also provides a useful place to secure our pi. We used a variation of this popular design on Thingiverse, with some modifications.
The VESA holes in the original design are useful if your screen will be attached to its desktop stand; but you'll need to offset the case as shown here if it's using a wall mount. We've also added a side plate to attach our buttons. You may need to adjust the button placement if the monitor is hanging very close to a wall, or if you want additional physical controls.
Be aware when wiring your buttons that the Raspberry Pi GPIO pins expect 3.3 volts of input, and using the 5v source may damage them.
Step 5: Using Processing on the Raspberry Pi
Accessing GPIO Pins
In addition to the start and stop controls, you may want to have elements of your sketch interactive from your viewers or by other sensor elements in the room. GPIO access through Processing uses the io library, and it's usage is very similar to the Arduino's syntax:
import processing.io.*; //Setting up pins GPIO.pinMode(pin1,GPIO.INPUT); GPIO.pinMode(pin2,GPIO.OUTPUT); //Note that Processing can't yet access the pull-up mode the GPIO pins, so you'll need to use external pull-up or pull-down resistors. //Reading and writing to pins if (GPIO.digitalRead(pin1) == GPIO.HIGH) { GPIO.digitalWrite(pin2,GPIO.LOW); }
The full Processing io API can be found here.
Adapting your sketches
The raspberry-pi can be a noticeably different environment if you've written your sketch on a normal machine. There are various issues that affect speed and compatibility.
- Compiling a sketch is a fairly slow process, so run from an exported application when possible.
- On the Pi, various graphics tasks can be handled more efficiently using the GPU memory rather than CPU. Sketches should be run in P2D or P3D mode to utilize OpenGL.
- You may need to change the split of CPU vs GPU memory as well. This can be adjusted by running raspi-config and choosing Memory Split under advanced options.
- You may also need to remove the libles2-mesa package when working with OpenGL:
sudo aptitude remove libgles2-mesa
- If possible, avoid using loadPixels() and updatePixels(). These functions are purely CPU based, and can lag a program for several seconds or cause it to crash.
- strokeWeight() should be used with care, as the triangulation process can cause moderate slowdown. If the weighted lines don't need to constantly change, they should be first drawn into PShape objects. This lets processing only calculate the triangulation once.
Additional troubleshooting information can be found on Processing's Raspberry-pi page.