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

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");
}