Skip to main content

Conversion of cheap optical mouse to robot odometer

For a small robot project I'm working on I needed a way to measure the robot's progress across the floor. There are various possibilities, such as: use stepper motors (expensive and am recycling some old continuous run servos), add an encoder to the wheels (would need to go buy some parts for that), or use the optical sensor for a mouse.

I had a really old PS/2 optical mouse lying around which contains an MCS-12085 optical sensor that has a rather simple serial interface suitable for connection to a microcontroller. Inside there are two separate areas of components. On the right in the picture above is the PS/2 interface chips and four nice extras that I desoldered for later use (three microswitches and a quadrature encoder). On the left is the red LED that illuminates the surface and the 8 pin square MCS-12085 that has the camera.

The only description of the chip was for a related optical sensor, the MCS-12086. The difference between the two appears to be that the MCS-12085 requires an external oscillator. A quick comparison of one of the designs in the datasheet and the PCB reveals the simple circuit that runs the chip:

Here's a marked up picture of the mouse internals:
The reverse side shows that there's a nice clean separation between the optical sensor side and the PS/2 interface.
So, after taking a hacksaw to the PCB and case, exposing some copper tracks with sand-paper and drilling four holes for +5V, GND, SDIO and SCLK it was possible to attach a small piece of the PS/2 cable and some connecting pins to have a stand-alone optical sensor unit for my robot.
Then it's just a question of software. For this project I'm using an Arduino Uno which can easily supply the 5V that the sensor needs and two digital pins can be used to generate the clock and I/O signals to read the movement of the sensor. I've created a small Arduino code module called mcs12085 that reads the delta-X and delta-Y values from the sensor as it moves.
Each call to mcs12085_dx() and mcs12085_dy() gives the distance the sensor has moved in the X and Y directions in dots with the range -128 to 127. Note that the sensor has a default accuracy of 1,000 dpi so it will overflow in either direction if the sensor moves more than 3.2mm in any direction.
The code uses one digital pin to act as the clock and generates the relevant clock signal, and another pin to read and write from the sensor.
Before I dismantled it I used a Salae Logic analyzer to observe what the PS/2 interface chip was doing to communicate with the sensor. Here's a screen shot of the complete cycle. The top shows the clock signal and the bottom the data.
It clocks in 8 bits of data corresponding to 0x02 (this is the read DX register command), pauses and reads out 8 bits (in this example the read bits were all 0). Then it clocks in 0x03 (the read DY register command), pauses and reads out 8 bits.
More details of the commands possible are in this document. At some point I'll add some of them to the project.


x said…
The ADNS 2060 looks like an equivalent part to the MCS 12085:
Thanks for that Ron. It looks similar although the commands seem to be slightly different (e.g. read delta X is 0x42 on that device and 0x02 on the one I have).

Zaid Pirwani said…
I would love to see these in action on a bot, measuring distance travelled...

I myself have been thinking about doing something like this for long [I have gathered about 4 old mice for the purpose]... maybe now I will do it.... thanks for the simple explanation and code example.
Unknown said…
What is the max speed that the sensor can track?

I had a similar idea and just used software to track "raw mouse" movements - but once the mouse was moving faster then 4 (maybe it was 8) MPH it couldn't keep up any longer. I was looking for a solution to track at least 25mph and was hopeful for something up to 30+ so I abandoned the approach.

Nice write up!

Anonymous said…
By the way, you seem to have uploaded your mcs-12085.h with the same text as your .cpp file on Github.
Thanks for pointing that out John. Bizarre situation, but I've pushed the correct file to github now.
aodhan said…
I hacked apart an old ps2 mouse I had lying around and tried to get your hack up and running. I wasn't getting anything useful from the mouse until I added a delay of 100ms between "mcs12085_dx()" calls. I am now getting meaningful data from the mouse, however this delay means I can only get 10 updates a second from the mouse. Any thoughts on speeding this up, or is this delay due to the crunch time it takes the mouse to calculate its dx,dy movements?
Unknown said…
I like this and I wana try this ASAP.... But I would like to know the commands? For example how were u able to differentiate between ADNS2620 and MCS 12085 in ur comments??
Anonymous said…
@aodhan I found out in the data sheet that the chip needs a small delay to complete the setup (~40 ms). You can try 100 ms just to be safe. After that you should be able to poll it at the full 1500 fps. I was able to run it at 100 fps without any problems.

I have uploaded my code here:

Thanks to John Graham-Cumming for providing an excellent library!
Rick Bruderick said…
Thanks for sharing this, John!

I've found a few optical mice to hack, but none with the MCS-12085/6 chip.
Instead, I've found the MX8733 and MX8731A chips.…d-SOC-mouse/MX8733_Spec_V1.2.pdf…min/Product20/MX8731 SPEC V1_1.pdf
They are PS2 and seem quite like the MCS-12085/6. But when I connect them to the Arduino UNO and run your code, the x and y always equal -1. I don't have a scope to look at the DATA and CLK signals.
Did you ever just see -1 as the x and y outputs? Any clue as to what I'm not doing right?


Popular posts from this blog

How to write a successful blog post

First, a quick clarification of 'successful'. In this instance, I mean a blog post that receives a large number of page views. For my, little blog the most successful post ever got almost 57,000 page views. Not a lot by some other standards, but I was pretty happy about it. Looking at the top 10 blog posts (by page views) on my site, I've tried to distill some wisdom about what made them successful. Your blog posting mileage may vary. 1. Avoid using the passive voice The Microsoft Word grammar checker has probably been telling you this for years, but the passive voice excludes the people involved in your blog post. And that includes you, the author, and the reader. By using personal pronouns like I, you and we, you will include the reader in your blog post. When I first started this blog I avoid using "I" because I thought I was being narcissistic. But we all like to read about other people, people help anchor a story in reality. Without people your bl

Your last name contains invalid characters

My last name is "Graham-Cumming". But here's a typical form response when I enter it: Does the web site have any idea how rude it is to claim that my last name contains invalid characters? Clearly not. What they actually meant is: our web site will not accept that hyphen in your last name. But do they say that? No, of course not. They decide to shove in my face the claim that there's something wrong with my name. There's nothing wrong with my name, just as there's nothing wrong with someone whose first name is Jean-Marie, or someone whose last name is O'Reilly. What is wrong is that way this is being handled. If the system can't cope with non-letters and spaces it needs to say that. How about the following error message: Our system is unable to process last names that contain non-letters, please replace them with spaces. Don't blame me for having a last name that your system doesn't like, whose fault is that? Saying "Your

The Elevator Button Problem

User interface design is hard. It's hard because people perceive apparently simple things very differently. For example, take a look at this interface to an elevator: From flickr Now imagine the following situation. You are on the third floor of this building and you wish to go to the tenth. The elevator is on the fifth floor and there's an indicator that tells you where it is. Which button do you press? Most people probably say: "press up" since they want to go up. Not long ago I watched someone do the opposite and questioned them about their behavior. They said: "well the elevator is on the fifth floor and I am on the third, so I want it to come down to me". Much can be learnt about the design of user interfaces by considering this, apparently, simple interface. If you think about the elevator button problem you'll find that something so simple has hidden depths. How do people learn about elevator calling? What's the right amount of