Saturday, 21 February 2009

Arduino and Processing 2

Processing Listing

import processing.serial.*;
import java.util.concurrent.* ;
import java.util.concurrent.BlockingQueue ;

// Class Wrapper for keeping in Nunchuck reading

public class NunChuckReading
{
int joyx,joyy,accx,accy,accz,buttonC,buttonZ ;

public NunChuckReading() {

}

public void setButtonC(int val) { buttonC = val ;}
public int getButtonC() { return buttonC ; }

public void setButtonZ(int val) { buttonZ = val ;}
public int getButtonZ() { return buttonZ ; }

public void setJoyX(int val) { joyx = val ; }
public int getJoyX() { return joyx ; }

public void setJoyY(int val) { joyy = val ; }
public int getJoyY() { return joyy ; }

public void setAccX(int val) { accx = val ; }
public int getAccX() { return accx ; }

public void setAccY(int val) { accy = val ; }
public int getAccY() { return accy ; }

public void setAccZ(int val) { accz = val ; }
public int getAccZ() { return accz ; }


public String toString() {
return "joy x,y= "+joyx+", "+joyy+", accXYZ= "+accx+", "+accy+", "+accz+" ButtonC,Z= "+buttonC+", "+buttonZ ;
}


}


Serial sPort ;
// Processing does not handle Types very well!
//private BlockingQueue nunChuckQueue = new LinkedBlockingQueue() ;
private BlockingQueue nunChuckQueue = new LinkedBlockingQueue();

void setup()
{
println("SetUp") ;
println(Serial.list()) ;
sPort = new Serial(this,Serial.list()[2],19200) ; // my USB serial port to the Arduino is the 3rd in my list
size(200, 200);
sPort.bufferUntil(13) ; // buffer until LineFeed

}

// serialEvent(Serial) serial event callback -
// when serialport receives a linefeed (via bufferUntil function)
// This function will be called -

void serialEvent(Serial sPort)
{
int sz = 0 ;
while ((sz = sPort.available()) > 0) {
//Expand array size to the number of bytes you expect:
byte[] inBuffer = new byte[sz];
sPort.readBytes(inBuffer);

if (inBuffer != null) {
String xmlString = new String(inBuffer) ;
parseSerialXmlString(trim(xmlString)) ;

}
}


}

// NB: XMLElement throws a wobbly at the start of joystick input for the first
// one to two seconds - and then settles down

void parseSerialXmlString(String xmlString) {

XMLElement el = new XMLElement(xmlString) ;

String rName = el.getName() ;
if (rName != null && rName.equals("NUNCHUK") && el.hasChildren())
{
NunChuckReading nunchuck = new NunChuckReading() ;

java.util.Enumeration elEnum = el.enumerateChildren() ;

while(elEnum.hasMoreElements()) {
XMLElement childElement = elEnum.nextElement() ;
String childName ;
int value ;

childName = childElement.getName() ;
value = Integer.parseInt(childElement.getContent());

if (childName.equals("JOYX")) {
nunchuck.setJoyX(value) ;

}else if (childName.equals("JOYY")) {
nunchuck.setJoyY(value) ;

} else if (childName.equals("ACCX")) {
nunchuck.setAccX(value) ;

} else if (childName.equals("ACCY")) {
nunchuck.setAccY(value) ;

} else if (childName.equals("ACCZ")) {
nunchuck.setAccZ(value) ;

} else if (childName.equals("BUTZ")) {
nunchuck.setButtonZ(value) ;

} else if (childName.equals("BUTC")) {
nunchuck.setButtonC(value) ;
} else {
print("SEE A CODE DOCTOR - UNRECOGNISED ELEMENT IN NUNCHUCK DATA!") ;
}



} // while
// Add Joystick reading to the queue

nunChuckQueue.add(nunchuck) ;

} // rootName is NUNCHUCK

}


void draw()
{
NunChuckReading reading = (NunChuckReading)nunChuckQueue.poll() ;
if (reading != null) {
println("nunchuck "+reading) ;
}
}


void mousePressed() {
//System.exit(0) ;

}



Arduino Listing


#include <Wire.h>

void setup()
{
Serial.begin(19200) ;
nunchuck_init_with_power();
}

void loop()
{
nunchuck_get_data() ;
nunchuck_print_data() ;

}


/*
* Nunchuck functions -- Talk to a Wii Nunchuck
*
* This library is from the Bionic Arduino course :
* http://todbot.com/blog/bionicarduino/
*
* 2007 Tod E. Kurt, http://todbot.com/blog/
*
* The Wii Nunchuck reading code originally from Windmeadow Labs
* http://www.windmeadow.com/node/42
*/



static uint8_t nunchuck_buf[6]; // array to store nunchuck data,

// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
static void nunchuck_init()
{
Wire.begin(); // join i2c bus as master
Wire.beginTransmission(0x52);// transmit to device 0x52
Wire.send(0x40);// sends memory address
Wire.send(0x00);// sends sent a zero.
Wire.endTransmission();// stop transmitting
}

// General version of nunchuck_init_with_power()beginWithPower().
// Call this first when a Nunchuck is plugged directly into Arduino
static void nunchuck_init_with_power_pins(byte pwrpin, byte gndpin)
{
DDRC |= _BV(pwrpin) | _BV(gndpin); // make outputs
PORTC &=~ _BV(gndpin);
PORTC |= _BV(pwrpin);
delay(100); // wait for things to stabilize

nunchuck_init();
}

// Call this first when a Nunchuck is plugged directly into Arduino
static void nunchuck_init_with_power()
{
nunchuck_init_with_power_pins(PC3,PC2);
}

// Send a request for data to the nunchuck
// was "send_zero()"
static void nunchuck_send_request()
{
Wire.beginTransmission(0x52);// transmit to device 0x52
Wire.send(0x00);// sends one byte
Wire.endTransmission();// stop transmitting
}

// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
static char nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
return x;
}

// Receive data back from the nunchuck,
// returns 1 on successful read. returns 0 on failure
static int nunchuck_get_data()
{
int cnt=0;
Wire.requestFrom (0x52, 6);// request data from nunchuck
while (Wire.available ()) {
// receive byte as an integer
nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive());
cnt++;
}
nunchuck_send_request(); // send request for next data payload
// If we recieved the 6 bytes, then go print them
if (cnt >= 5) {
return 1; // success
}
return 0; //failure
}

// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits. That is why I
// multiply them by 2 * 2
static void nunchuck_print_data()
{
int joy_x_axis = nunchuck_buf[0];
int joy_y_axis = nunchuck_buf[1];
int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;
int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;

int z_button = 0;
int c_button = 0;

// byte nunchuck_buf[5] contains bits for z and c buttons
// it also contains the least significant bits for the accelerometer data
// so we have to check each bit of byte outbuf[5]
if ((nunchuck_buf[5] >> 0) & 1)
z_button = 1;
if ((nunchuck_buf[5] >> 1) & 1)
c_button = 1;

if ((nunchuck_buf[5] >> 2) & 1)
accel_x_axis += 2;
if ((nunchuck_buf[5] >> 3) & 1)
accel_x_axis += 1;

if ((nunchuck_buf[5] >> 4) & 1)
accel_y_axis += 2;
if ((nunchuck_buf[5] >> 5) & 1)
accel_y_axis += 1;

if ((nunchuck_buf[5] >> 6) & 1)
accel_z_axis += 2;
if ((nunchuck_buf[5] >> 7) & 1)
accel_z_axis += 1;

Serial.print("");

Serial.print("");
Serial.print(joy_x_axis,DEC);
Serial.print("
");
Serial.print(joy_y_axis, DEC);
Serial.print("
");

Serial.print("");
Serial.print(accel_x_axis, DEC);
Serial.print("
");
Serial.print(accel_y_axis, DEC);
Serial.print("
");
Serial.print(accel_z_axis, DEC);
Serial.print("
");

Serial.print("");
Serial.print(z_button, DEC);
Serial.print("
") ;
Serial.print(c_button, DEC);
Serial.print("
\r\n"); // newline
}

// returns zbutton state: 1=pressed, 0=notpressed
static int nunchuck_zbutton()
{
return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1; // voodoo
}

// returns zbutton state: 1=pressed, 0=notpressed
static int nunchuck_cbutton()
{
return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1; // voodoo
}

// returns value of x-axis joystick
static int nunchuck_joyx()
{
return nunchuck_buf[0];
}

// returns value of y-axis joystick
static int nunchuck_joyy()
{
return nunchuck_buf[1];
}

// returns value of x-axis accelerometer
static int nunchuck_accelx()
{
return nunchuck_buf[2]; // FIXME: this leaves out 2-bits of the data
}

// returns value of y-axis accelerometer
static int nunchuck_accely()
{
return nunchuck_buf[3]; // FIXME: this leaves out 2-bits of the data
}

// returns value of z-axis accelerometer
static int nunchuck_accelz()
{
return nunchuck_buf[4]; // FIXME: this leaves out 2-bits of the data
}

Friday, 6 February 2009

Arduino and Processing

I've just bought myself a little arduino board! They are cheap - easy to setup and program - and work well with the Processing language.

Infact those smart guys at Arduino have used the open source from Ben Fry's and Casey Reas's original processing Java IDE and have embedded a 'C' compiler which outputs the native code used by the little board. The Processing IDE can used to write Java applications which talk to the Arduino Board via the boards serial interface.

I will put up a demo if time permits - using b e n 's excellent ball of confusion - controlled by an analog joystick