At the core of an interactive exhibit is the interaction: the person who encounters the exhibit does something, and the exhibit responds. The person does something else, the exhibit responds again, and so on. Rather than simply viewing a static exhibit (or worse, reading a plaque), people can interact with the exhibit, have a sort of a conversation with it. We will be using the Processing programming language to script this interaction.
Reading and Coding
- If it has been a while since you’ve done any programming on your laptop, you might want to reread “Getting Started. Welcome to Processing“
- Reread “Processing Overview“
- Now try running the following three programs and see if you can figure out how they work. Try modifying the code and rerunning it to see if your assumptions are correct.
In Class
I am going to work through an extended example in class that uses an Arduino with physical inputs and outputs, a serial connection to the laptop, and a Processing sketch that scripts an interaction between the user and the exhibit. If you are already comfortable programming in Processing (or the language of your choice) feel free to skip class to work on your project. If not, bring your laptop, your Arduino and accessories.
Postmortem
The in-class demonstration went smoothly for a while, then we ran into problems at the end with the serial connection between Arduino and Processing. These things happen: doing real programming means spending a fair amount of time debugging. I cleaned up the in-class example, and provide the revised version below, with explanatory comments.
The first step is to connect a normally off pushbutton switch to digital pin 4 on the Arduino. We then compile and upload the following sketch to the Arduino. If it is working correctly, the built-in LED on pin 13 should light up whenever we press the button, and turn off when we stop pressing it. We should also open the serial monitor and confirm that we see a series of 0s until the button is pressed. As long as we are pressing the button we should see a series of 1s. If everything seems to be working correctly, we can make a note of which USB port the Arduino is connected to, then close the Arduino software. We have to leave the Arduino plugged in to our computer, of course.
/* Arduino program Normally off pushbutton switch connected to pin 4 Modified from DigitalReadSerial example This example code is in the public domain. */ void setup() { Serial.begin(9600); pinMode(4, INPUT); pinMode(13, OUTPUT); } void loop() { // read the value of the switch int sensorValue = digitalRead(4); // write the value of the switch to the serial port Serial.println(sensorValue); if (sensorValue == 1) { // if switch is pressed, turn on LED on pin 13 digitalWrite(13, HIGH); } else { // switch is not pressed digitalWrite(13, LOW); } delay(50); }
So we now have a program on the Arduino that continually sends the state of our pushbutton switch (i.e., pushed or not) over the serial port. Now we need to devise a Processing program that will listen to the serial port and take appropriate action when the button is pressed.
We started by sketching out what we want our program to do using comment statements in Processing.
// My Exhibit Program // Tell Processing we are using serial ports // Set up a serial port connection to the Arduino // Do this forever... // If the user hasn't pushed the button, prompt him or her // If the user has pushed the button, respond
The next step was to create separate routines to handle the prompting and responding. Rather than actually worry about designing the exhibit at this point, we just need to let ourselves know that the routines are being called when we expect them to be. The following program alternates between our user-prompting routine and our response routine forever.
// My Exhibit Program // Tell Processing we are using serial ports // Set up a serial port connection to the Arduino void setup() { } // Do this forever... void draw() { // If the user hasn't pushed the button, prompt him or her userPrompt(); // If the user has pushed the button, respond responseRoutine(); } // responds to user void responseRoutine() { println("Inside responseRoutine"); } // prompts the user to press a button on the Arduino void userPrompt() { println("Inside userPrompt"); }
Next we add the code that sets up the serial port, reads the last character sent, and decides what to do next. Unlike the version we developed in class, this one should work :) It is still pretty minimal. The user prompts and response routines need to be developed, and the Arduino would probably have a richer set of inputs for a working exhibit (including, perhaps, some analog sensors). The trick is to get something very simple working before you add embellishments.
// My Exhibit // Tell Processing we are using serial ports import processing.serial.*; Serial myPort; // Set up a serial port connection to the Arduino void setup() { // println(Serial.list()); myPort = new Serial(this, Serial.list()[0], 9600); } // Do this forever... void draw() { while (myPort.available() > 0) { char lastIn = myPort.lastChar(); // If the user hasn't pushed the button, prompt him or her if (lastIn == '0') { userPrompt(); } // If the user has pushed the button, respond if (lastIn == '1') { responseRoutine(); } } } // responds to user void responseRoutine() { println("Inside responseRoutine"); } // prompts the user to press a button on the Arduino void userPrompt() { println("Inside userPrompt"); }