Word Finder, Google Earth Edition

Google Earth Word Finder

This is a 1st Life / 2nd Life game that is based on paper-based word-finder games. In this game, you try to identify dictionary words within a grid of letters and circle them. In this variation, the landscape becomes the game grid and you have to walk (or run!) to generate a virtual line that runs through the letters in order to “capture” the word and score points. A GPS is used to help the team identify where the letters are in 1st Life space, and to “capture” the words composed of those letters by recording “track logs” through them. The GPS is able to record where you are in 1st Life, and to create “tracks” of locations, which are essentially connected points that make up lines on the GPS. These track logs can be seen as a way of geospatial drawing — the tracks you make delineate lines which can compose various forms of drawing. In our case, the lines are meant to create lines through the letters that make up the words. (Note that in the more traditional word finder games one circles the letters — that would be a bit tricky in this variation, so we’ll just draw an approximate line _through_ the letters.

Google Earth Word Finder

Teams start with a traditional word finder grid. The grid contains words up, down, diagonal and backwards. The challenge is to identify the words and “capture” them by physically tracing their corresponding locations in 1st Life as quickly as possible.

Each team has 10 minutes to identify the words on paper, and then 20 minutes to “capture” them. The team that captures the most words in the shortest time “wins.”

Google Earth Word Finder

The game takes place in Aldrich Park at UC Irvine, part of the UC Humanities Research Institute’s “Technofutures” Symposium.

Suggestions
1. It may be helpful to identify the corners of the game grid to help you geospatially orient in 1st Life. Translating the game grid on paper to real space can be tricky!

2. Extracting GPS tracks from a Garmin GPS isn’t hard, but it isn’t easy, either. I used GPSBabel, a smart cross-switch between all kinds of geospatial data dialects.

For example, here is how I used GPSBabel for a class project in order to extract students’ track logs from their GPS’s:

gpsbabel -t -i garmin -f /dev/cu.KeySerial1 -o kml -F ~/Desktop/CTIN405/gps_6.kml

-t instructs GPSBabel to extract the tracklog only
-i specifies that the input device is a Garmin
-f specifies the input “file” — in this case the device is actually the Keyspan serial adapter connected to my Macintosh — your precise device will almost certainly be different, depending on your computer, operating system, and how you connect the Garmin device to your computer
-o indicates that the output type, in this case a Google Earth KML file
-F specifies where I want the output file saved

On my computer I had to run this as a privileged (root) user in order to access the device. There’s a GUI for GPSBabel, but it was wonky and would say it was done when it hadn’t done a thing. I like the command line, I guess..

Technorati Tags: , ,

Arduino Workshop — An Introduction To Device Art With The Arduino

R0012414

Recently at IMD we had a ball workshopping design and technology for device art using the Arduino. Fun stuff.

Below are links to the workshop’s slides and tutorial code.

Workshop Slides (No Notes)

Workshop Slides (With Notes)

Technorati Tags: , , , ,

The Ersatz Cylon Detector: A Hardware Sketch To Illuminate The Inner Workings of the MAX6953 Integrated Circuit

Cylon Detector In Operation

An on-going project that requires the display of alphabetic and numeric characters using a 5×7 LED matrix turned me towards a chip by Maxim IC — the MAX6953. The chip, while expensive (~$8), has lots of built-in features that mitigate the damage to my purse, trading such in kind for time-saved. It will directly drive up to 4 5×7 LED matrices with direct control from a microcontroller over a two-wire interface (TWI/I2C), can manage varying intensities (16 or 32 degree scales), has a built-in Arial-like font set with a reasonably full-range of characters, diacritics and symbols, and allows me to create 24 characters of my own design.

Here’s my Eagle PCB library of the MAX6951 and MAX6953; feel free to use it.

SlowMessenger_Max6953_Breakout

SlowMessenger_Max6953_Breakout_Board

My first attempt at mucking with the chip used the DIP version, which is ginormous and requires such patience and diligence with wiring the thing up — all those lines going to the pins of the LED matrix — that I pretty much gave up after it didn’t work the first time. I decided that I’d just go ahead and design a PCB for the thing and continue to hone my skills with Eagle, while also learning how to work with the MAX6953.

Some Samples

I sent a design off, it came back, I stared at it for a few minutes, looked for the MAX6953’s in my bin of samples and realized I didn’t have any. I managed to coax a bunch from Maxim’s sample guy, which is great. (Thanks whoever you are, wherever you are.) A couple of weeks later, when my plate was relatively clear, I assembled one of the boards, using a yellowish/orange 5×7 matrix LED I purchased from Digikey and manufactured by LiteOn. I wanted small, but the closest I got to small was 0.7″, which still seems big to me. (The story of it’s assembly and problems therein is instructive if you’re curious about surface-mount PCB work..and the problems therein.)

I powered the thing up and, naturally enough, it didn’t illuminate at all. I poked through the spec sheet and figured out that there’s a whole start-up ritual you’ll want to go through, such as the test mode and negating the shutdown bit, which defaults to “shutdown enabled.” After an hour or so of puzzling, I managed to get it displaying characters while hooked up to my usual Arduino test harness thing.

Lower "T"

While I was assembling the board, I realized I wasn’t sure what the proper orientation of the LED device should be. I looked for markings to indicate pin 1 and found nothing definitive. I looked at the product data sheet and they had an arrow pointing at pin 1 but nothing that clearly told me how to determine which of the pins was the first. Now, the holes I put in for the LED device in Eagle were a bit snug — too snug, really. It required a bit of jiggering to get the LED device to fit. (I went back and made the holes slightly bigger in the design.) But, I realized this could be an advantage given my current pin alignment peril — the snugness would allow the LED device’s pins to make contact with the through-holes’ platings! In other words, I could fit the device one way and not solder the pins to see if I had the thing right-way-around.

Evil Rabbit Character

Well, that worked. A consequence of it working was that some of the columns and rows didn’t illuminate quite consistently — they’d flicker and such — and a mysterious character appeared — an evil rabbit was the first thing I saw.

I ran through a few code gyrations and got characters to show, right-way-around, so I went ahead and soldered the LED device permanently to the board, easy-peasy.

Thinking of a few possible ways to make this learning project fun to share for the show-and-tell session of the weekly luncheon I have with some friends, I decided that I’d make a combination Magic 8 Ball / Cylon Detector, the idea being that one could reasonably ask the Magic 8 Ball if one were a Cylon — I mean..why not? — which would be a lot easier than what Baltar was trying to construct, and wouldn’t require blood samples or anything. You could just ask yourself, in the privacy of your own home or a public restroom, and then choose whether or not you wanted to share your result.

So, I hooked it up to an accelerometer that detects the normative shaking motion one inflicts on the Magic 8 Ball..the evil rabbit then divines the response.

Anyway, it definitely works.

The Ersatz Cylon Detector is meant for entertainment purposes only. It does not purport to factually report whether or not individuals are Cylons, except for Don Milvio. (He’s definitely a weird hybrid Franco-Italian Cylon thing.) The results are for home amusement and cannot be used for discovery or detection of actual Cylons, their friends or family. The results cannot be used for legal purposes, nor as a sanction for physical violence. The Ersatz Cylon Detector and its results are not endorsed by the producers of Battlestar Galactica, The SciFi Channel, or its affiliates and their station managers.


Arduino Code

#include <Wire.h>
#include <math.h>

// http://wiring.org.co/reference/libraries/Wire/index.html
// On the Arduino board, Analog In 4 is SDA, Analog In 5 is SCL
// These correspond to pin 27 (PC4/ADC4/SDA) and pin 28 (PC5/ADC5/SCL) on the Atmega8
// The Wire class handles the TWI transactions, abstracting the nittygritty to make
// prototyping easy.
// This sketch has two TWI devices connected to it — a LIS3LV02DQ triaxis accelerometer
// and the MAX6953 5x7 matrix LED driver. The MAX6953 is at address 0x50, and the LIS3LV02DQ is
// at address 0x1D.

char mAnswer_1[19] = {‘S’,‘i’,‘g’,‘n’,‘s’,‘ ‘,‘p’,‘o’,‘i’,‘n’,‘t’,‘ ‘,‘t’,‘o’,‘ ‘,‘y’,‘e’,‘s’,0x00};
char mAnswer_2[4] = {‘Y’,‘e’,‘s’,0x00};
char mAnswer_3[12] = {‘M’,‘o’,‘s’,‘t’,‘ ‘,‘l’,‘i’,‘k’,‘e’,‘l’,‘y’,0x00};
char mAnswer_4[16] = {‘W’,‘i’,‘t’,‘h’,‘o’,‘u’,‘t’,‘ ‘,‘a’,‘ ‘,‘d’,‘o’,‘u’,‘b’,‘t’,0x00};
char mAnswer_5{16] = {‘Y’,‘e’,‘s’,‘,’,‘ ‘,‘d’,‘e’,‘f’,‘i’,‘n’,‘i’,‘t’,‘e’,‘l’,‘y’,0x00};
char mAnswer_6[17] = {‘A’,‘s’,‘ ‘,‘I’,‘ ‘,‘s’,‘e’,‘e’,‘ ‘,‘i’,‘t’,‘,’,‘ ‘,‘y’,‘e’,‘s’,0x00};
char mAnswer_7[19] = {‘Y’,‘o’,‘u’,‘ ‘,‘m’,‘a’,‘y’,‘ ‘,‘r’,‘e’,‘l’,‘y’,‘ ‘,‘o’,‘n’,‘ ‘,‘i’,‘t’,0x00};
char mAnswer_8[13] = {‘O’,‘u’,‘t’,‘l’,‘o’,‘o’,‘k’,‘ ‘,‘g’,‘o’,‘o’,‘d’,0x00};
char mAnswer_9[14] = {‘I’,‘t’,‘ ‘,‘i’,‘s’,‘ ‘,‘c’,‘e’,‘r’,‘t’,‘a’,‘i’,‘n’,0x00};
char mAnswer_10[19] = {‘I’,‘t’,‘ ‘,‘i’,‘s’,‘ ‘,‘d’,‘e’,‘c’,‘i’,‘d’,‘e’,‘d’,‘l’,‘y’,‘ ‘,‘s’,‘o’,0x00};
char mAnswer_11[22] = {‘R’,‘e’,‘p’,‘l’,‘y’,‘ ‘,‘h’,‘a’,‘z’,‘y’,‘,’,‘ ‘,‘t’,‘r’,‘y’,‘ ‘,‘a’,‘g’,‘a’,‘i’,‘n’,0x00};
char mAnswer_12[24] = {‘B’,‘e’,‘t’,‘t’,‘e’,‘r’,‘ ‘,‘n’,‘o’,‘t’,‘ ‘,‘t’,‘e’,‘l’,‘l’,‘ ‘,‘y’,‘o’,‘u’,‘ ‘,‘n’,‘o’,‘w’,0x00};
char mAnswer_13[16] = {‘A’,‘s’,‘k’,‘ ‘,‘a’,‘g’,‘a’,‘i’,‘n’,‘ ‘,‘l’,‘a’,‘t’,‘e’,‘r’,0x00};
char mAnswer_14[26] = {‘C’,‘o’,‘n’,‘c’,‘e’,‘n’,‘t’,‘r’,‘a’,‘t’,‘e’,‘ ‘,‘a’,‘n’,‘d’,‘ ‘,‘a’,‘s’,‘k’,‘ ‘,‘a’,‘g’,‘a’,‘i’,‘n’,0x00};
char mAnswer_15[19] = {‘C’,‘a’,‘n’,‘n’,‘o’,‘t’,‘ ‘,‘p’,‘r’,‘e’,‘d’,‘i’,‘c’,‘t’,‘ ‘,‘n’,‘o’,‘w’,0x00};
char mAnswer_16[18] = {‘M’,‘y’,‘ ‘,‘s’,‘o’,‘u’,‘r’,‘c’,‘e’,‘s’,‘ ‘,‘s’,‘a’,‘y’,‘ ‘,‘n’,‘o’,0x00};
char mAnswer_17[14] = {‘V’,‘e’,‘r’,‘y’,‘ ‘,‘d’,‘o’,‘u’,‘b’,‘t’,‘f’,‘u’,‘l’,0x00};
char mAnswer_18[20] = {‘O’,‘u’,‘t’,‘l’,‘o’,‘o’,‘k’,‘ ‘,‘n’,‘o’,‘t’,‘ ‘,‘s’,‘o’,‘ ‘,‘g’,‘o’,‘o’,‘d’,0x00};
char mAnswer_19[18] = {‘D’,‘o’,‘n’,,‘t’,‘ ‘,‘c’,‘o’,‘u’,‘n’,‘t’,‘ ‘,‘o’,‘n’,‘ ‘,‘i’,‘t’,0x00};

void setup()
{

Serial.begin(9600);

CLKPR = (1<<CLKPCE);
CLKPR = 0;

// initialize the LIS3LV02DQ
Wire.begin(); // join i2c bus (address optional for master)
Wire.beginTransmission(0x1D);
Wire.send(0x20); // CTRL_REG1 (20h)
Wire.send(0x87); // Device on, 40hz, normal mode, all axiss enabled
Wire.endTransmission();

// initialize the MAX6953
Wire.beginTransmission(0x50);
Wire.send(0x07); // Display Test
Wire.send(0x00); // Normal Operation
Wire.endTransmission();

Wire.beginTransmission(0x50);
Wire.send(0x01); // Intensity16
Wire.send(0x0F); // Full
Wire.endTransmission();

Wire.beginTransmission(0x50);
Wire.send(0x04); // configuration register
Wire.send(0x01); // disable shutdown mode
Wire.endTransmission();
initializeSpecialCharacters();
}

void loop() {
int z_val, x_val, y_val;
int sum_sq, sum_sq_2, diff, mShake, message;
int max_accel;
byte i;

message = 0;

setCharacter(0x00);
delay(random(500,1000));
setCharacter(0x01);
delay(random(500,1500));

x_val = getX();
y_val = getY();
z_val = getZ();

sum_sq = sqrt(pow(x_val, 2) + pow(y_val, 2) + pow(z_val, 2));

delay(100);
x_val = getX();
y_val = getY();
z_val = getZ();
mShake = 0;
sum_sq_2 = sqrt(pow(x_val, 2) + pow(y_val, 2) + pow(z_val, 2));
diff = abs(sum_sqsum_sq_2);
if(diff > 300) { mShake = 1; }
if(diff > 1000) { mShake = 2; }
if(diff > 1200) { mShake = 3; }

//Serial.print(diff); Serial.print(" "); Serial.print(max_accel); Serial.print(" "); Serial.println(mShake);

if(diff > max_accel) max_accel = diff;

//delay(500);

if(mShake > 0) {
message = random(0,18);
for(int i=0; i<3; i++) {
setCharacter(‘*’); delay(500); setCharacter(‘ ‘); delay(500);
}
} else {
message = 1;
}
switch(message) {
case 0:
i = 0;
while(mAnswer_1[i] != 0x00) {
setCharacter(mAnswer_1[i]); delay(800);
i++;
}
break;
case 1:
i = 0;
while(mAnswer_2[i] != 0x00) {
setCharacter(mAnswer_2[i]); delay(800);
i++;
}
case 2:
i = 0;
while(mAnswer_3[i] != 0x00) {
setCharacter(mAnswer_3[i]); delay(800);
i++;
}
break;
case 3:
i = 0;
while(mAnswer_4[i] != 0x00) {
setCharacter(mAnswer_4[i]); delay(800);
i++;
}
break;
case 4:
i = 0;
while(mAnswer_5[i] != 0x00) {
setCharacter(mAnswer_5[i]); delay(800);
i++;
}
break;
case 5:
i = 0;
while(mAnswer_5[i] != 0x00) {
setCharacter(mAnswer_5[i]); delay(800);
i++;
}
break;
case 6:
i = 0;
while(mAnswer_6[i] != 0x00) {
setCharacter(mAnswer_6[i]); delay(800);
i++;
}
break;
case 7:
i = 0;
while(mAnswer_7[i] != 0x00) {
setCharacter(mAnswer_7[i]); delay(800);
i++;
}
break;
case 8:
i = 0;
while(mAnswer_8[i] != 0x00) {
setCharacter(mAnswer_8[i]); delay(800);
i++;
}
break;
case 9:
i = 0;
while(mAnswer_9[i] != 0x00) {
setCharacter(mAnswer_9[i]); delay(800);
i++;
}
break;
case 10:
i = 0;
while(mAnswer_10[i] != 0x00) {
setCharacter(mAnswer_10[i]); delay(800);
i++;
}
break;
case 11:
i = 0;
while(mAnswer_11[i] != 0x00) {
setCharacter(mAnswer_11[i]); delay(800);
i++;
}
break;
case 12:
i = 0;
while(mAnswer_12[i] != 0x00) {
setCharacter(mAnswer_12[i]); delay(800);
i++;
}
break;
case 13:
i = 0;
while(mAnswer_13[i] != 0x00) {
setCharacter(mAnswer_13[i]); delay(800);
i++;
}
break;
case 14:
i = 0;
while(mAnswer_14[i] != 0x00) {
setCharacter(mAnswer_14[i]); delay(800);
i++;
}
break;
case 15:
i = 0;
while(mAnswer_15[i] != 0x00) {
setCharacter(mAnswer_15[i]); delay(800);
i++;
}
break;
case 16:
i = 0;
while(mAnswer_16[i] != 0x00) {
setCharacter(mAnswer_16[i]); delay(800);
i++;
}
break;
case 17
i = 0;
while(mAnswer_17[i] != 0x00) {
setCharacter(mAnswer_17[i]); delay(800);
i++;
}
break;
case 18:
i = 0;
while(mAnswer_18[i] != 0x00) {
setCharacter(mAnswer_18[i]); delay(800);
i++;
}
break;
case 19:
i = 0;
while(mAnswer_19[i] != 0x00) {
setCharacter(mAnswer_19[i]); delay(800);
i++;
}
break;
default:
break;
}
message = 0;
}

void flickerOutIntensity()
{
for(int i=16; i>=0; i) {
Wire.beginTransmission(0x50);
Wire.send(0x01); // Intensity16
Wire.send(i);
Wire.endTransmission();
delay(random(400));
if(i % 4 == 0) {
Wire.beginTransmission(0x50);
Wire.send(0x01); // Intensity16
Wire.send(0x02);
Wire.endTransmission();
delay(random(500));
}
}
Wire.beginTransmission(0x50);
Wire.send(0x01); // Intensity16
Wire.send(0x0f); // Full
Wire.endTransmission();
}

// create two custom characters that look like an evil cylon detecting magic 8 ball rabbit
// this writes the two characters by writing first to register 0x05 the value 0x80, which is
// the address of the first 7 bits of he first usercreated font character. Each character
// has 5 rows of 7 bits, you write to each row in sequence. The MAX6953 will autoincrement
// the address written during the I2C/TWI transaction, so each of these Wire.send instructions
// is writing to the next row.
void initializeSpecialCharacters
{
Wire.beginTransmission(0x50);
Wire.send(0x05);
Wire.send(0x80);

// character 0x00
Wire.send(0x7f);
Wire.send(0x14);
Wire.send(0x44);
Wire.send(0x14);
Wire.send(0x7f);

// character 0x01
Wire.send(0x7f);
Wire.send(0x04);
Wire.send(0x44);
Wire.send(0x04);
Wire.send(0x7f);

Wire.endTransmission();

}

void setCharacter(char c)
{
// if(c >= 0x20 && c <= 0x7F) {
Wire.beginTransmission(0x50);
Wire.send(0x20); // Digit 0 Plane 0
Wire.send(c); // N
Wire.endTransmission();
// }
}

int getX()
{
byte x_val_l, x_val_h;
int x_val, y_val;
//Serial.println("hello?");
//byte in_byte;
// transmit to device with address 0x1D
// according to the LIS3L* datasheet, the i2c address of is fixed
// at the factory at 0011101b (0x1D)
Wire.beginTransmission(0x1D);
// send the sub address for the register we want to read
// this is for the OUTZ_H register
// n.b. supposedly masking the register address with 0x80,
// you can do multiple reads, with the register address autoincremented
Wire.send(0x28);
// stop transmitting
Wire.endTransmission();
// Now do a transfer reading one byte from the LIS3L*
// This data will be the contents of register 0x28
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
x_val_l = Wire.receive();
}
Wire.beginTransmission(0x1D); Wire.send(0x29); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
x_val_h = Wire.receive();
}
x_val = x_val_h;
x_val <<= 8;
x_val += x_val_l;

return x_val;
}

int getY()
{
byte y_val_l, y_val_h;
int y_val;
// Y Axis
Wire.beginTransmission(0x1D); Wire.send(0x2A); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
y_val_l = Wire.receive();
}
Wire.beginTransmission(0x1D); Wire.send(0x2B); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
y_val_h = Wire.receive();
}

y_val = y_val_h;
y_val <<= 8;
y_val += y_val_l;

return y_val;
}

int getZ()
{
byte z_val_l, z_val_h;
int z_val;
// Z Axis
Wire.beginTransmission(0x1D); Wire.send(0x2C); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
z_val_l = Wire.receive();
}
Wire.beginTransmission(0x1D); Wire.send(0x2D); Wire.endTransmission();
Wire.requestFrom(0x1D, 1);
while(Wire.available())
{
z_val_h = Wire.receive();
}

z_val = z_val_h;
z_val <<= 8;
z_val += z_val_l;

return z_val;
}

Update — here are a schematic and a board layout for the little board in the picture that contains the MAX6953 and the Matrix LED. I used my own breakout board like this, rather than run a whole bunch of wires from the 6953 to the Matrix LED.

SlowMail_Schematic

SlowMail_Board


Creative Commons License


This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License.

Technorati Tags: ,

Rhizome Commissions 2007-2008

Dear Julian Bleecker,

We’re pleased to announce that Rhizome’s 2007-08 Commissions cycle is now open. This year we will commission eleven new art works with awards ranging from $1000-$3000. The deadline for proposals is midnight, April 2.

We are funding in two categories: 1) New Works of Internet-based Art and 2) A Community Project. The second category is new this year, and will be awarded to one artist or group whose project will benefit our community by enhancing communication, participation or the user experience on the Rhizome website.

As a Rhizome Member, you are eligible to participate in our Community Vote, which determines three of the eleven commissions. The first phase of voting begins on April 9. We see the Community Vote as a unique member benefit, as it not only allows you to advocate for works you believe in, but also gives you a chance to survey timely ideas and practices in the field.

We encourage you to get involved and spread the word! As a member, your support contributes to our ability to commission these works and we hope that you will participate – either by submitting a work, voting, or both! – in this year’s Commissions Program.

For more information:

Commissions program: http://rhizome.org/commissions/
Submission and Voting Procedures: http://rhizome.org/commissions/2007/procedures.php

When 1st Life Meets 2nd Life: The 1685 Pound Avatar and the 99 Ton Acre

Lift2007_FrontPage

A Second Life avatar produces 1,685 pounds of CO2? And an acre of real estate in Second Life produces 99 tons of CO2? What gives?

One of my pet research projects has been to find ways to establish effective, playful bridges between 1st life and 2nd life. What is 1st Life and what is 2nd Life? By 2nd life, I’m not referring to the virtual world run by Linden Labs. For me, “2nd life” is an evocative metaphor that counterpoints the normal, human, physical, material world, which I refer to as 1st life. I’ll grant that the language lacks precision, but I’m relying a bit on my own assumptions, which I think are fairly well-shared, as to what counts as a digital, networked, social environment. 1st life is then the non-networked, non-digital social environment.

The presentation — titled When 1st Life Meets 2nd Life I gave this week at Lift07 started with a reminder as to the material basis of 2nd life. There is “stuff” that undergirds digital networks — indeed every digital bit owes its life to some sort of material. Atoms compose digital data. There’s that stuff that we’re never really aware of unless we spend time working in the data center facilities where all of the Internets take physical form. 2nd life and its digital networks are made of heavy material — copper cable, steel racks to hold servers, rubber or plastic insulated power cabling, cooling systems, human labor, billions and billions of integrated circuits and the effluvia of the toxic chemicals expelled during their production, shipping and decomposition, etc. Our participation in this materiality probably ends at about the time when we discard the cardboard box and styrofoam packing of the shipping material in which our new computers arrive.

But this is more than the William Mitchell bits & atoms thesis. It’s not just the equivalence, but the precise nature of that material — what kind of stuff are we talking about? It’s not just the composition of digital bits, but what physical material, in the use of digital bits, of digital networks, of our PC’s, web and game servers, is produced.

Perhaps the most unsettling material characteristic of our 2nd lives is considering the resources necessary to maintain them. Whether emailing, googling, blogging, uploading videos, downloading music — everything — this owes a measurable and material debt to first life. When one computes the amount of power — normal 1st life electricity — that is consumed to maintain our 2nd lives it becomes clear what that debt is. Or when one computes how many tons of CO2 emissions result from the production of that electricity, assuming the majority of our power comes from plants that burn something that produces CO2 as a consequence of producing electricity.

I started running these numbers after reading a very interesting and thought-provoking discussion on Nicholas Carr’s blog where he computed these figures based on some public figures he found pertaining to Linden Lab’s Second Life environment. One could run the same numbers for any other digitally networked activity, like emailing or web surfing or whatever.

What’s particularly appealing about choosing an online world like Second Life as my example is that it’s underlying metaphor is 1st life. Email would be another good example, as postal mail requires energy that exhausts CO2 in its processing and delivery. But Second Life has more PR these days, so I’ll use that as an example.

Second Life itself captures many of the important characteristics of 1st life and uses that to convey a sense of familiarity for the users. There is property in Second Life, waterways, buildings, etc. It’s a 3D virtual world that is largely modeled on commonly held assumptions about what counts as 1st life. What it doesn’t convey to its users is any kind of Second Life representation of the ecological cost of that Second Life world, which would be very cool — Second Life CO2 emissions, for instance, to correspond to equivalent estimates about how much CO2 is emitted in 1st life.

I was shocked at the numbers on Carr’s blog, so I computed them myself to check the math. I revised some of his assumptions, so my figures are significantly more conservative than his. (I’d even go so far as to say that my figures are unrealistically low, because a more rigorous analysis would include estimates about the power consumption of the ancillary network devices between the user’s computer and the data center.) I also culled from comments in Carr’s blog post to refine some of the assumptions, especially the remarks from Second Life employees who have direct access to some of the power consumption figures.

There are a few additional assumptions I’ve made, mostly pertaining to what I think is a more realistic assumption as to how much power a typical home PC uses, and how often one might actually play Second Life.

Carr assumes that a home PC consumes 120 watts, which I think is much too low — I assume 300 watts, based on looking at the technical specifications of a mid-range Dell computer, and I also compute the power consumption of an LCD display. I also don’t assume, as Carr does, that someone playing Second Life is playing 24 hours a day — I assume, averaged over a year, they will play eight hours per day. Some days they won’t play, others they may invest 12 hours. I think 8 hours is a fair assumption.

I’ve also used the assumption that 1.35 pounds of CO2 is emitted per kWH of electricity produced.

A Linden Labs employee measured the power consumption of their servers and came up with the figure of 175 watts (energy per hour) with the server running at full-tilt. I assume that the servers basically run at full-tilt 24 hours a day, seven days a week, and that servers of this sort make demands on the data center for cooling, power distribution, ancillary resources like lighting, operations center energy costs, keeping the candy and pop machine running in the break room, etc., at an equivalent of 50% of their nominal energy use. So, a 175 watt server actually needs 175+87.5 watts of energy to function in a data center.

I came up with the following figures (the calculus is further below):

Power Consumption Per Avatar Per Year (Second Life Servers): 153 kWH
Power Consumption Per Avatar Per Year (Home User’s PC): 1,095 kWH
Total Power Consumption Per Avatar Per Year: 1,248 kWH

CO2 Emissions Per Avatar Per Year (Second Life Servers): 207 lbs (94 kilos)
CO2 Emissions Per Avatar Per Year (Home User’s PC): 1,478 lbs (670 kilos)
Total CO2 Emissions Per Avatar Per Year: 1,685 lbs (764 kilos)

Second Life is composed of regions that have a correspondence to normal 1st life acres. I’ve learned that there are 16 acres per region, and there are 4 regions per server, so there are a total of 64 Second Life acres per server. That means the power consumption per Second Life acre is 4.10 kWH, or 147,168 kWH per Second Life acre per 1st life year. And that means that 23 pounds of CO2 is produced and exhausted into the 1st life atmosphere per Second Life acre per hour, or 198,677 pounds (90,118 kilos) per Second Life acre per year.

Some equivalence for perspective:

In 2003, the per-capita power consumption in the United States: 13,242 kWH
In 2001, the per-capita power consumption in Iceland: 26,947 kWH
In 2001, the per-capita power consumption in Keyna: 118 kWH
(World Resource Institute, EarthTrends — http://earthtrends.wri.org)

Every year, every Avatar in Second Life produces CO2 emissions equivalent to a typical, honking, bloated, arrogant SUV driving 1,293 miles, based on the assumption that this kind of SUV generates 1 lbs of CO2 per mile.

If serving this page took the CPU on my modest web server .1 second to serve to you, it probably consumed .004 watt (assuming my clunker consumes 100 watts + 50 watts for overhead)..it works out to about 6 micrograms of CO2, not counting whatever your PC contributed to the production of CO2. Okay, I’m getting carried away, but you get the idea.

Why do I blog this?I find this kind of analysis fascinating and revealing. It is the kind of bridge between 1st life and 2nd life I am trying to build, where the semantic link between what goes on in our 2nd life worlds is made plain in its correspondence to 1st life. 2nd life activities are not the clean, sustainable, whole-earth friendly activities the Bay Area, Web 2.0 crew may think they are. Despite the important evolution of human social formations that have arisen, the messiness of the 1st life remains. Maybe there should be a little eco-meter on the dashboard of Second Life, World of Warcraft and, whatever — YouTube and my blog. I’d be interested in computing the same figures for World of Warcraft. I suspect they’re probably equivalent, although I’d probably bump up the average hours of play per WoW character quite a bit. I would need to know the distribution of simultaneous characters per server, or number of servers per instance, as well as some sense as to how much power is consumed by whatever server they may use. It’s about provoking some thinking about the material contingencies of our online activities. I won’t really quibble about the numbers. Someone’s going to want me to adjust something this way or that — the accuracy of the figure will be forever elusive, so I’m not interested in debating that, or tweaking some of the numbers. The point is — there is a debt paid for our online lives and we rarely think about it. How can we start to introduce the material aspects of this activity more directly? That is my goal here.


The Calculus

At The Data Center
Server Power Consumption (Energy Per Hour): 175 watts
Percept Power Consumption for Cooling and Ancillary Network Operations Center Needs: 50%
Ancillary Power Consumption Per Server (Energy Per Hour): 87.5 watts
Total Server Instance Power Consumption (Energy Per Hour): 262.5

Active Servers for Second Life: 1,000
Active Avatars in Second Life Per Day: 15,000
Average Active Avatars Per Server in Second Life Per Day: 15
Power Consumption Per Avatar Per Hour (Server Only): 262.5/15=17.5
Power Consumption Per Avatar Per Day (Server Only): 17.5*24=420
Power Consumption Per Avatar Per Year (kilowatt hours): 420*365/1000=153.3
CO2 Emissions Per Avatar Per Year (lbs): 153.3 (kilowatt hours)*1.35 (CO2 pounds per kilowatt hour)

Acres Per Region: 16
Regions Per Server: 4
Acres Per Server: 64
Power Consumption Per Acre: 262.5/64=4.10 kWH
Power Consumption Per Acre Per Year: 4.10*24*365=35,916kWH

CO2 Emissions Per Acre Per Hour: 1.35 (CO2 pounds per kilowatt hour) * 4.10 kWH = 5.535 lbs
CO2 Emissions Per Acre Per Year: 5.535 *24*365=48476.6 lbs

Average PC Power Consumption: 300 watts
Average PC LCD (17″) Power Consumption: 75 watts

At Home
PC Use (Hours/Day): 8
Power Consumption Per PC Per Day: 3 kWH
Power Consumption Per Avatar Per Day: 3 kWH (One PC At Home Per Avatar)
Power Consumption Per Avatar Per Year: 1,095 kWH

CO2 Emissions Per Avatar Per Day (Home PC @ 8 hours/day): 1.35 CO2 Pounds Per kWH * 3kWH = 4.05 lbs
CO2 Emissions Per Avatar Per Year (Home PC @ 8 hours/day): 4.05 * 365 = 1,478 lbs

Power Consumption Per Avatar Per Day (Home + Server): 20.5 lbs
Power Consumption Per Avatar Per Year (Home + Server): 1,248.3 lbs

CO2 Emissions Per Avatar Per Day (Home + Server): 27.68 lbs
CO2 Emissions Per Avatar Per Year: 1,685 lbs

SUV CO2 Emissions Per Mile: 1 lbs
Equivalent SUV Miles Per Avatar Per Year: 1,685

==============
Additional Links
Data Centers’ Growing Power Demands: A new report quantifies the electricity consumption of servers, revealing a startling trend.

Demand grows, but data centers don’t hog power: Net uses barely over 1 percent of U.S. electricity, study says

==============
Parenthetically, I’ve been asked why I pluralize Internets isn’t there just one? I guess my speculation is that we are heading toward a kind of Balkanization of digital networks, thanks to the deleterious effects of net neutrality. It wouldn’t surprise me if there were tiers of networks, with levels of privilege offered based on one’s ability to pay for better or faster or thicker bandwidth.

Technorati Tags: , , ,

In Geneva

This week I’m at the Lift Conference. I went last year and had an amazing time meeting a really novel cast of participants, and not all of them alpha-geeks by any means. There were people from the UN, doctor’s, bankers, homemakers, senior citizen’s advocates, artists, researchers, university professors, architects and on and on. The diversity made for such interesting and engaging conversations, which is something one rarely finds at a technology conference.

Lift is also a unique conference in my experience for the openness and transparency of its process. I serve on the advisory board and even with that exposure to the operation you’d think I have special insight, but I really don’t. We publish the expenses directly on the web site. For one, none of the organizers gets paid a salary, at all. Period. It’s all volunteer. No one gets paid. Speakers have their travel expenses covered for and that’s it. No long-dollar honorariums, etc. And that actually keeps the cost of attending within reason of humans. The conference costs 215000CHF to put on and had raised 210000, including registration of attendees. The last 5000 CHF should be made up by the last remaining last-minute registrations, which were raised to 395CHF each to make up for the deficit. Even at that price (around 319USD), this is still the least expensive conference around.

Flavonoid v.01s Notes

Flavonoid v.01s (I2C)

This is another Flavonoid variation. I fear there are now becoming more than is reasonable to manage. Each one reflects a different design sensibility and a learn-through-practice approach. I decided to use the I2C protocol for many of the devices, largely to address the challenge of routing too many signals and in a bid to make the software more manageable. But, I sometimes get ahead of myself. My eagerness to send designs off to be manufactured sometimes has me skip some important considerations. In the case of this design here, I thought I could substitute the clock chip with another, which has the exact same pin-outs, only uses I2C versus SPI. I even prototyped with it. But, it turns out that it’s a 5 volt device, with no real leeway. Most of the other chips prefer a low-voltage in the range of 2-3.6 volts. So, basically — this real-time clock, the DS1307, is incompatible.

Back to the drawing board to find a replacement. Fortunately, I found a suitable chip, the DS1340, which has the exact same pinouts, is compatible with I2C and is happy as a fed pig at the 3 or 3.3 volts with which I plan to power the board. I should be able to hot-air the DS1307 off and replace it with the DS1340. We’ll see how that goes.

On this design, I also went with a surface mount crystal for the clock and tried working with a dual-axis accelerometer, but now I’m pretty much definitely of the mind that a tri-axis unit is the way to go.

LIS3LV02DQ

I’ve been working at salvaging the LIS3LV02DQ tri-axis thing that cost me $15 a pop by trying my hand at hot-air rework. Here I popped the unit off and applied some flux to the thing, and then a warm solder iron. Like magic, it cleaned up and what looked like the perfect amount of solder magically adhered to each and every pin, clean as you like. This is what I should’ve done to begin with. Lesson learned. I reapplied it to the board and it looks like it attached just right. Unfortunately, the landing pad was a bit messed up with missing pads, but those were no-connects, so I might be okay.

Why do I want a tri-axis accelerometer? Well, my intuition is sort of guiding me here. This Durable Affinity design project is not concerned with the typical sort of meanings of precision (split-second, spot-on-accurate measurements of acceleration, etc.) I am curious how ambient precision can be used as a part of the interaction syntax. For instance, what sorts of interaction designs may arise when we take account of ambient movement, or ambient time — how much movement over the last 30 minutes, or has an hour passed or a few hours, and so forth.

Why do I blog this? Trying to create implications for my own work and keep track of what’s going on (and why it’s going on) in the Near Future Laboratory!