Ways to improve optical mouse sensor tracking

I am starting a new topic, as I believe it is better suited here (and it strays from my original topic). Generally, I want to implement a two-way high resolution rotation counter for my training bike; more details here: http://arduino.cc/forum/index.php/topic,66550.0.html

I have tried a mechanical rotary encoder and found out it is not best suited for my purposes, so I've switched to optical sensors. I've tried the ps2 library with two of my mice and it works great! At least until I actually try to implement it...

The problem is that the tracking distance for the mouse sensor is very short (it almost has to touch the tracking surface). There are not many places on the bike itself where it can be placed - the wheel is not suitable, as it is freewheel. The width and depth of the chain is too large - i.e. the mouse tracks it with interruptions. This leaves only the big sprocket (crankwheel), with enough surface to work on. However, it is still rather unreliable (hard to position the mouse exactly) and the mouse is hard to fit due to space restraints. Getting the electronics out of the body makes it unoperable - probably because it's the body that aligns the lens precisely to the sensor.

Any way to make it more reliable at longer distance? I've seen several projects where people use the mouse sensor without such problems, but no clear explanation how they did that...

Optical mouse is overkill for such project. If you know how regular bike computer measure a speed, they place a magnet on a spoke and read revolution per second/minutes from reed switch positioned on the frame. In your situation, as for some reason you need to know direction of rotation, just place two reed switches slightly shifted, let say 10-20 mm apart, so when magnet approaches from one side one triggered first, if magnet coming other way - second switch triggered first. In general, it would be mechanical rotary encoder build from parts. Any software library written for rotary encoder should be able to process signals from your two switches, and give on output direction and PPM.

Oh... It seems the basics of the project are described in yet another forum.

I am using Arduino to convert the training bike speed into signal for a digital potentiometer for an axis in a computer gaming driving wheel. In other words, if I want to win computer game races, I need to pedal really fast.

I am using a setup similar to the one you describe - it came with the bike (it's mechanical, but it does not matter much). However, it generates only one impulse per wheel turn, about four times per second. This is far from satisfactory - the response time is low, it is very diffcult to maintain speeds lower than 100% etc. Moreover, I cannot brake with the pedals - it is a freewheel, so the signal is registered only for one direction.

That is why I wanted to increase the resolution. Two-way measurement would be nice as well. Everything works great on the electric/software side of things, but the mechanical setup is way more difficult than I thought...

I have considered placing a number of magnets on the crankwheel and using Hall sensors (which I happen to have), but given the past experiences I am a bit afraid that the precise placement of magnets and sensors as well as phasing the encoding will not be that easy.

To win a game you don't have to pedal at all, just take a PWM 50% duty from arduino, 490 PPM! Why placing two/three magnets on the wheel would require precise phasing? It's not a rocket technology :)

Magician: To win a game you don't have to pedal at all, just take a PWM 50% duty from arduino, 490 PPM!

I think you miss the point here... If I don't pedal, why use the training bike at all? Fun + exercise = win!

Why placing two/three magnets on the wheel would require precise phasing? It's not a rocket technology :)

Two magnets won't cut it, for the reasons I have stated above. The crankwheel is twice as big as the sprocket, so on the average there are two turns per second. With eight magnets the response for braking (change of direction) would be almost 1/8 s - passable, but not great...

Could you help to figure out mechanical setup, by posting photo or video? edited.

Sparkfun has a kit, would it be useful? http://www.sparkfun.com/products/9209

I am not a native speaker of English, so I got the terms from the Internet - they might be wrong...

Here is the picture:

Yes, English is not my native ether, so I decided to remove a link to youtube, after I have seen a few minutes... Draw on a computer a disk: Encoder_disc_(3-Bit_binary) Print it , and attach/glue from internal side of the crankwheel. Using two of the photo-transistor couplers attached to the frame (similar, like on a link to sparkfun) you will get your optical rotary encoder. If 1/8 of turn is too much, hey, draw on disk as much stripes as you want, 64 , 128.... unlimited.....

Jabberwock: I've seen several projects where people use the mouse sensor without such problems, but no clear explanation how they did that...

Just for academic interest here's an example. Basically it just comes down to using a lens and getting a good focus on the target.

The "paper encoder" is brilliant! I've made a 2-bit chart and soldered the little buggers and it seems to work!

No time to program it yet, but I will get around to it...

Where did you connect the paper disk (your freewheel could be a big one), please post a picture

No time for a picture now, I'll post it later...

I did just as Magician said - on the internal side of the crankwheel (i.e. on the other side of the wheel with pedals). It could not be the freewheel, because, well, it's a freewheel.

Got some (not much) time to play around with this again...

Obviously I am not the right person to do that. On the workbench it works fine, but when I get around to implement it, it's problems, problems, problems...

One of them is that lighting is a bit tricky - I have fitted two LEDs to light the area evenly, however, due to restricted space and surrounding (i.e. white glossy paint of the bike frame) it's hard to get good contrast - either two much light is reflected off the paper or it is too dim.

Anyway, I have started a bit too ambitious - I've put the encoding wheel with 24 sections (12 impulses per turn), but there was too much noise to establish the threshold value right. Now I've fitted 8-section wheel - this works well, but then the resolution is the measly 4 impulses per turn... Hall sensors look attractive again, but then I'd need to order the magnets. By the way, anyone has any experience with hall sensors and neodymium magnets? What's the typical distance they detect the field from? I do not want to space them too densely...

Upto several cm, depends on the size of the magnets and the amount of hysterysis of the Hall sensors (most Hall sensors output logic level and have slight hysterysis, analog output hall sensors are the exception not the rule). Magnetic field strength falls off roughly as the cube of distance, note.

Thanks for the info! A few cms might be problematic given the diameter, especially if I want to get the phase for the second sensor. I'll check it out when the magnets arrive.

Unfortunately, the optics turned out to be a dead end - it works well while tested (so the setup and the software are OK, I believe), but at the working speed it stops picking up the impulses - the input value kind of flatlines, I guess the sensor is not fast enough so it just gets a grey blur... actually, when I look at it spinning, I get it, too.

Optics fast enough to transmit 100 GB/s over optical cable, something wrong with your hardware configuration. Can you post your schematic/drawings?

I am not sure the optics network guys use exactly the same photocells as I do…

I attach the diagram, hope it is clear enough.

The code is:

int PinA = 2;
int PinB = 3;
int Last = 0;
int n = 0;
unsigned long timeold;
int delta;
int distance;

void setup() {
	digitalWrite(A2, HIGH);
	digitalWrite(A3, HIGH);
	timeold = millis();

void loop(){
	n = (analogRead(PinA) > 505);
	if ((Last == 0) && (n == 1)) {
		if (analogRead(PinB) > 500) {
			delta =  millis() - timeold;
			timeold = millis();
		// reverse
	if (n == 1) {
		Last = 1;
		Last = 0;
	Serial.print (analogRead(PinA));
	Serial.print ("/");
	Serial.print (analogRead(PinB));
	Serial.print ("/");
	Serial.println (delta);

You must use photodiodes or phototransistors. LDRs are incredibly slow.

I use this:


Is this the slow kind?

Great news for a change!

Hall sensors and magnets work perfectly! No skipping, no delay, no need for debouncing. They are so precise I just placed two sensors next to each other and I can detect the change of direction with just one pass of a magnet...

I've placed eight magnets around the wheel (the glued encoder chart from the previous solution was quite useful for this :) ). I think I could do even sixteen, but for now this is good enough - the time between the pulses is below 100 ms, which is comparable to analog game controllers.

Funny thing is, I've almost had another solution - I've recovered an IR phototransistor and emitter from an old mouse and wanted to count the teeth on the wheel. I've got the wiring part all done when the magnets have arrived...

Anyway, thank you all for invaluable help, I've learned heaps doing this!