Loading...
Pages: [1]   Go Down
Author Topic: ADNS5050  (Read 877 times)
0 Members and 1 Guest are viewing this topic.
SEA/PDX/CPH
Offline Offline
Newbie
*
Karma: 0
Posts: 22
having fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Has anyone successfully interfaced one of these (ref http://www.avagotech.com/pages/en/navigation_interface_devices/navigation_sensors/led-based_sensors/adns-5050/) with an Arduino? I've been working off of this old forum post http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1154816099 (nb in French) and the sparkfun code for the 2620 (http://www.sparkfun.com/products/10105) but I'm not having any luck even just getting the ADNS5050 to respond with its PRODUCT_ID.

I've wired it up as shown in the diagram. Not sure why all the capacitors are necessary, but I'm simply following the diagram from the datasheet. Excuse the image too, fritzing isn't being my friend lately. Anything obvious that I'm missing or does anyone have any advice? I'd be happy to post code if it's helpful.
« Last Edit: July 31, 2011, 01:16:32 pm by joshuajnoble » Logged

Netherlands
Offline Offline
Tesla Member
***
Karma: 87
Posts: 9387
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Your first link gives - page not found -  error
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

SEA/PDX/CPH
Offline Offline
Newbie
*
Karma: 0
Posts: 22
having fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Odd, guess the Avago site can't redirect w/o the trailing '/', the link is corrected: http://www.avagotech.com/pages/en/navigation_interface_devices/navigation_sensors/led-based_sensors/adns-5050/
Logged

Netherlands
Offline Offline
Tesla Member
***
Karma: 87
Posts: 9387
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From the link
Quote
Description
The ADNS-5050 is a mainstream, small form factor optical mouse sensor.  It is a user-friendly product with many built-in features and optimized for LED-based corded products.   
The ADNS-5050 is capable of high-speed motion detection – up to 30ips and 8g.  In addition, it has an on-chip oscil-lator and built-in LED driver to minimize external compo-nents. Frame rate is also adjusted internally.

The sensor is programmed via registers through a three-wire SPI interface.

The PDF - http://www.avagotech.com/docs/AV02-1045EN -  shows a schematic how to build a mouse (figure smiley-cool  and has a description of how a read operation should work.

Can you post your code ?

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

SEA/PDX/CPH
Offline Offline
Newbie
*
Karma: 0
Posts: 22
having fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Here's the code. The 3 wire SPI seems to be (unless I misunderstood) the CS pulled low, and then a clock and IO pin. I've set these on 2 and 3. The CS pin, I just set on 4.

Code:
#define SCLK                3
#define SDIO                2

#define PRODUCT_ID          0x00
#define DELTA_Y_REG         0x03
#define DELTA_X_REG         0x04
#define SQUAL_REG           0x05
#define MAXIMUM_PIXEL_REG   0x08
#define MINIMUM_PIXEL_REG   0x0a
#define PIXEL_SUM_REG       0x09
#define PIXEL_DATA_REG      0x0b
#define SHUTTER_UPPER_REG   0x06
#define SHUTTER_LOWER_REG   0x07
#define RESET 0x3a
#define CPI500v 0x00
#define CPI1000v 0x01

const int NCS = 4;

void setup()
{
  Serial.begin(57600);

  pinMode(NCS, OUTPUT);
  digitalWrite(NCS, LOW);

  pinMode(SDIO, OUTPUT);
  pinMode(SCLK, OUTPUT);

  delay(50); //from PD inactive (when NRESET pin is asserted high or write 0x5a to register 0x3a) to valid motion
  sync(); //
  //call reset
  writeReg(RESET, 0x5a);
  delay(50); // From NRESET pull high to valid mo tion, assuming VDD and motion is present.

}

void loop()
{
  delay(100);
  Serial.print(readReg(PRODUCT_ID), DEC); // this should return 0x12 :/
}

//Essentially resets communication to the ADNS5050
void sync()
{
  digitalWrite(SCLK, HIGH);
  delay(1);
  digitalWrite(SCLK, LOW);
  delay(1); 
  digitalWrite(SCLK, HIGH);
  delay(100);
}

//Reads a register from the ADNS5050 sensor. Returns the result to the calling function.
char readReg(char address)
{
  char value=0;
  pinMode(SDIO, OUTPUT); //Make sure the SDIO pin is set as an output.
  digitalWrite(SCLK, HIGH); //Make sure the clock is high.
  address &= 0x7F;    //Make sure the highest bit of the address byte is '0' to indicate a read.

  //Send the Address to the ADNS5050
  for(int address_bit=7; address_bit >=0; address_bit--){
    digitalWrite(SCLK, LOW);  //Lower the clock
    pinMode(SDIO, OUTPUT); //Make sure the SDIO pin is set as an output.
    //If the current bit is a 1, set the SDIO pin. If not, clear the SDIO pin
    if(address & (1<<address_bit)){
      digitalWrite(SDIO, HIGH);
    }
    else{
      digitalWrite(SDIO, LOW);

    }
    delayMicroseconds(10);
    digitalWrite(SCLK, HIGH);
    delayMicroseconds(10);
  }
  delayMicroseconds(120);   //Allow extra time for ADNS5050 to transition the SDIO pin (per datasheet)
  //Make SDIO an input on the microcontroller
  pinMode(SDIO, INPUT); //Make sure the SDIO pin is set as an input.
  digitalWrite(SDIO, HIGH); //Enable the internal pull-up

  //Send value byte
  for(int value_bit=7; value_bit >= 0; value_bit--){
    digitalWrite(SCLK, LOW);  //Lower the clock
    delayMicroseconds(10); //Allow the ADNS5050 to configure the SDIO pin
    digitalWrite(SCLK, HIGH);  //Raise the clock
    delayMicroseconds(10);
    //If the SDIO pin is high, set the current bit in the 'value' variable. If low, leave the value bit default (0).   
    //if((ADNS_PIN & (1<<ADNSSDIO)) == (1<<ADNSSDIO))value|=(1<<value_bit);
    if(digitalRead(SDIO))value |= (1<<value_bit);
  }
  return value;
}

//Writes a value to a register on the ADNS5050.
void writeReg(char address, char value)
{
  pinMode(SDIO, OUTPUT); //Make sure the SDIO pin is set as an output.
  digitalWrite(SCLK, HIGH);          //Make sure the clock is high.
  address |= 0x80;    //the highest bit is '1' to indicate a write.

  //Send Address
    for(int address_bit=7; address_bit >=0; address_bit--){
    digitalWrite(SCLK, LOW); //Lower the clock
    delayMicroseconds(10); //small delay
    //If the current bit is a 1, set the SDIO pin. If not, clear the SDIO pin
    if(address & (1<<address_bit))digitalWrite(SDIO, HIGH);
    else digitalWrite(SDIO, LOW);
    delayMicroseconds(10);
    digitalWrite(SCLK, HIGH);
    delayMicroseconds(10);

  }

  //Send the Value byte to the ADNS5050

    for(int value_bit=7; value_bit >= 0; value_bit--){
    digitalWrite(SCLK, LOW);  //Lower the clock
    //If the current bit is a 1, set the SDIO pin. If not, clear the SDIO pin
    if(value & (1<<value_bit))digitalWrite(SDIO, HIGH);
    else digitalWrite(SDIO, LOW);
    delayMicroseconds(10);
    digitalWrite(SCLK, HIGH);
    delayMicroseconds(10);
  }

}

Logged

SEA/PDX/CPH
Offline Offline
Newbie
*
Karma: 0
Posts: 22
having fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Found another reference for this that I'm going to try to get into Arduino-ready shape. It's Atmega328 code, if anyone is interested: http://servomagazine.com/index.php/magazine/article/july2011_mrroboto
Logged

Germany
Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have worked on A5020 (with SCLK, NCS, SDIO). If your A5050 is similar than maybe I can help you out.
Logged

 -- Nitin

SEA/PDX/CPH
Offline Offline
Newbie
*
Karma: 0
Posts: 22
having fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


thanks nitin29. I'd love to hear any advice you have. I'm not sure if you meant that I should post all my code, but I'm going to go for it anyways. If anything in here looks wrong, I'd love to know about it. Thanks!

Code:
#define SCLK                18
#define SDIO                19

#define PRODUCT_ID          0x00 // should be 0x12
#define PRODUCTID2          0x3e
#define REVISION_ID         0x01
#define DELTA_Y_REG         0x03
#define DELTA_X_REG         0x04
#define SQUAL_REG           0x05
#define MAXIMUM_PIXEL_REG   0x08
#define MINIMUM_PIXEL_REG   0x0a
#define PIXEL_SUM_REG       0x09
#define PIXEL_DATA_REG      0x0b
#define SHUTTER_UPPER_REG   0x06
#define SHUTTER_LOWER_REG   0x07
#define RESET     0x3a
#define CPI500v     0x00
#define CPI1000v     0x01

const int NCS = 4;

void setup()
{
  Serial.begin(57600);

  pinMode(SDIO, OUTPUT);
  pinMode(SCLK, OUTPUT);

  pinMode(NCS, OUTPUT);
  digitalWrite(NCS, LOW);
  delayMicroseconds(2);
  digitalWrite(NCS, HIGH);

  //call reset
 
  ADNS_write(RESET, 0x5a);
  delay(50); // From NRESET pull high to valid mo tion, assuming VDD and motion is present.

}

void loop()
{
  delay(200);
  Serial.println(ADNS_read(PRODUCT_ID), BIN);
}

void ADNS_write(unsigned char addr, unsigned char data) {
  char temp;
  int n;

  digitalWrite(NCS, LOW);//nADNSCS = 0; // select the chip

  temp = addr;
  digitalWrite(SCLK, LOW); // start clock low
  pinMode(SDIO, OUTPUT); // set data line for output
  for (n=0; n<8; n++) {
    digitalWrite(SCLK, LOW);
    pinMode(SDIO, OUTPUT);
    delayMicroseconds(1);
    if (temp & 0x80)
      digitalWrite(SDIO, HIGH);
    else
      digitalWrite(SDIO, LOW);
    temp = (temp << 1);
    digitalWrite(SCLK, HIGH);
    delayMicroseconds(1);//delayMicroseconds(1); // short clock pulse
  }
  temp = data;
  for (n=0; n<8; n++) {
    digitalWrite(SCLK, LOW);
    delayMicroseconds(1);
    if (temp & 0x80)
      digitalWrite(SDIO, HIGH);
    else
      digitalWrite(SDIO, LOW);
    temp = (temp << 1);
    digitalWrite(SCLK, HIGH);
    delayMicroseconds(1); // short clock pulse
  }
  delayMicroseconds(20);
  digitalWrite(NCS, HIGH); // de-select the chip
}

byte ADNS_read(unsigned char addr) {
  byte temp;
  int n;

  digitalWrite(NCS, LOW); // select the chip
  temp = addr;
  digitalWrite(SCLK, OUTPUT); // start clock low
  pinMode(SDIO, OUTPUT); // set data line for output
  for (n=0; n<8; n++) {

    digitalWrite(SCLK, LOW);
    pinMode(SDIO, OUTPUT);
    if (temp & 0x80) {
      digitalWrite(SDIO, HIGH);
    }
    else {
      digitalWrite(SDIO, LOW);
    }
    temp = (temp << 1);
    delayMicroseconds(1);
    digitalWrite(SCLK, HIGH);
    delayMicroseconds(1); // short clock pulse
  }
 
  temp = 0; // This is a read, switch to input
  pinMode(SDIO, INPUT);
  delayMicroseconds(4);
  for (n=0; n<8; n++) { // read back the data
    digitalWrite(SCLK, LOW);
    delayMicroseconds(1);
    if(digitalRead(SDIO)) { // got a '1'
      temp |= 0x1;
    }
    temp = (temp << 1); // shift left
    digitalWrite(SCLK, HIGH);
    delayMicroseconds(1);
  }
 
  digitalWrite(NCS, HIGH); // de-select the chip
  return temp;
}


I'm not able to get the chip to respond with anything at the moment, very frustrating as I've followed the data sheet very precisely.
Logged

SEA/PDX/CPH
Offline Offline
Newbie
*
Karma: 0
Posts: 22
having fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Came back to this and realized that I forgot to pull down the reset pin. Embarrassing, thanks for not embarrassing me futher by commenting on it smiley There were also some timing and read issues that I sorted out. Here's the code, and I'll put it wrapped nicely up on github. Big thanks to robtillaart for the copy/paste and internet tips.

Code:
#define SCLK                18
#define SDIO                19
#define RESET               3
#define NCS                  4

#define PRODUCT_ID          0x00 // should be 0x12
#define PRODUCTID2          0x3e
#define REVISION_ID         0x01
#define DELTA_Y_REG         0x03
#define DELTA_X_REG         0x04
#define SQUAL_REG           0x05
#define MAXIMUM_PIXEL_REG   0x08
#define MINIMUM_PIXEL_REG   0x0a
#define PIXEL_SUM_REG       0x09
#define PIXEL_DATA_REG      0x0b
#define SHUTTER_UPPER_REG   0x06
#define SHUTTER_LOWER_REG   0x07
#define RESET    0x3a
#define CPI500v    0x00
#define CPI1000v    0x01

#define NUM_PIXELS          361

byte pix[360];

void setup()
{
  Serial.begin(57600);

  pinMode(SDIO, OUTPUT);
  pinMode(SCLK, OUTPUT);

  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, LOW);
  
  sync();
  
  ADNS_write(RESET, 0x5a);
  delay(50); // From NRESET pull high to valid mo tion, assuming VDD and motion is present.

}

void loop()
{
  digitalWrite(RESET, LOW);
  delay(50);
  Serial.println(ADNS_read(MINIMUM_PIXEL_REG), BIN);
  //pixelGrab();
}

void sync() {
  pinMode(NCS, OUTPUT);
  digitalWrite(NCS, LOW);
  delayMicroseconds(2);
  digitalWrite(NCS, HIGH);
}

void ADNS_write(unsigned char addr, unsigned char data) {
  char temp;
  int n;

  digitalWrite(NCS, LOW);//nADNSCS = 0; // select the chip

  temp = addr;
  digitalWrite(SCLK, LOW);//SCK = 0; // start clock low
  pinMode(SDIO, OUTPUT);//DATA_OUT; // set data line for output
  for (n=0; n<8; n++) {
    digitalWrite(SCLK, LOW);//SCK = 0;
    pinMode(SDIO, OUTPUT);
    delayMicroseconds(1);
    if (temp & 0x80)
      digitalWrite(SDIO, HIGH);//SDOUT = 1;
    else
      digitalWrite(SDIO, LOW);//SDOUT = 0;
    temp = (temp << 1);
    digitalWrite(SCLK, HIGH);//SCK = 1;
    delayMicroseconds(1);//delayMicroseconds(1); // short clock pulse
  }
  temp = data;
  for (n=0; n<8; n++) {
    digitalWrite(SCLK, LOW);//SCK = 0;
    delayMicroseconds(1);
    if (temp & 0x80)
      digitalWrite(SDIO, HIGH);//SDOUT = 1;
    else
      digitalWrite(SDIO, LOW);//SDOUT = 0;
    temp = (temp << 1);
    digitalWrite(SCLK, HIGH);//SCK = 1;
    delayMicroseconds(1); // short clock pulse
  }
  delayMicroseconds(20);
  digitalWrite(NCS, HIGH);//nADNSCS = 1; // de-select the chip
}

byte ADNS_read(unsigned char addr) {
  byte temp;
  int n;

  digitalWrite(NCS, LOW);//nADNSCS = 0; // select the chip
  temp = addr;
  digitalWrite(SCLK, OUTPUT); //SCK = 0; // start clock low
  pinMode(SDIO, OUTPUT); //DATA_OUT; // set data line for output
  for (n=0; n<8; n++) {

    digitalWrite(SCLK, LOW);//SCK = 0;
    pinMode(SDIO, OUTPUT); //DATA_OUT;
    if (temp & 0x80) {
      digitalWrite(SDIO, HIGH);//SDOUT = 1;
    }
    else {
      digitalWrite(SDIO, LOW);//SDOUT = 0;
    }
    temp = (temp << 1);
    delayMicroseconds(1);
    digitalWrite(SCLK, HIGH); //SCK = 1;
    delayMicroseconds(1); // short clock pulse
  }
  
  temp = 0; // This is a read, switch to input
  pinMode(SDIO, INPUT); //DATA_IN;
  for (n=0; n<8; n++) { // read back the data
    digitalWrite(SCLK, LOW);
    if(digitalRead(SDIO)) {// got a '1'
      temp |= 0x1;
    }
    if( n != 7) temp = (temp << 1); // shift left
    digitalWrite(SCLK, HIGH);
  }
  
  digitalWrite(NCS, HIGH);// de-select the chip
  return temp;
}

void pixelGrab()
{
  
  int grabCount = 0;
  while( grabCount < NUM_PIXELS )
  {
    pix[grabCount] = ADNS_read(PIXEL_DATA_REG);
    grabCount++;
  }
  
}
« Last Edit: August 20, 2011, 05:58:13 am by joshuajnoble » Logged

Pages: [1]   Go Up
Print
 
Jump to: