Arduino + p5

Over the past two weeks we learned how to use an Arduino to read data from a sensor and then display the data as an output, using light from an LED or sound from a speaker.

This week we will learn how to connect the Arduino to a p5 sketch and use the input to interact with the art in a p5 sketch.

Analog input

First we'll set up the Arduino with a basic analog input sketch to read the values from a potentiometer and/or photocell.

To review, an analog sensor is one that can sense a range of values using varying amounts of voltage. Unlike digital input, which is either on or off, analog values can vary from 0 to 1023.

The code is pretty simple.

void setup() { Serial.begin(9600); } void loop() { int sensorValue = analogRead(A0); Serial.println(sensorValue); delay(10); }

Arduino code can be written in C or C++, which looks similar to JavaScript but has some differences.

void setup() { }

void is equivalent to the function keyword in Javascript. void means the function does not return any type of value, which we'll talk about more when we talk about functions.

setup is like the setup function in p5. It runs once when the program starts to setup things that only need to happen once.

void setup() {
	Serial.begin(9600);
}

Serial.begin starts the communication between the computer and the Arduino over the USB cable.

9600 is the Baud rate which is the rate at which information is transferred across the cable, in this case 9600 bits of information per second. That's a lot of 0 and 1s.

void loop() { } is the Arduino version of function draw() { } in p5.

The code in this function will run over and over as long as the Arduino is connected and running.

Inside the loop we read the sensor value and then print the value to the Serial monitor.

int sensorValue = analogRead(A0);

int is the type of value, in this case an integer or whole number.

sensorValue is a variable to store the current value of the sensor.

analogRead() is a function to read the voltage from the Arduino pin and A0 is the pin to read from.

delay(10);

delay delays the loop by a number of milliseconds. This helps stabilize the sensor reading.

Using delay is okay here because we have a very simple sketch, but anything more complex than this should use a timer instead. delay actually pauses most of the functionality of the microchip, which would be bad if we were doing more than just reading a sensor value.

Serial control app

The Chrome browser cannot directly read values from the USB port on the computer, so we need to run another program to read the value and make it available to Chrome.

The p5.serialcontrol app was developed to make the connection between a p5 sketch and the Arduino.

Download the latest version of the Serial Control app from the releases page.

Download the "darwin-64" zip for Mac and "win32" zip for Windows.

Extract the zip file and leave the app inside the folder. It needs to be in the folder to run correctly. It does not have to be inside your project folder. The Desktop is a good place to put the folder.

The app itself is called p5.serialcontrol and you can double click to open it.

Once you have the app running, select the port where the Arduino is listed or the port that you suspect to be the Arduino (often it is COM3) and click the "Open" button. That's it, just leave the app running in the background.

p5.serialport.js

We also need to add a new library to the HTML page for the p5 sketch, p5.serialport.js.

Download p5.serialport.js here and add a new script tag into index.html.

<script src="p5.min.js"></script> <script src="p5.serialport.js"></script> <script src="sketch.js"></script>

sketch

In the sketch, we need to add some code and some events to connect with the serial port.

First, some global variables.

var serial; var portName = "COM3"; var sensorValue;

serial will be used to create the SerialPort object.

portName needs to match the port name in the p5.serialcontrol app.

sensorValue will store the sensor value.

setup

In setup, we create the p5.SerialPort object and then add a series of events to listen for all of the data coming from the serial port app.

Then open the port matching the port name in the app.

function setup() { createCanvas(640, 360); serial = new p5.SerialPort(); serial.on('connected', serverConnected); serial.on('open', portOpen); serial.on('data', serialEvent); serial.on('error', serialError); serial.on('close', portClose); serial.open(portName); }

Serial events

These events simply log in the console the state of the serial port connection for the purposes of developer testing. If you don't see these log messages in your console when you start the sketch than you may need to adjust the setup.

function serverConnected() { console.log('connected to server.'); } function portOpen() { console.log('the serial port opened.') } function portClose() { console.log('The serial port closed.'); } function serialError() { console.log("error"); }
function serialEvent() { var currentString = serial.readLine(); // read the incoming string trim(currentString); // remove any trailing whitespace if (!currentString) { return; // if the string is empty, do no more } sensorValue = currentString; // save it for the draw method }

The serialEvent function is doing most of the work in reading the sensor value and storing it in the sensorValue variable to use in the sketch.

draw

This is a simple sketch that uses the sensor value to create a sunset.

The sensorValue is mapped to both the background color of the sketch and the position of the sun in the sky.

function draw() { var c = map(sensorValue, 0, 1023, 0, 180); // sky background(c, c, c + 85); // sun var y = map(sensorValue, 0, 1023, height, 0); fill('gold'); noStroke(); ellipse(width/2, y, 100); // ground fill(c, c + 75, c); rect(0, height * 0.75, width, height * 0.25); }