Graphing the x-y coordinates of the mouse

I've found this really cool site Interfacing an optical mouse sensor to your Arduino on interfacing an Arduino to an optical mouse to read out x-y readings from it. I've done it, and it's working nicely.

Then I was thinking, 'Why not plot all this to become a graph?' and I came across Processing.

I am aware that Processing has an example named 'MouseSignal'

This example is the EXACT thing that I want to write with Processing. But, the only change is that, I want to use the x-y coordinates from the mouse that is attached to the Arduino and ask Processing to generate a 'real-time' graph of the coordinate.

I tried using this http://www.diymaker.com/realtime-arduino-ad-channel-graph-plotting/ and thishttp://www.glacialwanderer.com/hobbyrobotics/?p=261 as a start, but I came across a problem. Regarding the Serial.list. All my USB ports on my laptop is detected as COM3 by both Arduino and Processing. So there's a clash. There is no clear way for me to import the data from the serial output. It's either I run Arduino and get only numbers printed out on it's serial monitor, or a blank black window from Processing.

Any help would be appreciated. Thanks!

PS. It's an Arduino Duemilanove if that's any help.
PPS. If there is any other method, that would help too.

There can only be one connection on each end of a serial port. The Arduino is on one end. The other end can be connected to by the Serial Monitor OR by Processing, but not both.

If you are not getting Processing to plot data read from the serial port, it is likely that the problem lies in the way that Processing is reading the data, or in how the Arduino is writing the data.

Without seeing any code, though, it's hard to help you.

The Arduino code goes like this (this is the one from the 'Interfacing an optical mouse sensor to your Arduino' site)

// This example reads out the PixArt PAN3101 Optical Navigation Sensor
// It's used in many cheap optical mouses.
//
// For support for the Agilent ADNS-2051, ADNS-2083 or ADNS-2610, move
// the files for your mouse to the folder with the OptiMouse files.
// Then uncomment the right header files and object instances below.
//
// The Arduino will keep track of a (x, y) coordinate by increasing
// or decreasing the x and y variables by dx and respectively dy.
// Every 128th sample it reports the current (x, y) over the Serial.
//
// Written by Martijn The -> post [at] martijnthe.nl
// Tutorial: http://www.martijnthe.nl/optimouse/
// Based on the sketches by Beno[ch65533]t Rousseau

#include "PAN3101.h"
// #include "ADNS2051.h"
// #include "ADNS2610.h"
// #include "ADNS2083.h"

#define SCLK 2                            // Serial clock pin on the Arduino
#define SDIO 4                            // Serial data (I/O) pin on the Arduino (change: pin 3 to 4)

PAN3101 Optical1 = PAN3101(SCLK, SDIO);   // Create an instance of the PAN3101 object
// ADNS2051 Optical1 = ADNS2051(SCLK, SDIO);
// ADNS2610 Optical1 = ADNS2610(SCLK, SDIO);
// ADNS2083 Optical1 = ADNS2083(SCLK, SDIO);

signed long x = 0;                        // Variables for our 'cursor'
signed long y = 0;                        //

int c = 0;                                // Counter variable for coordinate reporting

void setup()
{
  Serial.begin(38400);
  Optical1.begin();                       // Resync (not really necessary?)
}

void loop()
{

//  The status commands are available only for the PAN3101 and the ADNS2051:

Optical1.updateStatus();                // Get the latest motion status
  if (Optical1.motion())                  // If the 'Motion' status bit is set,
  {

    x += Optical1.dx();                   // Read the dX register and in/decrease X with that value
    y += Optical1.dy();                   // Same thing for dY register.....

  }
  
  if (c++ & 0x80)
  {                                       // Report the coordinates once in a while...
    Serial.print("x=");
    Serial.print(x, DEC);
    Serial.print(" y=");
    Serial.print(y, DEC);
    Serial.println();
    c = 0;                                // Reset the report counter
  }
}
o

As for the Processing code, the code below is from Hobby Robotics » Realtime Graphing of Accelerometer/Gyroscope Data. It'll serve as the basis for my final code.


Sorry for the double posting. Ran out of characters

Anyway, here's the Processing code. It'll serve as a basis for my final one

// Maurice Ribble 
// 6-28-2009
// http://www.glacialwanderer.com/hobbyrobotics

// This takes data off the serial port and graphs it.
// There is an option to log this data to a file.

// I wrote an arduino app that sends data in the format expected by this app.
// The arduino app sends accelerometer and gyroscope data.

import processing.serial.*;

// Globals
int g_winW             = 820;   // Window Width
int g_winH             = 600;   // Window Height
boolean g_dumpToFile   = true;  // Dumps data to c:\\output.txt in a comma seperated format (easy to import into Excel)
boolean g_enableFilter = true;  // Enables simple filter to help smooth out data.

cDataArray g_xAccel    = new cDataArray(200);
cDataArray g_yAccel    = new cDataArray(200);
cDataArray g_zAccel    = new cDataArray(200);
cDataArray g_vRef      = new cDataArray(200);
cDataArray g_xRate     = new cDataArray(200);
cDataArray g_yRate     = new cDataArray(200);
cGraph g_graph         = new cGraph(10, 190, 800, 400);
Serial g_serial;
PFont  g_font;

void setup()
{
  size(g_winW, g_winH, P2D);

  println(Serial.list());
  g_serial = new Serial(this, Serial.list()[0], 38400, 'N', 8, 1.0);
  g_font = loadFont("ArialMT-20.vlw");
  textFont(g_font, 20);
  
  // This draws the graph key info
  strokeWeight(1.5);
  stroke(255, 0, 0);     line(20, 420, 35, 420);
  stroke(0, 255, 0);     line(20, 440, 35, 440);
  stroke(0, 0, 255);     line(20, 460, 35, 460);
  stroke(255, 255, 0);   line(20, 480, 35, 480);
  stroke(255, 0, 255);   line(20, 500, 35, 500);
  stroke(0, 255, 255);   line(20, 520, 35, 520);
  fill(0, 0, 0);
  text("xAccel", 40, 430);
  text("yAccel", 40, 450);
  text("zAccel", 40, 470);
  text("vRef", 40, 490);
  text("xRate", 40, 510);
  text("yRate", 40, 530);
  
  if (g_dumpToFile)
  {
    // This clears deletes the old file each time the app restarts
    byte[] tmpChars = {'\r', '\n'};
    saveBytes("c:\\output.txt", tmpChars);
  }
}

void draw()
{
  // We need to read in all the avilable data so graphing doesn't lag behind
  while (g_serial.available() >= 2*6+2)
  {
    processSerialData();
  }

  strokeWeight(1);
  fill(255, 255, 255);
  g_graph.drawGraphBox();
  
  strokeWeight(1.5);
  stroke(255, 0, 0);
  g_graph.drawLine(g_xAccel, 0, 1024);
  stroke(0, 255, 0);
  g_graph.drawLine(g_yAccel, 0, 1024);
  stroke(0, 0, 255);
  g_graph.drawLine(g_zAccel, 0, 1024);
  stroke(255, 255, 0);
  g_graph.drawLine(g_vRef, 0, 1024);
  stroke(255, 0, 255);
  g_graph.drawLine(g_xRate, 0, 1024);
  stroke(0, 255, 255);
  g_graph.drawLine(g_yRate, 0, 1024);
}

// This reads in one set of the data from the serial port
void processSerialData()
{
  int inByte = 0;
  int curMatchPos = 0;
  int[] intBuf = new int[2];

  intBuf[0] = 0xAD;
  intBuf[1] = 0xDE;
  
  while (g_serial.available() < 2); // Loop until we have enough bytes
  inByte = g_serial.read();
  
  // This while look looks for two bytes sent by the client 0xDEAD
  // This allows us to resync the server and client if they ever
  // loose sync.  In my testing I haven't seen them loose sync so
  // this could be removed if you need to, but it is a good way to
  // prevent catastrophic failure.
  while(curMatchPos < 2)
  {
    if (inByte == intBuf[curMatchPos])
    {
      ++curMatchPos;
      
      if (curMatchPos == 2)
        break;
    
      while (g_serial.available() < 2); // Loop until we have enough bytes
      inByte = g_serial.read();
    }
    else
    {
      if (curMatchPos == 0)
      {
        while (g_serial.available() < 2); // Loop until we have enough bytes
        inByte = g_serial.read();
      }
      else
      {
        curMatchPos = 0;
      }
    }
  }
  
  while (g_serial.available() < 2*6);  // Loop until we have a full set of data

  // This reads in one set of data
  {
    byte[] inBuf = new byte[2];
    int xAccel, yAccel, zAccel, vRef, xRate, yRate;
  
    g_serial.readBytes(inBuf);
    // Had to do some type conversion since Java doesn't support unsigned bytes
    xAccel = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
    g_serial.readBytes(inBuf);
    yAccel = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
    g_serial.readBytes(inBuf);
    zAccel = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
    g_serial.readBytes(inBuf);
    vRef   = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
    g_serial.readBytes(inBuf);
    xRate  = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
    g_serial.readBytes(inBuf);
    yRate  = ((int)(inBuf[1]&0xFF) << 8) + ((int)(inBuf[0]&0xFF) << 0);
    
    g_xAccel.addVal(xAccel);
    g_yAccel.addVal(yAccel);
    g_zAccel.addVal(zAccel);
    g_vRef.addVal(vRef);
    g_xRate.addVal(xRate);
    g_yRate.addVal(yRate);

    if (g_dumpToFile)  // Dump data to a file if needed
    {
      String tempStr;
      tempStr = xAccel + "," + yAccel + "," + zAccel + "," + vRef + "," + xRate + "," + yRate + "\r\n";
      FileWriter file;

      try  
      {  
        file = new FileWriter("c:\\output.txt", true); //bool tells to append
        file.write(tempStr, 0, tempStr.length()); //(string, start char, end char)
        file.close();
      }  
      catch(Exception e)  
      {  
        println("Error: Can't open file!");
      }
    }

    /*
    print(xAccel);  print(" ");   print(yAccel);   print(" ");    print(zAccel);     print(" ");
    print(vRef);    print(" ");   print(xRate);    print(" ");    println(yRate);
    */
  }
}

// This class helps mangage the arrays of data I need to keep around for graphing.
class cDataArray
{
  float[] m_data;
  int m_maxSize;
  int m_startIndex = 0;
  int m_endIndex = 0;
  int m_curSize;
  
  cDataArray(int maxSize)
  {
    m_maxSize = maxSize;
    m_data = new float[maxSize];
  }
  
  void addVal(float val)
  {
    
    if (g_enableFilter && (m_curSize != 0))
    {
      int indx;
      
      if (m_endIndex == 0)
        indx = m_maxSize-1;
      else
        indx = m_endIndex - 1;
      
      m_data[m_endIndex] = getVal(indx)*.5 + val*.5;
    }
    else
    {
      m_data[m_endIndex] = val;
    }
    
    m_endIndex = (m_endIndex+1)%m_maxSize;
    if (m_curSize == m_maxSize)
    {
      m_startIndex = (m_startIndex+1)%m_maxSize;
    }
    else
    {
      m_curSize++;
    }
  }
  
  float getVal(int index)
  {
    return m_data[(m_startIndex+index)%m_maxSize];
  }
  
  int getCurSize()
  {
    return m_curSize;
  }
  
  int getMaxSize()
  {
    return m_maxSize;
  }
}

// This class takes the data and helps graph it
class cGraph
{
  float m_gWidth, m_gHeight;
  float m_gLeft, m_gBottom, m_gRight, m_gTop;
  
  cGraph(float x, float y, float w, float h)
  {
    m_gWidth     = w;
    m_gHeight    = h;
    m_gLeft      = x;
    m_gBottom    = g_winH - y;
    m_gRight     = x + w;
    m_gTop       = g_winH - y - h;
  }
  
  void drawGraphBox()
  {
    stroke(0, 0, 0);
    rectMode(CORNERS);
    rect(m_gLeft, m_gBottom, m_gRight, m_gTop);
  }
  
  void drawLine(cDataArray data, float minRange, float maxRange)
  {
    float graphMultX = m_gWidth/data.getMaxSize();
    float graphMultY = m_gHeight/(maxRange-minRange);
    
    for(int i=0; i<data.getCurSize()-1; ++i)
    {
      float x0 = i*graphMultX+m_gLeft;
      float y0 = m_gBottom-((data.getVal(i)-minRange)*graphMultY);
      float x1 = (i+1)*graphMultX+m_gLeft;
      float y1 = m_gBottom-((data.getVal(i+1)-minRange)*graphMultY);
      line(x0, y0, x1, y1);
    }
  }
}

Though however, I don't seem to get past line 34 g_serial = new Serial(this, Serial.list()[0], 115200, 'N', 8, 1.0);

If I open up the Serial Monitor on Arduino 1st, I get an 'Error inside Serial.()

If I play the Processing code 1st, I'll get a 'Serial COM3 already in use' on Arduino's serial monitor and it won't display me any coordinates from the mouse

If I open up the Serial Monitor on Arduino 1st, I get an 'Error inside Serial.()

If I play the Processing code 1st, I'll get a 'Serial COM3 already in use' on Arduino's serial monitor and it won't display me any coordinates from the mouse

This is to be expected. There can only be one application bound to the serial port on the PC end of the connection. If it's Processing, it can't be the Serial monitor. If it's the Serial Monitor, it can't be Processing.

Though however, I don't seem to get past line 34

Ever? Or only if you open the Serial Monitor first?

The code to read the serial data in Processing does not begin to match the data being sent by the Arduino.

For now, don't try to do anything with the data. If there is one or more bytes available, simply print the byte that was read. Get a sense of the data that is being sent.

You are currently trying to extract x, y, and z acceleration data as well as three more values from a stream that only contains x and y position information.

This is to be expected. There can only be one application bound to the serial port on the PC end of the connection. If it's Processing, it can't be the Serial monitor. If it's the Serial Monitor, it can't be Processing.

Noted. But how do I get around this 'problem'?

On another note, are there 'specific' steps to run Processing and open up the Serial Monitor?

Because like I mentioned earlier, if the Serial Monitor is run first, I can't get past line 34. And if Processing is played 1st, I do get a window, but nothing from the Serial Monitor.

OR is it that, Processing is meant to give me the x-y coordinate in graph form (assuming I get the Processing code correct) and that means I cannot get the reading from the Serial Monitor anymore?

If this is the case, that I probably know what's the problem. Like you mentioned, the Processing code is extracting x,y and z values but the mouse is only giving out x and y values.

Ever? Or only if you open the Serial Monitor first?

Only if I open the Serial Monitor first.

But how do I get around this 'problem'?

You can't. It's the nature of serial communications.

On another note, are there 'specific' steps to run Processing and open up the Serial Monitor?

Just one. Don't.

OR is it that, Processing is meant to give me the x-y coordinate in graph form (assuming I get the Processing code correct) and that means I cannot get the reading from the Serial Monitor anymore?

This is the case. When Processing is running, though, the bottom part of the IDE shows messages that the application has written using println(). So, you can see what was read from the serial port by using println().