Off-The-Shelf Hacker: Use the Processing Programming Language to Build an On-Screen Gauge

Last week we looked at using a servo as a gauge. The project had its difficulties: I attributed the crazy operation of the servo to timing issues.
Not being able to leave well enough alone, I looked into using one of my old gauge programs written in the Processing programming language, to replace the servo-based gauge in my steampunk conference badge. The on-screen response is much better, although it would still be fun to have a physical analog-type gauge, sweeping it’s little hand up and down on the front of the badge.
To get an on-screen gauge working, we’ll need to change a few things. What’s cool about many physical computing projects is that if you’re clever with the hardware, lots of behaviors and features are easily altered through software updates.
First, we’ll have to mod the servo code, a bit, for the Arduino Pro Mini. Then, we’ll have to load the Processing language on the Raspberry Pi 3. Finally, there’s also that small matter of the code for the gauge.
I like Processing because it’s easy to use and designed for visual applications. It runs on Linux, on both notebooks and the Raspberry Pi. The development environment and code structure are identical to what we use to program the Arduino Pro Mini, as well. If you can code for an Arduino, you can certainly code in Processing.
Start with the Pro Mini Servo Code
Making the Arduino code from the servo gauge project work with an on-screen gauge was pretty trivial. The changes are highlighted in bold.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
/* HC-SR04 Ping distance sensor] VCC to arduino 5v; GND to arduino GND Echo to Arduino pin 7; Trig to Arduino pin 8 */ #include <Servo.h> Servo myservo; // create servo object to control a servo #define echoPin 8 #define trigPin 7 int val; void setup() { Serial.begin (115200); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); myservo.attach(9); } void loop() { // send a pulse on the trigger pin to initiate measurement digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // the length of the pulse on the echo pin is proportional to the distance long duration = pulseIn(echoPin, HIGH); long distance = (duration / 2) / 29.1 * .3937 ; if (distance >= 200 || distance <= 0) { <strong>// Serial.println("Out of range");</strong> } else { Serial.println(distance); <strong>// Serial.println(" in");</strong> } val = map(distance, 1, 70, 0, 180); // scale it to use it with the servo (value between 0 and 180) myservo.write(val); <strong>// Serial.println(val);</strong> delay(300); } |
The only real changes I made to the Arduino code were to comment out the “out-of-range,” “in” and “val” serial print statements. That information was used to make the output readable for humans. We don’t need to include those things when sending distance values over the serial line to the Raspberry Pi and a Processing program.
I left the code for the servo, in the program, thinking that I might come back and try to tweak it in the future. By simply unplugging the servo from the connector, we don’t waste valuable battery power and it really didn’t hurt anything to leave those lines in the code. I like to use connectors and sockets to add hardware components to my projects. It takes a little extra time to solder things together but makes it much easier to adjust your design.
Here’s a shot of the three-wire servo connector, with a piece of tape over it to prevent shorts.

3 Wire Servo Connector, Insulated With Scotch Tape
After the changes, I compiled and uploaded the code to the Pro Mini, using the usual techniques. I checked the data coming from the serial port by starting the Arduino’s embedded serial console.
Install Processing on the Pi 3
The Processing package has to be installed on the Pi 3 before using the on-screen gauge code. I used wget on the command line to download the 3.3 (ARM) version to the Pi:
1 2 |
pi% cd /home/pi pi% wget http://download.processing.org/processing-3.3-linux-armv6hf.tgz |
Once the file is on the Pi, use tar to unzip it into a directory:
1 |
pi% tar -xzvf processing-3.3-linux-armv6hf.tgz |
Using Processing is pretty straightforward, with one caveat: You’ll have to set the serial port first so that the data coming in over the serial port matches what the program expects, particularly the bit rate.
Lots of times, I’ve issued the cat command to read data streaming in on the serial line (or USB) only to sit there and wonder why there weren’t any values scrolling down the screen. I chose a bit-rate of 115,200. You can use any speed you like, just as long as you set the serial line (using stty) and both the Arduino and Processing gauge code, all to the same value. If the serial line speed or what’s in the code is off, you’ll get a bunch of funny characters, at best or nothing at all, at worst. Not issuing a stty before starting the Processing program, causes the gauge to simply not show a pointer.
1 |
pi% sudo stty -icrnl -F /dev/ttyS0 115200 |
With that done, go into the directory and start the Processing interactive development environment (IDE). It works the same way as the Arduino IDE.
1 2 |
pi% cd processing-3.3 pi% ./processing |

Processing IDE on the Raspberry Pi 3 screen.
Click the File dropdown and then the “New” menu item.
Since I developed the Processing code on my Linux notebook, I had to get the code over to the Pi. The easiest way is to simply scp the code from the notebook to the Pi.
1 |
pi% scp /home/rob/sketchbook/processing/gauge2/gauge2.pde pi@192.168.1.102/home/pi/gauge2.pde |
Readers can copy/paste the text, from this story, into a new Processing file, then save it to the sketchbook.
Here’s the Processing code for the Pi on-screen gauge:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
/** Gauge code for the ARM chip in the Raspberry Pi 3. The angle of each segment (in radians) is controlled by the data streaming in from the serial line. **/ import processing.net.*; PFont font; float x, y; String angle = "0"; // angle in degrees String distance = "0"; // distance in inches float anglef = 0.0; float angle1 = 0.0; float segLength = 110; BufferedReader reader; String line; void setup() { size(350, 300); strokeWeight(2); stroke(255, 160); x = width * 0.5; y = height * 0.8; font = loadFont("LiberationSans-20.vlw"); textFont(font); textAlign(CENTER); reader = createReader("/dev/ttyS0"); } void draw() { background(0); try { line = reader.readLine(); } catch (IOException e) { e.printStackTrace(); line = null; } if (line == null) { // Stop reading because of an error or file is empty noLoop(); } else { // println("distance = ", line); } distance = line; if (angle != null) { anglef = (180-(float(distance))*1.8)*3.1416/180*-1; // scale the distance to an angle for the gauge // println(distance, " ", anglef); //in radians } pushMatrix(); segment(x, y, anglef); popMatrix(); text("Distance (in)", 175, 50); text("0", 35, 250); text("25", 65, 150); text("50", 175, 100); text("75", 285, 150); text("100", 320, 250); noFill(); arc(175, 245, 240, 245, PI, TWO_PI); } void segment(float x, float y, float a) { translate(x, y); rotate(a); line(0, 0, segLength, 0); } |
There are a couple of things of note in the code.
The wired serial port on a Raspberry Pi before version 3, was designated as /dev/ttyAMA0. Raspberry Pi 3’s have reassigned that name to the Bluetooth interface. Instead, use /dev/ttyS0 for the wired serial port on the Pi and everything will work fine. Of course, if you want to pull data in from a USB connected device, use the regular /dev/ttyUSB0, /dev/ttyUSB1, etc. names.
Another interesting thing about the program is that angle measurements are calculated in radians, not degrees. I had to scale the distance, from 0 to 200 inches, to from 0 to 180 degrees, which is a sweep of the hand from the horizontal left (0 degrees) to horizontal right (180-degrees). The 1.8 value scales the measurement from 0-180 to 0-200.
Lastly, the tick values for the reading on the gauge are placed on the gauge face with the “text” lines, near the bottom of the program. I simply selected X and Y values to make it look right. Sure, there was a little trial and error, to get it right.
Save the program to a file name, like “gauge” and then press the “Run” arrow button in the Processing IDE. After a short wait, the gauge should appear on the LCD screen and sweep through an arc, according to the distance detected by the ultrasonic range finder. Make sure the Arduino is powered up and don’t forget about that stty statement, before starting Processing.
The gauge worked very well and was pretty responsive. Holding my hand about a foot in front of the badge showed about 12 inches, on the gauge. With the badge sitting on my desk, the gauge showed about 70 inches, which was the distance up to the ceiling.
What’s Next
The on-screen gauge worked much better than the servo model. The readings were consistent and fast. And, there essentially were no changes to the hardware. That is the beauty of the physical computing stack.
My prototype gadgets are designed to attract attention through outlandish design, a color video screen, sometimes lights and the strong steampunk vibe. Of course, they also serve as test beds for various real-world physical computing ideas that I use in the Off-The-Shelf Hacker column.
Why use boring old white plastic breadboards, on projects that will only live in a workshop, when we can build things that you can wear, touch and demonstrate to people?