Processing and Arduino

Processing is an open-source IDE with a Java-based programming language that is aimed at lowering the learning threshold for interactive graphics creation. It can be used for teaching programming, making prototypes, creating art experiments or just generating crazy visual stuff in general. The community is very active and there are tons of useful contributed libraries. Wiring and the Arduino IDE are spin-offs from Processing and there are many cool things happening in the JavaScript version of Processing, p5.js (more about this in an upcoming post).

In this post I will connect a Processing sketch with an Arduino for the purpose of visualizing the input and output pins of the hardware board with graphics in Processing.

Getting to know Processing

I started out with a book by the Processing project founders:

processingboook
Make: Getting Started with Processing

It provides a very easy-to-get-started introduction to the subject. To learn more, the Processing IDE has a set of examples included that can be browsed, launched and modified from within the IDE. I really like this approach as it kickstarts you into learning by doing.

The Processing IDE is very light-weight and can be downloaded for Mac, Windows and Linux from processing.org.

A typical Processing sketch has a setup() method where you initialize your program, and a draw() method that is called repeatedly when the GUI is rendered and updated. A minimal Processing sketch that acts on mouse input can look like this:


void setup() {
size(400, 300);
rectMode(CENTER);
}
void draw() {
background(220);
fill(200,200,0);
rect(mouseX, height/2, mouseY/2+10, mouseY/2+10);
fill(0,200,200);
int inverseX = width-mouseX;
int inverseY = height-mouseY;
ellipse(inverseX, height/2, (inverseY/2)+10, (inverseY/2)+10);
}

This example (adapted from a built-in example in the IDE), draws a rectangle and a circle. The rectangle follows the mouse x-position and the rectangle moves in the other direction. The size of the objects are determined by the mouse y-position.

Working with 3D-objects is also straightforward. This sketch rotates a box and a sphere when the mouse is moved within the window:


void setup() {
size(600, 300, P3D);
}
void draw() {
background(100);
lights();
stroke(10);
float rotationX = map(mouseX,0,width,0,2*PI);
float rotationY = map(mouseY,0,height,0,2*PI);
// Draw a rotated box
fill(150,40,40);
pushMatrix();
translate(200, height/2, 0);
rotateY(rotationX);
rotateX(rotationY);
box(130);
popMatrix();
// Draw a rotated sphere
fill(40,150,40);
pushMatrix();
translate(500, height/2, -200);
rotateY(-rotationX);
rotateX(-rotationY);
sphere(150);
popMatrix();
}

view raw

Simple3D.pde

hosted with ❤ by GitHub

processing_3d.png

Communicating with an Arduino UNO

A simple solution for interaction between a Processing sketch and the I/O pins of an Ardunio board is to use serial communication with the Firmata protocol over USB. By using the StandardFirmata sketch on the Arduino and the Processing Arduino Firmata library in Processing, it is possible to read and write pins via the USB connection from the Processing sketch.

You can e.g. read Arduino GPIO pin voltages (=binary or analog data from sensors) and visualize them in the Processing GUI or create an input control in Processing that sends data to a pin on the Arduino for controlling an actuator.

Reading analog input pins

To demonstrate reading analog input pins on the Arduino, I will connect potentiometers to some Arduino analog input pins and then read and visualize these values from a Processing sketch.

For the Arduino board I use three 500KΩ potentiometers for changing the input voltages to the input pins and one 4.7KΩ resistor to limit the current between 5V and ground. Here is a Fritzing drawing of my setup:

Arduino_analogIn_pots_bb.jpg

The Arduino runs the StandardFirmata sketch (available from File->Examples->Firmata in the Arduino IDE).

The main sketch in Processing contains a setup()- and a draw() method:


int maxBarHeight = 600;
int barWidth = 400;
//IArduinoIntegration arduino = new ArduinoFakeIntegration();
IArduinoIntegration arduino = new ArduinoIntegration(this);
// A list with bars to draw
// Specify the matching Arduino analog pin number and a color for the bar that should represent the input voltage
BarSpec[] barSpecs = { new BarSpec(0, color(150,150,20)),
new BarSpec(1, color(20,100,20)),
new BarSpec(2, color(20,20,100))
};
void setup() {
size(1200,600);
for (BarSpec barSpec : barSpecs) {
arduino.setupAnalogPinAsInput(barSpec.pinNumber);
}
}
void draw() {
background(0);
int numPinsDrawn = 0;
for (BarSpec barSpec : barSpecs) {
float v = arduino.getVoltageFromPin(barSpec.pinNumber);
// Draw the bar
int barXPos = barWidth*numPinsDrawn;
float barHeight = map(v,0,5.0,0,maxBarHeight);
fill(barSpec.barColor);
rect(barXPos,height-barHeight,barWidth,barHeight);
// Draw the text within the bar
fill(200,200,200);
textSize(40);
text(round(v*100)/100.0 + "[V]",barXPos,height-80);
text("Pin A" + barSpec.pinNumber,barXPos,height-40);
numPinsDrawn++;
}
delay(200);
}

The program creates a list of objects that defines what pins should be used and what color to draw the corresponding bars with. In the setup() method the window size of the Processing GUI is set and the Arduino pins are set to input mode. In the draw() method, the voltages (0-5V) for each defined pin are fetched and this is scaled into the height of a filled rectangles on the screen. The voltage value and the pin name is drawn at the bottom of each bar.

In the main sketch I have used a helper class ArduinoIntegration that hides the details of the Arduino communication. The ArduinoIntegration class uses the Arduino Firmata Processing library to communicate via the Firmata protocol with the Arduino. The values from the analog pins are integers between 0 and 1024 which are then scaled to 0-5 to represent the actual voltages.

Note that the arduinoUSBDeviceName has to be set to the correct device name in your setup! On a Mac or Linux OS, use ls /dev before and after plugging in the USB cable from the Arduino to locate the device name to use.


import processing.core.PApplet;
import processing.serial.*;
import cc.arduino.*;
public class ArduinoIntegration implements IArduinoIntegration {
// Change this so that it matches the usb device connected to the Arduino
String arduinoUSBDeviceName = "/dev/tty.usbmodem1421";
Arduino arduino;
ArduinoIntegration(PApplet applet) {
try {
arduino = new Arduino(applet, arduinoUSBDeviceName , 57600);
}
catch(Exception e) {
println(e.getMessage());
}
}
public float getVoltageFromPin(int pinNumber) {
if (arduino == null)
return 0;
float pinValue = arduino.analogRead(pinNumber);
float pinValueInVolts = map(pinValue,0,1024,0,5);
return pinValueInVolts;
}
public void setupAnalogPinAsInput(int pinNumber) {
if (arduino != null) {
arduino.pinMode(pinNumber, Arduino.INPUT);
}
}
}

The helper class implements an interface IArduinoIntegration and the main sketch uses this interface instead of the concrete class. This way it is possible to test the Processing sketch without a connected Arduino and instead use a fake ArduinoIntegration that e.g. just returns random voltages.

The Processing sketch in action looks like this:

arduinoinbars

When turning the potentiometers that are connected to the Arduino board, the bars and the voltage values are updated on the screen in realtime. Coincidentally, I happened to have just the right knob colors for my potentiometers :-).

threepotentiometers.jpg

Writing digital output pins

To demonstrate writing digital output pins on the Arduino, I will connect four LEDs to the digital outputs D8, D9, D10 and D11 on the Arduino and create a GUI with state switches in Processing that turns the LEDs on and off.

There are lots of great contributed libraries for Processing and there are several that provide nice looking and easy to use controls for your sketch. For my purpose, the GImageToggleButton in the G4P library by Peter Lager does the job well.


import g4p_controls.*;
//IArduinoIntegration arduino = new ArduinoFakeIntegration();
IArduinoIntegration arduino = new ArduinoIntegration(this);
Digital_GPIO_Pin[] pins = { new Digital_GPIO_Pin("D8",8,0),
new Digital_GPIO_Pin("D9",9,1),
new Digital_GPIO_Pin("D10",10,0),
new Digital_GPIO_Pin("D11",11,0)
};
public void setup() {
size(400, 200);
int buttonArea = width/pins.length;
int numDrawnButtons = 0;
for (Digital_GPIO_Pin pin : pins ) {
pin.button = new GImageToggleButton(this, numDrawnButtons*buttonArea+10, 10);
pin.button.setState(pin.state);
pin.label = new GLabel(this, numDrawnButtons*buttonArea+10, 10 + 40, 50, 50);
arduino.setupDigitalPinAsOutput(pin.pinNumber);
arduino.setState(pin.pinNumber,pin.state);
numDrawnButtons++;
}
}
public void draw() {
background(150, 200, 150);
for (Digital_GPIO_Pin pin : pins ) {
pin.label.setText(pin.name + " : " + pin.getStateAsText());
arduino.setState(pin.pinNumber,pin.state);
}
}
// Event handler for image toggle buttons
public void handleToggleButtonEvents(GImageToggleButton button, GEvent event) {
for (Digital_GPIO_Pin pin : pins ) {
if (pin.button == button) {
pin.state = button.getState();
break;
}
}
}

This sketch creates a list of pin objects with pin number, name and initial state. The pin objects have a toggle button and a label attached that are drawn on the screen (as the controls are connected to this, which is the PApplet Processing window object). When the toggle button is pressed, it changes state and an event handler is called that updates the pin object. In the draw() method, the pin objects are iterated over and the current state is sent to the Arduino via a helper class:


import processing.core.PApplet;
import processing.serial.*;
import cc.arduino.*;
public class ArduinoIntegration implements IArduinoIntegration {
// Change this so that it matches the usb device connected to the Arduino
String arduinoUSBDeviceName = "/dev/tty.usbmodem1421";
Arduino arduino;
ArduinoIntegration(PApplet applet) {
try {
arduino = new Arduino(applet, arduinoUSBDeviceName , 57600);
}
catch(Exception e) {
println(e.getMessage());
}
}
public void setupDigitalPinAsOutput(int pinNumber) {
if (arduino != null) {
arduino.pinMode(pinNumber, Arduino.OUTPUT);
}
}
public void setState(int pinNumber, int state) {
if (arduino == null)
return;
arduino.digitalWrite(pinNumber,state);
}
}

Running the program generates this GUI:

Processing_DigitalOutput.png

and with a connected Arduino you can turn pins D8-D11 on/off.

Conclusions

Getting to know Processing has been a pleasant experience. The simplicity of the IDE is a great strength for the beginner and the built-in and contributed libraries provide fantastic features that are bound to triggers creative ideas. I really like the concept of built-in examples and an integrated library downloader. With the possibility to connect physical devices like an Arduino, the Processing universe gets even bigger. So, let’s go innovating with Processing and have some fun!

The code from this blog post can be downloaded from GitHub: https://github.com/LarsBergqvist/processing_playground

 

Leave a comment