Shop OBEX P1 Docs P2 Docs Learn Events
Mouse Sensor Kit — Parallax Forums

Mouse Sensor Kit

mbackusmbackus Posts: 4
edited 2012-09-30 13:50 in Accessories
I'm trying to write an Arduino 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 the Mouse Sensor Kit product page

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");
  }
}

Comments

  • Martin_HMartin_H Posts: 4,051
    edited 2012-09-28 11:40
    Just a guess, but I think the bit banging inverted serial I/O is the problem. You might have an interrupt occurring and throwing off the timing or something similar. I've found the mouse sensor worked better when I put it into harvest power from clock mode and drove the clock using a transistor as described in the documentation. Since the transistor acts as an invertor, you can use standard serial commands and sidestep problems with bit banging.
  • mbackusmbackus Posts: 4
    edited 2012-09-28 22:42
    Were you using an Arduino. I tried that but the sample program uses an argument in the Shiftin command that doesn't exist in the Arduino programming language: MSBPOST. If you did use an Arduino, what did you do to get around this?
  • Martin_HMartin_H Posts: 4,051
    edited 2012-09-29 04:20
    I haven't used the mouse sensor with the Arduino, but I have ported other PBasic code to the Arduino as I own both MCU's.

    I would try MSBFIRST which matches the bit order and sampling bits after the clock is normal serial behavior.

    I've used the mouse sensor with my Basic Stamp, but I would be interested in getting this working to increase my options.
  • mbackusmbackus Posts: 4
    edited 2012-09-29 22:05
    I tried your suggestion. I tested the circuit on my Boe-bot to make sure I have everything working properly. Then I put it on my Arduino. Unfortunately, no matter which register I read, all I get is "11111111"

    Here's my code:
    #define sclk 5 //Define pin 5 as clock
    #define sdio 6 //Define pin 6 as data
    
    //Mouse sensor register addresses
    #define DY 0x02
    #define QLTY 0x04
    #define STAT 0x16
    #define CONF 0x1B
    
    #define LORES 0x80
    #define CHNG  0x80
    #define OFLOW 0x18
    #define NEG 0x80
    
    byte stat;
    byte dx;
    byte dy;
    byte quality;
    byte ovfl;
    
    int x;
    int y;
    
    void WriteAddr(byte address, byte data)
    {
      shiftOut(sdio,sclk,MSBFIRST,address|0x80);
      shiftOut(sdio,sclk,MSBFIRST,data);
    }
    
    int ReadAddr(byte address)
    {
      int data;
      shiftOut(sdio,sclk,MSBFIRST,address);
      pinMode(sdio,INPUT);
      delayMicroseconds(100);
      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);
      dx = ReadAddr(0x03);
      dy = ReadAddr(0x02);
      quality = ReadAddr(0x04);  
      Serial.println(dx,BIN);
    }
    
  • Martin_HMartin_H Posts: 4,051
    edited 2012-09-30 09:04
    I did a line for line port of the Parallax sample to C and got the exact same problem. This is really odd.

    I'm going to try the separate power and clock mode to see if I get your initial problem.
  • mbackusmbackus Posts: 4
    edited 2012-09-30 11:55
    I got it working, and it's working really well. I forgot to set the data line's pinmode to output prior to writing after the first read. Here's my 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");
      }
    }
    
  • Martin_HMartin_H Posts: 4,051
    edited 2012-09-30 13:50
    Glad to hear it. I'll bet I have a similar problem because I think PBASIC is a little more liberal with setting pin modes based upon the command used.
Sign In or Register to comment.