Parallax Mouse Sensor Kit

I'm trying to write a program to work with Parallax's Mouse Sensor kit. I've seen a lot of people trying to do something similar with old mice-I think it would be fantastic to get this to work because then we would have standardized the hardware somewhat.

I've succeeded after a fashion. So long as I make slow, smooth movements it appears to function as desired. However, when I make sudden movements, the sensor is often "tricked" - it will say it isn't moving or is moving in the opposite direction at times. It looks almost like an overflow problem, but when I check the status bits for dy & dx, they're 0s.

When I run the basic stamp program with the sensor hooked up to my Boe-Bot, the performance is much more consistent, so it's not a limitation of the hardware. I also noticed that the basic stamp program seems to be more granular-it looks like it returns something besides a 0, 128, 0r 255; where these are the only values I seem to get when using the arduino.

Datasheets and sample programs can be found at: https://www.parallax.com/StoreSearchResults/tabid/768/List/0/SortField/4/ProductID/677/Default.aspx?txtSearch=mouse+sensor

Here's what I have so far:

#define sclk 5 //Define pin 5 as clock
#define sdio 6 //Define pin 6 as data

//Mouse sensor register addresses
#define CHNG  0x80

byte stat;
byte readx; //Vallue from sensor: 255 = -1, 128 = 1
byte ready; //Vallue from sensor: 255 = -1, 128 = 1
byte quality;

int dx;
int dy;
int x;
int y;

byte WriteNeg(byte data)
{
  pinMode(sdio,OUTPUT);
  for(int i = 0; i < 8; i++)
  {
    digitalWrite(sdio,bitRead(data,7));
    digitalWrite(sclk,LOW);
    delayMicroseconds(50);
    digitalWrite(sclk,HIGH);
    delayMicroseconds(50);
    data = data << 1;
  }
  pinMode(sdio,INPUT);
}

byte ReadNeg()
{
  byte data = 0;
  for(int i = 0; i < 8; i++)
  {
    digitalWrite(sclk,LOW);
    delayMicroseconds(50);
    digitalWrite(sclk,HIGH);
    delayMicroseconds(50);
    bitWrite(data,i,digitalRead(sdio));
  }
  return data;
}

void WriteAddr(byte address, byte data)
{
  WriteNeg(address|0x80);
  WriteNeg(data);
}

int ReadAddr(byte address)
{
  WriteNeg(address);
  delayMicroseconds(100);
  return ReadNeg();
}

void setup()
{
  delay(2000);
  Serial.begin(9600);
  Serial.print("Program Initializing");
  pinMode(sclk,OUTPUT);
  digitalWrite(sclk,HIGH);  
  Serial.print("\nClock pin set high");
  delay(100);
  WriteAddr(0xB1,0x80); //Sets resolution to 500 dpi
  Serial.print("\nResolution set to 500 dpi");
  Serial.print("\nMain program starting\n");
}

void loop()
{
  stat = ReadAddr(0x16);
  if (stat & CHNG != 0)
  {
    readx = ReadAddr(0x03);
    switch (readx)
    {
      case 255:
        dx = -1;
        break;
      case 128:
        dx = 1;
        break;
      case 0:
        dx = 0;
        break;
    }
    x = x + dx;
    Serial.print(dx,DEC);
    Serial.print("\t");
    Serial.print(x,DEC);
    Serial.print("\t");    
    ready = ReadAddr(0x02);
    switch (ready)
    {
      case 255:
        dy = -1;
        break;
      case 128:
        dy = 1;
        break;
      case 0:
        dy = 0;
        break;
    }
    y = y + dy;
    Serial.print(dy,DEC);
    Serial.print("\t");
    Serial.print(y,DEC);
    Serial.print("\t");
    quality = ReadAddr(0x04);
    Serial.print(quality,DEC);
    Serial.print("\t");
    Serial.print(stat,BIN);
    Serial.print("\n");
  }
}

I got it working really well using the Advanced hardware configuration shown in the documentation. Here's the code:

#define sclk 5 //Define pin 5 as clock
#define sdio 6 //Define pin 6 as data

//Mouse sensor register addresses
#define CONF 0x1B
#define LORES 0x80
#define CHNG  0x80
#define OFLOW 0x18
#define NEG 0x80

byte stat;
byte quality;
byte ovfl;
byte readx;
byte ready;

int dx;
int dy;
int x;
int y;

void WriteAddr(byte address, byte data)
{
  pinMode(sdio,OUTPUT);
  shiftOut(sdio,sclk,MSBFIRST,address|0x80);
  shiftOut(sdio,sclk,MSBFIRST,data);
}

int ReadAddr(byte address)
{
  int data;
  pinMode(sdio,OUTPUT);
  shiftOut(sdio,sclk,MSBFIRST,address);
  delayMicroseconds(100);
  pinMode(sdio,INPUT);
  data = shiftIn(sdio,sclk,MSBFIRST);
  return data;
}

void setup()
{
  Serial.begin(9600);
  pinMode(sclk,OUTPUT);
  digitalWrite(sclk,LOW);  
  delay(100);
  WriteAddr(CONF,LORES);
}

void loop()
{
  stat = ReadAddr(0x16);
  if(stat & CHNG == 0)
  {
  } else {
    if(stat & OFLOW)
    {
      ovfl = 10;
    }
    readx = ReadAddr(0x03);
    if(readx & NEG)
    {
      dx = -1*(256-readx);
    } else {
      dx = readx; 
    }
    x = x + dx;
    ready = ReadAddr(0x02);
    if(ready & NEG)
    {
      dy = -1*(256-ready);
    } else {
      dy = ready;
    }
    y = y + dy;
    quality = ReadAddr(0x04);
    Serial.print(dx,DEC);
    Serial.print("\t");
    Serial.print(x,DEC);
    Serial.print("\t");
    Serial.print(dy,DEC);
    Serial.print("\t");
    Serial.print(y,DEC);
    Serial.print("\t");
    Serial.print(quality,DEC);
    if(ovfl > 0)
    {
      ovfl = ovfl - 1;
      Serial.print("\t");
      Serial.print("Overflow");
    }
    Serial.print("\n");
  }
}

hi. i am not very good at programming. i have one of these modules. i just ran this code and it worked really well. Can you explain how each part works so that i can use it on one of my projects. i want to make an omni wheeled robot that i can move around on the floor then it will return to it's original position.

I'm sorry, but I don't have time to explain my code as you have requested. On the upside, you don't really need to understand it to use it (that's the wonderful thing about libraries). I've written a library for this kit which you can download and use. It even comes complete with sample code. It is available for download towards the bottom of the following page: https://sites.google.com/site/mbbackus/robotics/bread-board-bot. Hope this helps. Best of luck with your project.

thanks mate
I have been trying to work this thing out for ages. this is a life saver i will post how my project goes.

Hey. I'm trying to use this kit to measure XY displacement on a flat surface. I'm having a hard understanding the advanced three wire communication setup. Can you please explain how you arranged your jumpers and how you connected the sensor to the actual arduino board?

One last thing, what model arduino board were you using?

Any help you can provide would be great!