Pongbox

For week 2 of Understanding Networks, a newly created class that keeps shifting between abstraction and application, leaving me sadly uncertain as to whether I understand what Tom’s talking about at any given moment, our terrifying assignment was as follows:

Socket exercise: communicating in realtime. I will give you a game platform and the protocols to log in and communicate with it. Make a client to log in and play. Work in Processing, Flash, Arduino or whatever environment is comfortable to you. You will not play with your own client, but you’ll show someone else how to use it.

As Tom apprised us of this mission, I felt a panicky fit of rage welling up, and in my head I started to whine. This is such a pure ITP experience: spend two and a half hours trying to follow a discussion about something totally vague, and in the last two minutes get an assignment that’s way over my head, with absolutely no instruction in how to do it. Fucking PhysComp all over again.

I stomped out of the room and headed to my next activity alternately fuming and telling myself, Shut up, shut up, shut up! Stop bitching about how you can’t do this, and instead think about what you’re going to do! Because at midnight on the night before the thing is due, you know you’re going to bite the bullet and start doing something. How about starting early, for once, instead of wasting time being indignant?

Yeah, this is how things are in my head these days.

So I thought about it, and I decided not to overthink it. I wanted to avoid fucking with Processing (an ongoing aversion, apparently developed sometime in the first semester, although I enjoyed ICM), so I would just make a simple device that would have an obvious physical mapping: an accelerometer-based controller that would move the Ping-Pong paddle right when you tilted your hand to the right, left when you tilted your hand to the left, up and down blah blah, with a switch to restart the game or whatever. I thought I’d make it as small and light as possible, wearable on the back of the hand. Très elegant.

Well. Once I’d figured that out, I panicked less. So much less that I still didn’t feel a need to start the project until the afternoon before it was due. Curses! Foiled again!

I gathered all my electronics crap on Wednesday afternoon and took it to school, which I’d heard was a place where some people do their homework. On the way, I picked up a peppy red accelerometer at the NYU computer store. I set up in one of the least comfortable and work-friendly parts of the lounge and started casually wiring stuff together. I have conductive thread and enjoyed sewing the circuit for the drawing glove last fall, but I also wanted to follow the very wise advice that Peter Raymond had given in Wearables this spring—which is the same advice a lot of people give, but for some reason the way he said it sunk in—and focus on knocking together a prototype as quickly and dirtily as possible, so that I could get a sense of whether it worked before I started to obsess about making it look nice.

So I took the LilyPad and USB-mini cable I’d bought last spring out of their plastic baggies, dug up the Sparkfun FTDI Basic Breakout board I’d bought a year ago, and…noticed that the pins on the breakout board and the LilyPad didn’t match. Because although the LilyPad, which I’d gotten at the NYU store, was in a baggie labeled with the current Sparkfun part number, it was, in fact, the LilyPad Arduino 02, which has four pins to the breakout board’s six.

LilyPad 02 + LilyPad 04 + FTDI Basic Breakout

That Arduino was old when I started at ITP, and I’d deliberately avoided buying one from the NYU store last fall, because I’d read about the new six-pin version on Sparkfun and noticed that the local store still had old stock. By the time I bought LilyPad one the following spring, though, they should have been through with them—and perhaps they didn’t realize that they weren’t, because the thing was in a baggie labeled with the wrong part number. The result was a pain in my ass, leaving me with a device I couldn’t easily plug into a USB cable. I stared at the schematic, and at the breakout board, and the LilyPad itself, using a loupe so that I could read the labels on the pins in the by the lounge’s dingy evening light. Then Zach Taylor looked at it with me and confirmed my hope that I could use wires to connect the pins on the Arduino to the relevant pins on the breakout board. Then I found a packet of female-to-female jumper wires among my electronics junk, and I thought my problem was solved. I hooked up the accelerometer using pliers and wire, plugged everything in, and . . .

Ghetto LilyPad adapter

It didn’t work.

I couldn’t get Arduino-the-app to talk to Arduino-the-board. The LED on the board lit up, and it did a bit of blinking, but it didn’t seem to be listening. Having had similar issues with the Arduino NG which the NYU store had sold me—another instance of their selling outdated hardware, and the current board (and the one they sold to everyone else in my PhysComp class) was then the Diecimila—I tried pressing the reset button at various times before and after clicking the upload button in the app. Meanwhile, Snow Leopard was giving me a message about a new something-something being installed everytime I plugged the Arduino in, and I wasn’t sure what that was about. I spent some time looking at posts on arduino.cc troubleshooting forum, but without another board to use for testing, I couldn’t tell where the problem might lie—was it my ad-hoc cable adapter, or Snow Leopard, or the finicky LilyPad? So I took the whole mess home, so I could try again with my known-to-be-functional Duemilanove.

The Duemilanove worked eventually, of course, but it’s too big to wear on the back of your hand, so I switched from a wearable model to a handheld device. So I ended up cutting some holes in a Sparkfun box, taping the board in place inside, and printing a label for the top. Simple cue: if the text is upside-down when you’re holding the box, you’ve got it facing the wrong way.

Pong controller

The final Processing code, infinitesimally modified from what Tom supplied to us:

/*  
 Serial String Reader + Simple net Client
 Language: Processing
 
 Reads in a string of characters from a serial port until 
 it gets a linefeed (ASCII 10).  Then splits the string into 
 sections separated by commas. Then converts the sections to ints, 
 and prints them out.
 
 * Starts a network client that connects to a server on port 8080,
 * sends any keystrokes pressed.
 
 created 2 Jun 2005
 modified 6 Aug 2008
 by Tom Igoe
 modified 24 September 2009 by India Amos
 */

import processing.serial.*;     // import the Processing serial library
import processing.net.*;        // import the Processing networking library

Serial myPort;                  // The serial port

Client myClient;                   // instance of the net Client
String data;                       // string to hold incoming data
String ipAddress = "128.122.151.178";    // address of the server
String myKey1;                   // the virtual keypress generated by the x-pin of the accelerometer
String myKey2;                   // the virtual keypress generated by the y-pin of the accelerometer
String myKey3;                   // the virtual keypress generated by the switch
String myKeyBuffer;              // all the virtual keys pressed by a single bleat from the Arduino 

float bgcolor;		        // Background color

void setup() {
  // establish the background and foreground:
  size(200, 200);      
  background(50);
  fill(200);

  // Connect to server on port 8080
  myClient = new Client(this, ipAddress, 8080);

  // List all the available serial ports
  println(Serial.list());

  // I know that the first port in the serial list on my mac
  // is always my  Arduino module, so I open Serial.list()[0].
  // Change the 0 to the appropriate number of the serial port
  // that your microcontroller is attached to.
  myPort = new Serial(this, Serial.list()[0], 9600);

  // read bytes into a buffer until you get a linefeed (ASCII 10):
  myPort.bufferUntil('\n');
}

void draw() {
}

// serialEvent  method is run automatically by the Processing applet
// whenever the buffer reaches the  byte value set in the bufferUntil() 
// method in the setup():

void serialEvent(Serial myPort) { 
  // read the serial buffer:
  String myString = myPort.readStringUntil('\n');
  // if you got any bytes other than the linefeed:
  if (myString != null) {

    myString = trim(myString);

    // split the string at the commas
    // and convert the sections into integers:
    int sensors[] = int(split(myString, '\t'));

    // print out the values you got:
    print(sensors[0] + ","); 

    // If there's incoming data from the client:

    if (myClient.available() > 0) { 
      // get the data:
      data = myClient.readString(); 
      println(data);
    }

    if (myKeyBuffer != null) {
      // send out anything that's typed:
      myClient.write(myKeyBuffer); 
    }
    if (keyPressed) {
      // send out anything that's typed:
      myClient.write(key); 
    }
  }
}

The final Arduino code, cribbed from Arduino.cc:

/*
  ADXL3xx
  
  Reads an Analog Devices ADXL3xx accelerometer and communicates the
  acceleration to the computer.  The pins used are designed to be easily
  compatible with the breakout boards from Sparkfun, available from:
  http://www.sparkfun.com/commerce/categories.php?c=80

  http://www.arduino.cc/en/Tutorial/ADXL3xx

  The circuit:
  analog 0: accelerometer self test
  analog 1: z-axis
  analog 2: y-axis
  analog 3: x-axis
  analog 4: ground
  analog 5: vcc
  digital 2: push-button switch
  
  created 2 July 2008 by David A. Mellis
  modified 26 June 2009 by Tom Igoe
  modified 24 September 2009 by India Amos

 */

 // these constants describe the pins. They won't change:
 const int groundpin = 18;             // analog input pin 4 -- ground
 const int powerpin = 19;              // analog input pin 5 -- voltage
 const int xpin = 3;                   // x-axis of the accelerometer
 const int ypin = 2;                   // y-axis
 const int zpin = 1;                   // z-axis (only on 3-axis models)
 const int pushbuttonpin = 2;          // digital input 

 void setup()
 {
   // initialize the serial communications:
   Serial.begin(9600);

   // Provide ground and power by using the analog inputs as normal
   // digital pins.  This makes it possible to directly connect the
   // breakout board to the Arduino.  If you use the normal 5V and
   // GND pins on the Arduino, you can remove these lines.
   pinMode(groundpin, OUTPUT);
   pinMode(powerpin, OUTPUT);
   pinMode(pushbuttonpin, INPUT);
   digitalWrite(groundpin, LOW); 
   digitalWrite(powerpin, HIGH);
 }

 void loop()
 {
   // print the sensor values:
   Serial.print(analogRead(xpin));
   // print a tab between values:
   Serial.print("\t");
   Serial.print(analogRead(ypin));
   // print a tab between values:
   Serial.print("\t");
   Serial.print(analogRead(zpin));
   // print a tab between values:
   Serial.print("\t");
   Serial.print(digitalRead(pushbuttonpin));
   Serial.println();
   // delay before next reading:
   delay(50);
 }

And here’s the software we played against, more or less.

Leave a Reply

Your email address will not be published. Required fields are marked *