import java.io.*; import gnu.io.*; /** * Interface to 5DT Glove. The glove must be connected to a serial port or serial to USB adapter. * @author Michael Lones 19/04/2010 */ public class GloveRecorder { RXTXPort port = null; // connection to the glove InputStream in; // data received from the glove RecordThread recordThread; int currTime; /** * Connects to glove and copies data to file specified as first argument over the duration * specified by the second argument. * @param args filename duration_in_seconds */ public static void main(String[] args) { GloveRecorder recorder = new GloveRecorder(); if(recorder.connect()) try { recorder.record(new File(args[0]), Integer.parseInt(args[1])); } catch (IOException e) { e.printStackTrace(); } } /** * Creates a connection to the glove. It is assumed that the glove is connected to * COM5 under Windows or /dev/tty.usbserial on a Mac. */ public boolean connect() { // get port name String portName; String osname = System.getProperty("os.name"); if(osname.startsWith("Mac")) portName = "/dev/tty.usbserial"; else if(osname.startsWith("Windows")) portName = "COM5"; else { System.err.println("Glove connection failed: no default port name for operating system"); return false; } // connect to serial port try { port = new RXTXPort(portName); } catch(PortInUseException piuE) { System.err.println("Glove connection failed: serial port "+portName+" in use or does not exist"); return false; } // set up communication protocol try { port.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch (UnsupportedCommOperationException ucoE) { System.err.println(ucoE); System.err.println("Glove connection failed: could not configure serial port"); System.err.println("Please ensure that serial port driver is up to date"); return false; } // get input stream for serial port in = port.getInputStream(); return true; } /** * Thread for copying data from the serial port to a specified file */ class RecordThread extends Thread { PrintWriter writer; BufferedInputStream buffer; boolean stop; long ltime; public RecordThread(File destination, int time) throws IOException { writer = new PrintWriter(new FileWriter(destination)); buffer = new BufferedInputStream(in); ltime = time*1000; stop = false; } public void run() { long startTime = System.currentTimeMillis(); int data, value, s; boolean valid, fullByte; int[] packet = new int[19]; try { while(!stop && System.currentTimeMillis() < startTime+ltime) { valid = false; data = buffer.read(); if(data==0x3c) { // check for start character valid = true; packet[0] = buffer.read(); // read glove type packet[1] = buffer.read(); // read glove version fullByte = true; for(s=2; s<18; s++) { // read sensor values if(fullByte) { // do this when reading a full byte followed by a nibble value = buffer.read(); // read first 8 bits of sensor value value = value<<4; // shift along to make room for the other 4 bits data = buffer.read(); // read next 8 bits from stream value = value | data>>4; // copy 4 bits from this to complete the 12 bit sensor value packet[s] = value; } else { // and this when reading a nibble followed by a byte value = data<<8; // shift the 4 bits already loaded during reading of previous sensor value value = value & 0xFFF; // discard the 4 bits we don't want data = buffer.read(); // read the next 8 bits value = value | data; // and put them in front of the existing 4 bits packet[s] = value; } fullByte = !fullByte; } packet[18] = buffer.read(); // read checksum if(buffer.read()==0x3e) // check for footer valid = valid && true; } if(valid) { // save packet to disk for(int p: packet) { writer.write(""+p+'\t'); } writer.println(); writer.flush(); } } writer.flush(); writer.close(); } // note that PrintWriter does not throw exceptions // use writer.checkError() to check for write errors catch (IOException e) { e.printStackTrace(); } } } /** * Copies data from the glove to the specified file for the specified period. */ public void record(File destination, int time) throws IOException { currTime = time; (recordThread = new RecordThread(destination, time)).start(); } /** * Spawns a recording thread and starts copying glove data to a file. */ public void startRecording(File destination) throws IOException { (recordThread = new RecordThread(destination, Integer.MAX_VALUE)).start(); } /** * Stops the recording thread. */ public void stopRecording() { if(recordThread!=null) { recordThread.stop = true; while(recordThread.isAlive()) { try { Thread.sleep(100); } catch (InterruptedException e) {} } } } }