Arduino Tutorial: Get Traveled Distance Using ADNS-9800 Laser Mouse Sensor

49,245

29

97

The ADNS-9800 Laser gaming sensor comprises of sensor and VCSEL in a single chip-on-board (COB) package. ADNS-9800 provides enhanced features like programmable frame rate, programmable resolution, configurable sleep and wake up time to suit various PC gamers’ preferences. The advanced class of VCSEL was engineered by PixArt Imaging to provide a laser diode with a single longitudinal and a single transverse mode. This Laser gaming sensor is in 16-pin integrated chip-on-board (COB) package. It is designed to be used with ADNS-6190-002 small form factor (SFF) gaming laser lens to achieve the optimum performance featured in this document. These parts provide a complete and compact navigation system without moving part and laser calibration process is NOT required in the complete mouse form, thus facilitating high volume assembly. The sensor is based on Laser technology, which measures changes in position by optically acquiring sequential surface images (frames) and mathematically determining the direction and magnitude of movement. It contains an Image Acquisition System (IAS), a Digital Signal Processor (DSP), and a four wire serial port. The IAS acquires microscopic surface images via the lens and illumination system. These images are processed by the DSP to determine the direction and distance of motion. The DSP calculates the Δx and Δy relative displacement values. An external microcontroller reads the Δx and Δy information from the sensor serial port. The microcontroller then translates the data into PS2, USB, or RF signals before sending them to the host PC or game console.

In this tutorial You will learn how to connect ADNS-9800 Laser Mouse Sensor to Arduino and Display Traveled Distance (Δx) on 20x4 LCD


You can buy one from there: https://www.tindie.com/products/jkicklighter/adns-9800-optical-laser-sensor/

Step 1: Building Circuit

First You Need to Build Circuit
You have to Connect Your Arduino to ADNS-9800 and LCD Screen
You can download Circuit from there: https://dl.dropboxusercontent.com/s/vcu90sescnt10l2/Laser%20Mouse%20Control.fzz

Step 2: Uploading Code

Now Connect Your Arduino to Computer.
Download Arduino Project at https://dl.dropboxusercontent.com/s/4b3hy0y87f3a67b/Laser%20Mouse%20Sensor%20Code.rar
Then Open it, Select Your Board and Your COM Port and Click Upload Button

NOTE: You have to activate +5V mode first (this tutorial is written for arduino uno (any arduino will work which uses Atmega8 - Atmega16 - Atmega32)), To activate +5V mode you have to cut the three traces on the 3.3V side between the exposed sets of pads, and add three solder bridges to the 5V side of the board (Be careful don't damage board).When you will activate +5V mode and then connect it correctly it will work fine, but remember code that is uploaded doesn't show distance in meters and you have to decrease loop delay to speedup sensor. If you are removing LCD please edit code to display distance that sensor has traveled

Share

    Recommendations

    • Arduino Contest 2019

      Arduino Contest 2019
    • Trash to Treasure

      Trash to Treasure
    • Tape Contest

      Tape Contest

    97 Discussions

    0
    None
    jtloper1

    1 year ago

    For some reason the code won't compile. I hope this is something simple.

    There are pages of console out put but the issue seems to be:

    ------

    exit status 1

    'prog_uchar' does not name a type

    ------

    Full Dump: https://goo.gl/qTx3iX

    Capture.PNG
    0
    None
    SandraW115

    1 year ago

    Hi!

    I'm working on this code now for days but I cant get it to work properly. I want to see my traveled distance in cm in the serial monitor. Is there anyone who got it all working and wants to share his or her conde with me?

    I saw a code down here but since it was posted 3 years ago I can't open it anymore...

    It is for a project for my study, but I am not really good at arduino.

    I tried my best but are almost giving up...

    10247048753049823467394 thanks if you want to help!

    0
    None
    JasonC11

    4 years ago on Introduction

    Hi Gigi - I'm trying to use this to monitor the speed of movement. At first blush everything seems to be working, but xydat[0] seems to always be -1, 0 or 1 instead of a byte showing the distance moved since the last reading so it's really inaccurate unless you're moving really slowly. Any idea what could be causing this?

    17 replies
    0
    None
    wgdalJasonC11

    Reply 4 years ago on Introduction

    Hi GIgi, I am having a similar issue. The counter counts up and down, but is very inaccurate at any speed, say 5'/min. Is there a way to change the resolution of the ADNS-9800?

    Thanks

    0
    None
    JasonC11wgdal

    Reply 4 years ago on Introduction

    You can change the resolution using REG_Configuration_I (http://datasheet.octopart.com/ADNS-9800-Avago-datasheet-10666463.pdf page 29). However, this doesn't appear to solve this issue.

    0
    None
    JasonC11wgdal

    Reply 4 years ago on Introduction

    Hi wgdal - I got it working using Gigi's fix. Where xydat is defined, change it to:

    volatile byte xydat[4];

    int16_t * x = (int16_t *) &xydat[0];

    int16_t * y = (int16_t *) &xydat[2];

    And where xydat is read in UpdatePointers(), change to:

    xydat[0] = (byte)adns_read_reg(REG_Delta_X_L);

    xydat[1] = (byte)adns_read_reg(REG_Delta_X_H);

    xydat[2] = (byte)adns_read_reg(REG_Delta_Y_L);

    xydat[3] = (byte)adns_read_reg(REG_Delta_Y_H);

    Then (*x) and (*y) will contain accurate counts. Make sure you normalize by the CPI to get the distance.

    0
    None
    wgdalJasonC11

    Reply 4 years ago on Introduction

    JasonC11, can you please post your code? I applied Gigi's fix, but still no luck. It appeared to change nothing.

    Thanks in advance

    0
    None
    neaton14JasonC11

    Reply 4 years ago on Introduction

    Hey JasonC11, can you explain the math you're doing on the xydat[0] and xydat[2] in this line? I see the 2.54 so I assume you're going from inches to cm, but I'm not sure where the 200 is coming from along with the FS*1e-6, or 0.1 (1e5*1e-6).

    distancex = float(*x)/200*2.54/(FS*1e-6);

    Any help would be greatly appreciated. Thanks

    0
    None
    JasonC11neaton14

    Reply 4 years ago on Introduction

    He neaton14,

    The 200 comes from the CPI, which is set at line 177. Thus you get the distance count (*x) divided by the CPI to get inches, multiplied by 2.54 to get cm, and divided by (FS*1e-6) to get cm/second.

    Check out p29 of the datasheet (http://datasheet.octopart.com/ADNS-9800-Avago-data... for more information on how to set the CPI.

    I'm not really sure why I set it to 200, but you should be able to tweak it for your application.

    0
    None
    MagdaL6JasonC11

    Reply 3 years ago

    Hi, just a question, What is mean with the FS value u are using? I get many Data from my sensor and i really try hardly to get the traveled way out of it...but i can't get it...

    0
    None
    neaton14JasonC11

    Reply 4 years ago on Introduction

    Thanks for the explanation! Yeah I tweaked the values through trial and error and now I get solid inch & centimeter readings.

    0
    None
    wgdalJasonC11

    Reply 4 years ago on Introduction

    Thanks,, but I can't get your code to work either. It doesn't appear to initialize the ADNS. It only returns 0s on the monitor. Thanks

    0
    None
    neaton14wgdal

    Reply 4 years ago on Introduction

    Make sure the "ncs" pin number matches with your arduino/sensor setup.

    0
    None

    Pardon my ignorance, but does this mean that the code needs to be adjusted to ensure that it's reading from the correct NCS Pin # based upon where you connected the device physically?

    Thanks,

    0
    None

    That's exactly right. I think the "ncs pin" is the SS pin on the ADNS-9800. In this example he connects it to pin 10 on the arduino. If you connected it to, say, pin 6 on the arduino, make sure to change the number in code to 6.

    0
    None

    Cool beans, thanks for the very useful/valuable information. Will be sure to double check that when I get my setup re-connected.

    0
    None
    wgdalneaton14

    Reply 4 years ago on Introduction

    Thanks, That was it. Actually all I need is two output pulses derived from the laser mouse forward and reverse movement, that emulates a rotary encoder. I have a scalable totalizing counter that accepts square wave pulses. I do not need the "y" output. Sounds easy, but I haven't figured it out yet. I am completely new to Arduino and C. Any help would be greatly appreciated.