The next problem is that his chassis isn’t exactly sophisticated and the floors he is travelling over aren’t exactly flat. His front castor gets caught easily, and his back wheels lose traction, causing him to turn left and right in an unwanted fashion. How to correct for these little bumps and skips to get him going straight forward?
A little googling found that a number of people had tried interfacing an optical mouse with an Arduino for various reasons and this seemed like a good option. An optical mouse doesn’t rely on contact with the floor, so should be immune from bumps and skips. And it gives us exactly the type of x and y measurements we would need to do course corrections (and maybe to start mapping the room that Sammy is travelling around).
My first attempt followed the guidelines from Martijn Thé here. This involved stripping down a mouse and hooking a serial connection directly into the main camera chip and reading the x and y motion from the registers there. This seems to have worked for lots of people, but unfortunately despite my years of hoarding I couldn’t find a mouse with the right chip. The chip I did try (an OM02 if you’re interested) turned on and seemed to enter the right mode, but I just couldn’t get anything out if its registers, even with the help of the relevant data sheet.
I then discovered the PS/2 library. This allows the connection of keyboards and mice via the old-school PS/2 connector, now largely replaced by USB. Aha! Now I should be able to just plug in a mouse, run the library, and get X and Y movements from there — as well signals from the mouse’s on-board microswitches (from the buttons) and maybe even the rotary encoder (from the wheel).
I desoldered a PS/2 port from an old serial X10 MouseRemote receiver (which may come in handy down the line), and hooked up the relevant wires to the Arduino following the instructions here. I didn’t have a PS/2 optical mouse handy so I experimented with an old ball mouse. Sure enough, it worked!
I then started writing a simple function to take the input from this mouse and correct for any stray movements left or right when the robot was moving forward. This isn’t very sophisticated: it breaks a forward motion down into a series of single-unit-delay loops, making the robot inch forward and run error correction after each tiny movement. If there has been a movement of say 10 left (x=-10) it steers right until it has moved 10 units to the right, cancelling out the initial movement. I’ll need to do some work on this, as you will see later.
Not All Mice Are Created Equal
At the first opportunity I popped out to the shops to pick up a cheap optical mouse with a PS/2 port from my local PC hardware shop. I’m lucky enough to live within a few minutes of both Aria and Microdirect — perfect for those occasional cable/peripheral/hard disk needs or for full on upgrades. The mouse cost less than £4. I could have bought about five second hand ones from the Computer Fair at the weekend for the same price, but frankly I just couldn’t wait that long.
Unfortunately, it didn’t work. There was nothing wrong with the mouse, and it powered up but I got no readings.
OK, maybe that’s a little melodramatic but I was peeved to say the least.
The best diagnosis I could come up with is that not all PS/2 controllers support the ‘Remote Mode’ needed for the Arduino’s PS/2 library to work (great explanation of the PS/2 protocol here). This is a kind of debugging mode where the mouse only sends back data on request and it allows the creation of a kind of master/slave relationship between the Arduino and the mouse chip.
So, I would have to go to the Computer Fair after all. Or would I?
USB To the Rescue
When doing my initial experiments I had tried plugging in a USB optical mouse with a PS/2 converter. This hadn’t worked at all. But given my latest experience I wondered if this was an issue with the USB to PS/2 conversion or in fact the same issue as I was having now. I dug around in my box of old peripherals and found a little portable USB optical mouse. If this worked it would be ideal because it was small enough to fit between the robot’s back wheels and its front castor. Sure enough, I plugged it in, fired up the Arduino and it worked first time.
So, with a little Meccano fabrication and some tweaks to the code (I had to mount the mouse in reverse in order for the cable to fit) it was time for a test.
Now, testing was a mixed bag. About 60% of the time it seemed to work like a charm, with Sammy auto correcting his course along a very straight line until he hit something. But some of the time he just seemed to go off in circles. It seems to make a big difference whether he is started off on the ground and then placed down, or started with his wheels on the floor.
My suspicion is that this is a software problem and my very rudimentary correction algorithm is letting me down. There’s also the fact that the mouse is an extra couple of millimetres off the floor than normal, meaning its optics won’t be perfectly focused (the sensor is basically a camera). Over time I can try to fix both these issues and post the results here. Adding other sensors to give Sammy alternative frames of reference for location will also help. Unfortunately when I came to video the tests the morning after completing this stage, it all went horribly wrong: I couldn’t get Sammy to go straight for love nor money.
More work to be done on this issue and I will post my sketch when I have it working. But for now I’m going to jump over to the next piece: stopping him bumping into stuff. So, next: PING! Sammy gets Bat Vision using an ultrasonic rangefinder…