Posts Tagged “tangible”

My projects for the semester have been archived on my personal site:

http://sybak.com/

For each of the projects mentioned so far:

… optimized versions have been uploaded along with their source code. To see their source code, simply load them, right-click on the Flash player area, and choose “View source”.

That’s it for this semester; I’m beat. Tune in next semester for more adventures (though not necessarily at the iSchool!).

We have completed work on the embodied version of Battleship. It was a lot of Adobe Flex, felt-covered foam, and sleepless nights.

We demonstrated the novel interfaces we created at not one, but two Open House events held at the School of Information. Feedback was generally positive and a good time was had by all.

The creators of Physical Battleship demonstrating the embodied input required for their exertion interface

The creators of Physical Battleship demonstrating the embodied input required for their exertion interface

.

.

.

.

.

.

.

.

.

.

.

These events garnered significant interest from the press. Here is coverage from two local news outlets:

San Francisco Chronicle

KTVU Channel 2

The Chronicle article was picked up by ACM TechNews.

In addition, we have prepared a final paper in the ACM SIGCHI Extended Abstract format. It is accessible here.

The abstract of the paper is as follows:

The field of exertion interfaces is a new one, full of undiscovered practices and new paradigms of thinking about interaction. We present an instance of an exertion interface that not only accepts tangible input, but also provides an active tangible output that influences the user‟s ability to perform the tangible input. Our application, a full-body implementation of the strategy game Battleship, attempts to demonstrate the effectiveness of this approach. We examine the cycle of influence between players performing embodied input/output and note that it differentiates our game from existing exertion interfaces.

Now that the project is complete, the felt wall and platform are sitting dormant in my lab. Who knows if they will be put to use again?

After some turbulence in the Tangible User Interfaces course, we have a new group, a new project, and a new proposal presentation to kick things off.

This time, we’re planning to recreate the classic strategy game of Battleship as an ‘exertion interface‘. Inspired by Breakout for Two, we want to make Battleship a lot more physical, a lot more intense, and create twists using tangible aspects. Our ultimate goal is a completely embodied experience with the other Battleship player(s?!).

Check out our presentation here:
http://docs.google.com/Presentation?id=dgzj35md_39pnv6fzfz

Description

Our goal in this lab was to create a “musical instrument” utilizing the input/output devices we learned about this semester. Synthesizing at least four input devices, we created a networked “instrument” that is played with two people situated at different (possibly remote) stations.

The input devices at each station are one piezo (a “tapping” motion is used as input) and one potentiometer. The potentiometer controls the desired tone of the remote piezo, and tapping the local piezo sends a signal to activate the remote piezo. Thus, by tapping the local piezo and adjusting the potentiometer, a person at one station can send his ‘tone’ to the person at the other station and vice-versa. (His ‘tone’ will also be played on his local output piezo, so both parties are always aware of their own actions.)

We imagine a ‘matching’ game (i.e. in the vein of the game of Simon) could be played where each person tries to match the tone of the other.

Components Used

  • 2 Arduino microcontroller circuits
  • 4 piezo buzzers (2 as input, 2 as output)
  • 2 potentiometers as input
  • Insulated copper wire
  • Various flavors of resistors to keep piezo noise low

Arduino Code

In an earlier attempt at providing for more interesting output options, we wrote code to trigger a servo’s movement whenever a piezo was tapped. This added noise (by the servos) which had undesirable effects. We were hoping to use the servos to hit a bell or chimes, but were unable to find any materials to serve that purpose. Thus, we eliminated the servos from our system altogether, but kept the code here for reference.


/** Unused Servo Code ---
#include 

/** Output - Servo 
#define SERVO_PIN 11  // Control pin for servo motor
#define MIN_ANGLE 0  // Minimum servo position
#define MAX_ANGLE 150  // Maximum servo position

// Define states for the servo state machine
#define PULSE_ON       0
#define WAIT_PULSE_ON  1
#define PULSE_OFF      2
#define WAIT_PULSE_OFF 3

Servo servo;
int state = 0;    // For the state machine
long nextMillis = 0;    // Timing value
int angle = 0;    // Amount to angle the servo
int servCount = 0;  // Servo trigger value

/** Output - Piezzo **/
#define SPEAK_PIN 9     // Control pin for piezzo speaker
int piezCount = 0;      // Piezzo trigger value
int toneValue = 0;      // Pot value from serial input

char chIn;    // Character read in from serial port

/** Input - Piezzo **/
#define TAP_PIN 0
#define TAP_THRESHOLD 60
int inTapVal = 0;

/** Input - Potentiometer **/
#define POT_PIN 1
int inPotVal = 0;

void setup() {
  // Set output pins
  //pinMode(SERVO_PIN, OUTPUT);
  pinMode(SPEAK_PIN, OUTPUT);
  //servo.attach(SERVO_PIN);  // Activate servo
  //angle = MIN_ANGLE;      // Set the motor position value to the minimum
  Serial.begin(9600);       // Start serial port
}
 
void loop() {
  // If there's input waiting on the serial port, read all of it
  if (Serial.available()) {
    while ((chIn = Serial.read()) != -1) {
      switch(chIn) {
        case '0'...'9':
          toneValue = toneValue * 10 + chIn - '0';
          piezCount = 1; // Get the piezzo ready to buzz once
          break;
        case 's':
          //servCount++;
          break;
      }
    }
  }
  
  
  // Any input from the two input devices on the board?
  inTapVal = analogRead(TAP_PIN);      // Read value from Piezzo input
  inPotVal = analogRead(POT_PIN);      // Read value from pot

  if (inTapVal >= TAP_THRESHOLD) {     // If knock detected
     //servCount++;
     Serial.println(inPotVal); // Triggers the message over the network
     
     // Also fire our local piezo
     piezCount = 1;
     toneValue = inPotVal;
  }

  /** Output to Piezo **/
  digitalWrite(SPEAK_PIN, LOW);    // Reset speaker to OFF
 
  if (piezCount > 0 && toneValue > 200) {   
    for(int i = 0; i  0) {
    switch (state) {
      case PULSE_ON:
  angle = MAX_ANGLE;  // send servo to max position
  nextMillis = millis() + 300;  // wait 300 ms
  state = WAIT_PULSE_ON;
  break;
      case WAIT_PULSE_ON:
        if (millis() > nextMillis) {
          state = PULSE_OFF;  // time is up
  }
  break;
      case PULSE_OFF:
        angle = MIN_ANGLE;  // send servo to min position
        nextMillis = millis() + 500;  // wait half second between two rings
        state = WAIT_PULSE_OFF;
  break;
      case WAIT_PULSE_OFF:
        if (millis() > nextMillis) {
    state = PULSE_ON;  // time is up
    servCount--;  // one ring is done
  }
  break;
    }
  }

  servo.write(angle);
  Servo::refresh();
  */
}

Processing Code

The following is the network (socket programming) code that allows the proper messages to be sent between the two stations. The stations act as both client and server to each other (a peer-to-peer setup) and send messages whenever they receive input from their Arduino boards (i.e. through the local serial port).


import processing.serial.*;
import processing.net.*;

// Customize these values for the network/local ports
String COMPORT = "COM11"; // Local serial port where Arduino is
String REMOTE_IP = "136.152.144.62"; // Remote IP address of peer client/server
int NET_PORT = 5204;

// Character constants
int CR = 13;  // ASCII return   == 13
int LF = 10;  // ASCII linefeed == 10

String netBuf = "";

Serial arduinoPort;  // This is the local Arduino board
Client remotePeer;   // This is the peer we're talking to
Server myServer;     // This is us

void setup() {
  myServer = new Server(this, NET_PORT);
  delay(5000); // Make sure servers on both sides are running first
  arduinoPort = new Serial(this, COMPORT, 9600);
  remotePeer = new Client(this, REMOTE_IP, NET_PORT);
}

/* Infinite loop - don't use */
void draw() {}

/* Called whenever data arrives over the network from our peer */
void clientEvent(Client peer) {
  String sDataIn = peer.readString();
  if (sDataIn == null) { return; }
  println("Read string from client: " + sDataIn);
  arduinoPort.write(sDataIn.trim()); // Push it to Arduino
}

/* Called whenever data arrives from the Arduino serial port */
void serialEvent(Serial p) {
  String temp = arduinoPort.readString();
  netBuf += temp;  
  
  // Don't do anything until we read up to a newline
  String[] m = match(netBuf, "n");
  if (m == null) { return; }
  
  println("Received from Arduino: " + netBuf);
  
  // Hit up the clients connected to us
  myServer.write(netBuf);
  netBuf = "";
}

/* Called when a new client connects to our server */
void serverEvent(Server someServer, Client someClient) {
  println("New client successfully connected: " + someClient.ip());
  someServer.write("600"); // Confirm that connection works!
}

Images

Pictures of the dueling piezos setup:

Video

A video of the dueling piezos in action can be found at the official course website:
http://courses.ischool.berkeley.edu/i290-4/f08/?q=node/324

Our final project for the Tangible User Interfaces course has finally been determined. We will continue developing and refining the concept for the NiPix wall.

See our proposal here.