December 15, 2009

Final Project Update - Alec Rippberger

For my final project I will be creating a link between the physical and digital realms. Interaction with a physical representation of a tree is linked with an animation of a tree projected onto a screen.

With online virtual communities replacing physical interaction, this installation is meant to make the viewer contemplate our interactions in life. What is more real, the physical or digital representation? Which is more meaningful or beautiful?


In the final presentation of this digital tree the more a viewer shakes the physical tree the more leaves will fall off the digital tree.

I used "serproxy" to act as an intermediate between Flash and the Arduino because the Arduino talks to the computer through the serial ports while Flash will only listen to a type of internet protocol. Serproxy acts as a translator allowing Flash and the Arduino to communicate. Serproxy can be downloaded from the Arduino page HERE. Serproxy was configured as so:

# Config file for serproxy
# See serproxy's README file for documentation

# Transform newlines coming from the serial port into nils
# true (e.g. if using Flash) or false

# Comm ports used



# Idle time out in seconds

# Port 1 settings (ttyS0)

# Port 2 settings (ttyS1)

# Port 3 settings (ttyS2)

# Port 4 settings (ttyS3)

To allow the Arduino to trigger the flash animation I used a Flash class called "as3Glue" which can be found HERE. THis flash class allows flash to check inputs and send output to the Arduino board.

I used "Firmata" to allow as3Glue to fluidly communicate with my Arduino. Firmata can be found HERE. I used the standard Firmata code with slight modification:

Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

See file LICENSE.txt for further informations on licensing terms.

formatted using the GNU C formatting and indenting

* TODO: add Servo support using setPinModeCallback(pin, SERVO);
* TODO: use Program Control to load stored profiles from EEPROM



/* analog inputs */
int analogInputsToReport = 0; // bitwise array to store pin reporting
int analogPin = 0; // counter for reading analog pins

/* digital pins */
byte reportPINs[TOTAL_PORTS]; // PIN == input port
byte previousPINs[TOTAL_PORTS]; // PIN == input port
byte pinStatus[TOTAL_DIGITAL_PINS]; // store pin status, default OUTPUT
byte portStatus[TOTAL_PORTS];

/* timer variables */
unsigned long currentMillis; // store the current value from millis()
unsigned long nextExecuteMillis; // for comparison with currentMillis
int samplingInterval = 19; // how often to run the main loop (in ms)

Servo servos[2]; // the servo library can control servos on pins 9 and 10 only


void outputPort(byte portNumber, byte portValue)
portValue = portValue &~ portStatus[portNumber];
if(previousPINs[portNumber] != portValue) {
Firmata.sendDigitalPort(portNumber, portValue);
previousPINs[portNumber] = portValue;
Firmata.sendDigitalPort(portNumber, portValue);

/* -----------------------------------------------------------------------------
* check all the active digital inputs for change of state, then add any events
* to the Serial output queue using Serial.print() */
void checkDigitalInputs(void)
byte i, tmp;
for(i=0; i < TOTAL_PORTS; i++) {
if(reportPINs[i]) {
switch(i) {
case 0:
outputPort(0, PIND &~ B00000011); // ignore Rx/Tx 0/1
case 1:
outputPort(1, PINB);
outputPort(ANALOG_PORT, PINC);

// -----------------------------------------------------------------------------
/* sets the pin mode to the correct state and sets the relevant bits in the
* two bit-arrays that track Digital I/O and PWM status
void setPinModeCallback(byte pin, int mode) {
byte port = 0;
byte offset = 0;

// TODO: abstract for different boards
if (pin < 8) {
port = 0;
offset = 0;
} else if (pin < 14) {
port = 1;
offset = 8;
} else if (pin < 22) {
port = 2;
offset = 14;

if(pin > 1) { // ignore RxTx (pins 0 and 1)
if(pin > 13)
reportAnalogCallback(pin - 14, mode == ANALOG ? 1 : 0); // turn on/off reporting
switch(mode) {
case ANALOG:
digitalWrite(pin, LOW); // disable internal pull-ups and fall thru to 'case INPUT:'
case INPUT:
pinStatus[pin] = mode;
pinMode(pin, INPUT);
portStatus[port] = portStatus[port] &~ (1 << (pin - offset));
case OUTPUT:
digitalWrite(pin, LOW); // disable PWM and fall thru to 'case PWM:'
case PWM:
pinStatus[pin] = mode;
pinMode(pin, OUTPUT);
portStatus[port] = portStatus[port] | (1 << (pin - offset));
case SERVO:
if((pin == 9 || pin == 10))
pinStatus[pin] = mode;
Firmata.sendString("Servo only on pins 9 and 10");
case I2C:
pinStatus[pin] = mode;
Firmata.sendString("I2C mode not yet supported");
Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
// TODO: save status to EEPROM here, if changed

void analogWriteCallback(byte pin, int value)
switch(pinStatus[pin]) {
case SERVO:
if(pin == 9) servos[0].write(value);
if(pin == 10) servos[1].write(value);
case PWM:
analogWrite(pin, value);

void digitalWriteCallback(byte port, int value)
switch(port) {
case 0: // pins 2-7 (don't change Rx/Tx, pins 0 and 1)
// 0xFF03 == B1111111100000011 0x03 == B00000011
PORTD = (value &~ 0xFF03) | (PORTD & 0x03);
case 1: // pins 8-13 (14,15 are disabled for the crystal)
PORTB = (byte)value;
case 2: // analog pins used as digital
byte pin;
byte pinModeMask;
for(pin=0; pin<8; pin++)
if(pinStatus[pin] == OUTPUT)
pinModeMask += 1 << pin;
PORTC = (byte)value & pinModeMask;

// -----------------------------------------------------------------------------
/* sets bits in a bit array (int) to toggle the reporting of the analogIns
//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
void reportAnalogCallback(byte pin, int value)
if(value == 0) {
analogInputsToReport = analogInputsToReport &~ (1 << pin);
else { // everything but 0 enables reporting of that pin
analogInputsToReport = analogInputsToReport | (1 << pin);
setPinModeCallback(pin, ANALOG);
// TODO: save status to EEPROM here, if changed

void reportDigitalCallback(byte port, int value)
reportPINs[port] = (byte)value;
if(port == ANALOG_PORT) // turn off analog reporting when used as digital
analogInputsToReport = 0;

* SYSEX-BASED commands

void sysexCallback(byte command, byte argc, byte *argv)
switch(command) {
if(argc > 4) {
// these vars are here for clarity, they'll optimized away by the compiler
byte pin = argv[0] - 9; // servos are pins 9 and 10, so offset for array
int minPulse = argv[1] + (argv[2] << 7);
int maxPulse = argv[3] + (argv[4] << 7);
servos[pin].attach(argv[0], minPulse, maxPulse);
// TODO does the Servo have to be detach()ed before reconfiguring?
setPinModeCallback(pin, SERVO);
if (argc > 1)
samplingInterval = argv[0] + (argv[1] << 7);
Firmata.sendString("Not enough data");

void setup()
byte i;

Firmata.setFirmwareVersion(2, 1);

Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
Firmata.attach(SET_PIN_MODE, setPinModeCallback);
Firmata.attach(START_SYSEX, sysexCallback);

portStatus[0] = B00000011; // ignore Tx/RX pins
portStatus[1] = B11000000; // ignore 14/15 pins
portStatus[2] = B00000000;

for(i=0; i setPinModeCallback(i,OUTPUT);
// set all outputs to 0 to make sure internal pull-up resistors are off
PORTB = 0; // pins 8-15
PORTC = 0; // analog port
PORTD = 0; // pins 0-7

// TODO rethink the init, perhaps it should report analog on default
for(i=0; i reportPINs[i] = false;
// TODO: load state from EEPROM here

/* send digital inputs here, if enabled, to set the initial state on the
* host computer, since once in the loop(), this firmware will only send
* digital data on change. */
if(reportPINs[0]) outputPort(0, PIND &~ B00000011); // ignore Rx/Tx 0/1
if(reportPINs[1]) outputPort(1, PINB);
if(reportPINs[ANALOG_PORT]) outputPort(ANALOG_PORT, PINC);


* LOOP()
void loop()
/* DIGITALREAD - as fast as possible, check for changes and output them to the
* FTDI buffer using Serial.print() */
currentMillis = millis();
if(currentMillis > nextExecuteMillis) {
nextExecuteMillis = currentMillis + samplingInterval;
/* SERIALREAD - uses a 128 byte circular buffer, so handle
* all serialReads at once, i.e. empty the buffer */
/* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
* 60 bytes. use a timer to sending an event character every 4 ms to
* trigger the buffer to dump. */

/* ANALOGREAD - right after the event character, do all of the
* analogReads(). These only need to be done every 4ms. */
for(analogPin=0;analogPin if( analogInputsToReport & (1 << analogPin) ) {
Firmata.sendAnalog(analogPin, analogRead(analogPin));

I will post the code of the Flash code and more documentation once all bugs have been worked out.

December 9, 2009

jane's One-on-One: prototype I

This project is an interactive wearable belt. The content relates to my and other women's experiences of permission to touch a pregnant stomach strangers give themselves. It will have two modes of operation: non-touch and touch. In non-touch mode red "warning" lights will flash. In touch mode, a series of interactions will be possible. Extracting the container with the fetus embryo model, will trigger a tilt sensor causing either a muscle wire to produce a small movement or a blue LED to glow in the fetus model. Touching the cast rubber will cause different actions depending on how touched. Still deciding on what these should be.

One-on-One Sketch-crop8xAdjs.jpg

December 8, 2009

Final Project Concept

Interactive Concept.jpg

I have become very interested in Processing over the past couple of weeks and have made a slight shift in the direction of the final project. As discussed last week, I am interested in a more "code intensive" project than previously.

The project will use several capacitive sensors to communicate with Processing via the Arduino. The serial inputs will create contained lighting condition on a surface. In addition the inputs will manipulate the duration, tempo, and frequency of an audio signal to create a hybrid sensory experience.

Final Project Progress

For my final project i plan on creating an interactive painting utilizing diffused LED's and light sensors. I am currently trying to work on the programming of the LED's so that I can get multiple LED's to turn on and off based on the light sensor. I have several options for the painting in my head but i have yet to decide which version i will decide to use. I am thinking of either a cityscape/landscape that will become lit up as the viewer blocks the light source or possibly an eclipse in which the moon will block the light sensor embedded in the sun. These options will depend on how far i can get with the programming.