Sense of humour in datasheet.

I wasn’t expecting to find humour in one of Microchip’s Application Notes, especially one about 48 applications with the CTMU. (AN1375, “See what you can do with the CTMU”):

Ok, not as great as “The Polish OpAmp”, from National Semiconductor, but it’s always nice to find something like that nowadays!

Advertisements

2D positioning: hacking an optical mouse!

For my next project, I will need to know the relative position of a moving (<10cm/s) object above (+/- 10 cm ) a surface (flat, but of any quality). After playing with accelerometers, I realized it won’t work (damn you, gravity) so I took the other option I thought of: an optical mouse.

A regular optical mouse contains a chip, usually from avagotech (Agilent company) with a small 16*16 CCD sensor, taking pictures at high rate of what’s under the mouse. It calculates the “travelled distance” by looking for differences from several pictures and outputs the value via an i2c bus or QAM pins. A microcontroller interfaces the first chip with the USB or PS/2 port and also decodes the buttons/scroll wheel.

I found a cheap second hand USB mouse at my local flea market for 2 Euros:

The “Mini Notebook Mouse”, from the Typhoon brand gave her body to (my) science.

Luckily, it contains the A2051 sensor. The datasheet is freely downloadable on Avagotech’s website (link) [EDIT: Not anymore. But you can get it here]. The electronics are just two PCBs, stacked and connected with two 6-pin headers (easy to separate). The bottom one has the sensor and its red LED, the buttons and the encoder for the scroll wheel. The upper one, the chip with the USB capabilities.

On the left: My USB dev board with a PIC18F87J50. In the middle: the sensor PCB. On the right: the desoldered PCB for interfacing the sensor and buttons with the PC.

Closer look at the sensor:

It has 400/800 cpi resolution , with a two-wire SPI interface. The CCD is on the other side.

The main problem is that the focus distance of this kind of sensor assembly is very narrow, about +/- 3mm. I needed more.

All the optical mouse sensors have a function to get the actual image of the surface below the mouse.

I wrote a small software to get that image. The sensor is connected to the USB dev board, via the SPI interface.

A software to get the image of the CCD (256 pixels with 64 values of gray, up-scaled so each pixel for the sensor is 8 pixels on the screen)

It allowed me to try various combinations of lenses in front of the sensor to get a bigger focus zone and a higher minimal focus distance (I wanted 10cm +/- 5cm)

I used these small lenses for security cameras/babyphones, like this one: Mini 12mm Lens  (but you can find cheaper ones on eBay, I saw some for $7). They’re easily opened unscrewing the front part (need to heat the glue on the thread sometimes) and contain between two and four small optical elements that can be re-arranged to get different magnifications/view angles).

After a lot of try-and-error, I managed to get a good combination of optical elements. The positioning is really precise, but depends of the contrast of surface the sensor “is looking at”.

Here’s some of the code I use (Microchip MCC18):

Two functions to read/write to the A2051 optical sensor.

void WriteSensor(unsigned int address, unsigned int data)
{
    unsigned int bitcounter;

    bitcounter = 0;
    address = address | 0b10000000; //Set the MSB of the adress to 1
    SDIO_LAT  = 1;
    SDIO_TRIS = 0; //Output
    SCLK_TRIS = 0;
    SCLK = 1;
    while(bitcounter <8)
    {
        SCLK = 0; //Lower Clock
        Nop();
        if(address & 0b10000000 )
            SDIO_LAT  = 1;
        else
            SDIO_LAT  = 0;
        Nop();
        Nop();
        SCLK = 1; //High pulse on clock
        Nop();  //Let the sensor read the sent bit.
        address = address <<1;
        bitcounter++;
    }
    bitcounter = 0;
    while(bitcounter <8)
    {
        SCLK = 0; //Lower Clock
        Nop();
        if(data & 0b10000000 )
            SDIO_LAT  = 1;
        else
            SDIO_LAT  = 0;
        Nop();
        SCLK = 1; //High pulse on clock
        Nop();
        Nop();  //Let the sensor read the sent bit.
        data = data <<1;
        bitcounter++;
    }
} //end WriteSensor

unsigned int ReadSensor(unsigned int address)
{
    unsigned int bitcounter;
    unsigned int res;
    res = 0;
    bitcounter = 0;
    address = address & 0b01111111; //Set the MSB of the adress to 0 (read)
    SDIO_LAT  = 1;
    SDIO_TRIS = 0; //Output
    SCLK = 1;
    //Start to write the address of the register we want to read from
    while(bitcounter <8)
    {
        SCLK = 0; //Lower Clock
        if(address & 0b10000000 )
            SDIO_LAT  = 1; //Change the output to match the bit we want to send
        else
            SDIO_LAT  = 0;
        SCLK = 1; //High pulse on clock
        address = address <<1; //Shift the next bit to send
        bitcounter++; //Inc the bit counter
    }
    //We have to wait at least 100us
    SDIO_TRIS = 1;
    for(bitcounter=0;bitcounter<0x10;bitcounter++)
        Nop();
    //Configure the SDIO pin as an input
    SDIO_LAT  = 1;
    SDIO_TRIS = 1; //Input
    SDIO_TRIS = 1; //Input
    bitcounter=0;
    while(bitcounter <8)
    {
        SCLK = 0; //Lower the Clock line
        //Nop(); //Works without the Nop
        SCLK = 1; //Set the Clock line
        res = res <<1; //Shift the received bit in
        if(SDIO_PORT )
            res  = res | 0b00000001; //Read the current bit
        else
            res  = res & 0b11111110;
        bitcounter++;
    }
    SDIO_TRIS = 0;
    SDIO_LAT  = 1;
    SCLK = 1;
    return (res); //Return with the read byte
}//End ReadSensor

With I/O declared as such:

#define SDIO_PORT               PORTCbits.RC4
#define SDIO_LAT                LATCbits.LATC4
#define SDIO_TRIS               TRISCbits.TRISC4
#define SCLK                    LATCbits.LATC3
#define SCLK_TRIS               TRISCbits.TRISC3
#define PD                      LATCbits.LATC5
#define PD_TRIS                 TRISCbits.TRISC5

(PD is the sensor Power Down pin. Used to reset the A2051 at board’s power-up. You can use any pin of you PIC to communicate with the sensor, as long as there’s a pull-up resistor)

To dump the sensor image:

int ptr = 0;
WORD_VAL LowerB,UpperB;
unsigned char Buffer[256];
WriteSensor(0x0A,0b00001001); //Configuration register: Dump the pixels, no power saving
while(ptr <0xFF)
{
   LowerB.Val = ReadSensor(0x0C);//"LowerData" Contains the pixel value, 6bits.
   UpperB.Val = ReadSensor(0x0D);//"UpperData" The MSB indicates if the pixel in LowerData is valid. 
                                 //The seven other bits are the pixel address (form 0 to 0xFF)
   if(!(LowerB.bits.b7)) //Check if data valid
   {
     Buffer[UpperB.Val] = ((LowerB.Val)&0b00111111);
     ptr++;
   }
 }

The Buffer will contain the image from the sensor. I send it via USB to my mac application.

The next steps will be to build a frame around the PCB, integrate it to my project and see how good the positioning gets with different surfaces. I’ll probably still use an accelerometer to measure the tilt angle of the optical sensor and to provide a backup continuity in the displacement measurement in the case the surface contrast gets too bad for the sensor.

Inspiration from this article: Sprites mods.

Designing a simple and cheap temperature logger. Part 7: Schematics, PCB and source code.

I decided to publish all this project under Creative Commons license (Attribution, Derivatives, Non commercial, ShareAlike). The source code contains a FAT12 filesystem that can be reused to make custom flash drives for other projects.

USB Temperature Logger

(PCB version 1.2, hence the misaligned 3.3V regulator to include a diode. Corrected in the V2.0)

USB Temperature Logger 2

USB Temp Logger Schematics

You’ll find the schematics here: Simple USB temperature logger schematics

The Altium files (including a routed PCB) there: Simple USB temperature logger Altium files

The source code (based on Microchip Applications libraries -Device – Mass Storage – SD Card data logger- MPLABX): Simple USB temperature logger source code

The source code could be improved to increase the robustness of the logger (especially in the case of battery power failure while on logging mode). The PCB allows the monitoring of the battery voltage, it just needs to be implemented in the firmware.

I hope my work will be useful to someone!

Don’t hesitate to contact me (mail in the About section) for questions or comments!

Designing a simple and cheap temperature logger. Part 6: Video!!

I just finished developing my USB temperature logger and shot a video showing how it works. Here are the key figures:

  • Up to two months of logging with a single coin cell battery.
  • 30 000 timestamped temperature measurements.
  • Logging period from every 5 seconds to every 24 hours.
  • 0.5°C accuracy, 0.06°C resolution.
  • No driver, no software and no admin rights needed!
  • Compatible with any computer with USB port.
  • Automatic time synchronization with the computer.
  • Low cost design.

When plugged to a computer’s USB port, the logger appears as a normal USB drive. The temperature logging period is changed by editing a config.txt file. When this file is saved, the logger reads the periodicity (in seconds), synchronizes its clock to the computer’s date and time and starts to flash the LED to indicate it’s ready to log. Once removed from USB, the logging is started by pushing the button (the LED blinks three times). For every temperature measurement, the LED flashes.

Once plugged back to USB, the file DATA.CSV will contain all the temperature measurements and the corresponding date and time, TAB separated.

A future development could include a Li-Ion USB rechargeable battery, battery life monitoring, low power – long period logging mode.

If you’re interested by this project, don’t hesitate to contact me. Share if you like it!

Canon 1D mark III teardown

What is worse than having a leak in the roof of your house? -Leaving your super expensive Canon camera right under it.

Yes.

After one night of “Chinese water torture”, my camera gave up and didn’t power on any more, even after some drying on a heating.

It was actually three months ago, but I only had the time/need to do something about that just now (and of course, the warranty expired two months before it happened).

As I didn’t have much to loose, I decided to give a try and to fix it myself.

The quality of the photos should be better, but I didn’t really have the time or the motivation for that. Sorry. I took a lot of them when I was actually re-assembling the camera, so it’s not a *real* teardown (I was really desperate of the camera not working any more)

The basic tools are a set of philips screwdrivers and some boxes to put the screws (there are different lengths/threads). Tweezers and a plastic spudger can help. I also used electrostatic protective wrist band and electrostatic mat.

01-Canon-1D-Mark-III-Teardown

02-Canon-1D-Mark-III-Teardown-Stripped-Front

To access any screw, you need to undress the camera first by pulling off the pieces of rubber (I don’t know if it’s the glue used or my extreme way of using my cameras, but they were easy to peel).

The rubber on the memory card door doesn’t actually need to be removed. No screw there.

All the screws need to be removed and sorted.

This small piece of copper looks like a capacitive hand presence detector (there’s an other one on the other side of the grip) but it’s  not, as it isn’t connected to anything. If anyone knows what its purpose is, don’t hesitate to comment.

Once all the visible screws are unscrewed, it’s possible to remove the back panel with the LCD screen. It’s connected to the mainboard by two flat flexes and two sets of cables. Unfortunately, I didn’t take a picture of it.

A view from the back of the guts

Not-so-easy-to-spot-screw, holding the front assembly.

At first, I wondered what the two holes on the bottom were for..

This last screw is holding the top assembly. Tricky to spot, especially if you don’t remove the front cover..

More flex cables!!

The power management board. Note how some of the chips pins are coated. The black/red cable on the left comes from the battery DC/DC converter (a small PCB on the top of the battery compartment). As you can see, there are several SMD fuses on the board. Unfortunately, all of them were good.

Removing the power mngt board reveals one of the memory cards slot

Water is good for humans, not for $4000 cameras.

And the other side is affected too. The small board on the bottom is the battery DC/DC converter.

Caution! The next photo is really graphic. Don’t click to see it full size.

You never listen…

That’s also a good reason why it’s important to clean/dry any electronics that were in contact with water immediately. “Do what I say, not what I do”

After cleaning. Already better. There’s still some hope.

Nope. The hope is gone.

Let’s put it back and see what happens.

Next water damaged part: the top LCD and its buttons.

Ok, this one isn’t as horrible as the rotten PCB.

The top LCD assembly with the backlight, exposure correction and ISO buttons.

Backlighting/LCD display sandwich, held pressed together by the metallic piece laying on the right and two screws. There’s foam around the LCD to prevent condensation between it and the sealed transparent plexiglas.

Water was here. Come on Canon, stainless steel?

 

After more cleaning and re-screwing all the screws in the right order, I tried to power up the camera again. This time, it worked!

Unfortunately, the top LCD isn’t working. Luckily, all its information can be displayed on the main screen (“00” because no lens attached):

Also, more annoying, all the info in the viewfinder are gone. The AF system, AF points selection and all the rest seem to work as good as new (ok, as before the water damage). I’m not doing sport photography any more, so I should be able to use the camera like that and wait till I have enough money to send it to service or to buy a new one.