Spring 2010 CSCI 373 Final Lab

Last week

Last week we did look at a gruesome display controlled by an Arduino connected to an accelerometer.

If I remember correctly most of you downloaded the Arduino program and modified it for your board, which contains only a single potentiometer.

A simple team building game

Let's start with a simple game written in Processing. In the game you see four black dots connected by a brown line. The black dots represent places that can be moved up an invisible line. The brown line represents a rope connecting the four dots. The goal of the game is to raise the rope to the top of the window.

However, there is one catch. If the dots are raised at different rates, the rope is stretched. The tension on the rope is represented by the background of the game window. When tension is low, the background is green. As tension is raise, the background turns from green to yellow to orange and finally to red. If the background becomes a "pure" red, the rope is broken, and the game must be started.

The game is inspired by a training exercise for UNC Asheville faculty which was supposed to increase team(wo)manship. Go ahead and download the game and try to run it on your system.

The graphical interface of this program is rather week so you are welcome to improve it.

An XBee-ified game

The purpose of this lab is to modify the game so that four separate Arduino-controlled potentiometers are used to control the dots, rather than the mouse.

Step 1

To get this started, everyone must modify their XBee program to use a different CALLSIGN. Go ahead and do this and then report your CALLSIGN to the rest of the class.

Step 2

My next step was to modify the game program to receive inputs from the XBees rather than from the mouse. This isn't easy.

You can start by copying the serialEvent program from the Processing skull and bones program into the game program.

String inString = "";    // the string coming in from the serial port
// this method runs when bytes show up in the serial port:
void serialEvent(Serial myPort) {
  // read the next byte from the serial port:
  int inByte = myPort.read();
  // add it to  inString:
  inString += char(inByte);
  if (inByte == '\r') {
    processInput(inString) ;
    inString = "" ;
  }
} 

But once you do that you must write a processInput routine. This isn't easy, so I'm going to give you one.

void processInput(String inString) {
  String[] tokens = split(inString, '=') ;
  if (tokens.length == 2) {
    String varName = trim(tokens[0]) ;
    int newVal  = int(trim(tokens[1])) ;
    for (int i=0; i<NUMPLAYERS; ++i) {
      if (varName.equals(PLAYERNAMES[i])) {
        int restrictValue = constrain(newVal,
                                      PLAYERMINS[i],
                                      PLAYERMAXS[i]) ;
        yPos[i] = (int)map(restrictValue,
                           PLAYERMINS[i],
                           PLAYERMAXS[i],
                           maxY,
                           minY) ; 
      }
    }
  }
  if (!ropeOK) {
    int i ;
    for (i=0; i<NUMPLAYERS && yPos[i] == minY; ++i) ;
    if (i==NUMPLAYERS) {
      klaxon.pause() ;
      klaxon.rewind() ;
      ropeOK = true ; 
    }
  }
  redraw() ;
}

Go ahead and try to compile your program. You should get plenty of errors. There should be a few undeclared variables that contain "PLAYER" within their names, in particular, PLAYERNAMES, PLAYERMINS, and PLAYERMAXS. There arrays contain the player names and the minimum and maximum values that can be transmitted through there potentiometers. Try to give some reasonable values for these variables.

You still aren't done. You need to add a few lines of code to initialize the Serial variable. That will be something like the following:

  // list all the serial ports:
  println(Serial.list());
  // based on the list of serial ports printed from above
  // select the correct one below.

  portnum = "COM4" ;

  myPort = new Serial(this, portnum, 9600);