All dat hot glue, all dat ribbon cable

Wiimote IR camera w/ Arduino and processing

So, lately I have been working on a project for the upcoming Hacktech that involves some IR Position detection. The best way I found to do this was to take apart a wiimote and get the IR camera out of it.

The board with alot of major components taken off

The board with alot of major components taken off

The IR camera is a pretty simple I2c interface, but is complicated by the fact that it runs on 3.3v logic, not 5v, and needs 25mhz clock signal independent of the I2c scl line. This makes it a little bit harder to interface with a 5v mcu such as an arduino.

Pixart Circuit

Thats is my basic circuit, I chose to use a full on oscillator circuit as opposed to a crystal with the capacitors because it was just easier to put onto the circuit. be sure to check the datasheet of your oscillator though, because pin 1 is occasionally an enable pin that needs to be tied to vcc or gnd, luckily mine did not need that. Other tutorials involve a I2c buffer and voltage drop methods but I found that to be too complicated and time consuming so I got a logic level converter from Sparkfun and it works just as well. The only thing is that I didn’t get the Bidirectional one, so you have to wire it up exactly as shown in the circuit, because only certain lines of the chip support bidirectional conversion. There is a 3.3v regulator at the top to put into the camera and the lower voltage reference of the llc. The great thing about this circuit is that you can use it for any 5v mcu that supports I2c. Here is how it turned out for me.

A little bit messier than I wanted.

A little bit messier than I wanted.

You can see the back of the Pixart camera at the top, the oscillator and LLC in the middle, and the 3.3v regulator at the bottom. I used a header that I scrapped from a ps2 mouse to connect to the arduino (next to the regulator). The actual camera was a bitch to get off, and I couldn’t seem to desolder it (lead free solder) so i just cut it off pcb and all, and soldered ribbon cable to it.

One of the great things about this device is that it does all of the Ir detection for you and returns up to four blobs of IR, their intensity, and their x and y coordinates. With the help of a very useful arduino library found here, we can easily send these IR blobs  over serial with the example provided. One issue with the library is that it is a little bit old and needs a few quick changes to make it work with Arduino 1.0 and greater.

Go into the library folder and open up Pvision.h and Pvision.cpp. In Pvision.h, change the #include “Wconstants.h” line to #include “Arduino.h”.   Next, go to the cpp file, and pretty much just replace it with the code posted here. This will bring you fully up to date.

// Example of using the PVision library for interaction with the Pixart sensor on a WiiMote
// This work was derived from Kako's excellent Japanese website
// http://www.kako.com/neta/2007-001/2007-001.html

// Steve Hobley 2009 - www.stephenhobley.com
/******************************************************************************
* Includes
******************************************************************************/
#include "PVision.h"
#include <Wire.h>

/******************************************************************************
* Private methods
******************************************************************************/
void PVision::Write_2bytes(byte d1, byte d2)
{
    Wire.beginTransmission(IRslaveAddress);
    Wire.write(d1); Wire.write(d2);
    Wire.endTransmission();
}

/******************************************************************************
* Constructor
******************************************************************************/
PVision::PVision()
{
	Blob1.number = 1;
	Blob2.number = 2;
	Blob3.number = 3;
	Blob4.number = 4;
}

/******************************************************************************
* Public methods
******************************************************************************/
// init the PVision sensor
void PVision::init ()
{
    IRsensorAddress = 0xB0;
    IRslaveAddress = IRsensorAddress >> 1;   // This results in 0x21 as the address to pass to TWI

    Wire.begin();
    // IR sensor initialize
    Write_2bytes(0x30,0x01); delay(10);
    Write_2bytes(0x30,0x08); delay(10);
    Write_2bytes(0x06,0x90); delay(10);
    Write_2bytes(0x08,0xC0); delay(10);
    Write_2bytes(0x1A,0x40); delay(10);
    Write_2bytes(0x33,0x33); delay(10);
    delay(100);
}

byte PVision::read()
{
    //IR sensor read
    Wire.beginTransmission(IRslaveAddress);
    Wire.write(0x36);
    Wire.endTransmission();

    Wire.requestFrom(IRslaveAddress, 16);        // Request the 2 byte heading (MSB comes first)
    for (i=0;i<16;i++)
    {
       data_buf[i]=0;
    }

    i=0;

    while(Wire.available() && i < 16)
    {
        data_buf[i] = Wire.read();
        i++;
    }

    blobcount = 0;

    Blob1.X = data_buf[1];
    Blob1.Y = data_buf[2];
    s   = data_buf[3];
    Blob1.X += (s & 0x30) <<4;
    Blob1.Y += (s & 0xC0) <<2;
    Blob1.Size = (s & 0x0F);

    // At the moment we're using the size of the blob to determine if one is detected, either X,Y, or size could be used.
    blobcount |= (Blob1.Size < 15)? BLOB1 : 0;

    Blob2.X = data_buf[4];
    Blob2.Y = data_buf[5];
    s   = data_buf[6];
    Blob2.X += (s & 0x30) <<4;
    Blob2.Y += (s & 0xC0) <<2;
    Blob2.Size = (s & 0x0F);

    blobcount |= (Blob2.Size < 15)? BLOB2 : 0;

    Blob3.X = data_buf[7];
    Blob3.Y = data_buf[8];
    s   = data_buf[9];
    Blob3.X += (s & 0x30) <<4;
    Blob3.Y += (s & 0xC0) <<2;
    Blob3.Size = (s & 0x0F);

    blobcount |= (Blob3.Size < 15)? BLOB3 : 0;

    Blob4.X = data_buf[10];
    Blob4.Y = data_buf[11];
    s   = data_buf[12];
    Blob4.X += (s & 0x30) <<4;
    Blob4.Y += (s & 0xC0) <<2;
    Blob4.Size = (s & 0x0F);

    blobcount |= (Blob4.Size < 15)? BLOB4 : 0;

    return blobcount;
}

I modified the example code to only detect two blobs at most, and to print them serially in a format that I found easier to interpret in processing. Here you go. I found that sometimes it will print a 2nd blob when there is no 1st one in the example code which would have made my application a little harder to write (I’m lazy) so I made it print out a blob with all zeroes for values if this case occurs.


#include <Wire.h>
#include <PVision.h>

PVision ircam;
byte result;

void setup()
{
 Serial.begin(9600);
 ircam.init();
}

void loop()
{

 result = ircam.read();

 if (result & BLOB1)
 {
 Serial.print("BLOB1:,");
 Serial.print(ircam.Blob1.X);
 Serial.print(',');
 Serial.print(ircam.Blob1.Y);
 Serial.print(',');
 Serial.print(ircam.Blob1.Size);
 }
 if (result & BLOB2)
 {
 if (!(result & BLOB1))
 {
 Serial.print("BLOB1:,");
 Serial.print("0");
 Serial.print(',');
 Serial.print("0");
 Serial.print(',');
 Serial.print("0");
 }
 Serial.print(",BLOB2:,");
 Serial.print(ircam.Blob2.X);
 Serial.print(',');
 Serial.print(ircam.Blob2.Y);
 Serial.print(',');
 Serial.print(ircam.Blob2.Size);
 }

 Serial.println("");

// Short delay...
 delay(100);

}

Next comes the processing code. I hardcoded the  serial port number of my arduino into the code, you will more than likely have to change it or have it autodetect. There are tons of tutorials on that so I’m not going to write  about it here.


//Processing application to show two IR blobs from a PIxart IR camera
//and link the two blobs with a green line
//2013 - Sebastian Sarbora https://ssarbora.wordpress.com

import processing.serial.*;
Serial port;

int x1= 0;
int y1 =0;
int size1 = 0;

int x2= 0;
int y2 =0;
int size2 = 0;

void setup()
{
 size(1024,768);
 port = new Serial(this, "COM8", 9600);
 port.bufferUntil('\n');
}

void draw()
{
 background(0,0,0);
 fill(255,255,255);
 if (size1>0)
 ellipse(x1,y1,size1,size1);
 if (size2>0)
 ellipse(x2,y2,size2,size2);
 if (size1 >0 && size2>0)
 {
 stroke(0,255,0);
 line(x1,y1,x2,y2);
 }
}

void serialEvent (Serial port)
{
 String s = port.readString();
 s = trim(s);
 println(s);
 String[] coords =split(s, ',');
 if (coords.length>1)
 {
 x1 = Integer.parseInt(coords[1]);
 y1 = Integer.parseInt(coords[2]);
 size1 = Integer.parseInt(coords[3])*5;
 }
 else
 {
 size1=0;
 size2=0;
 }
 if (coords.length >4)
 {
 x2 = Integer.parseInt(coords[5]);
 y2 = Integer.parseInt(coords[6]);
 size2 = Integer.parseInt(coords[7])*5;
 }
 else
 {
 size2=0;
 }
}

Heres a video of this bad boy in action at Hacktech Spring 2014:

My next steps are to mount a widening lens on the camera to increase it’s viewing angle, and to use it for a couple of applications. I’m probably going to try to do something like these with it.

3d voxel Drawing- EDIT: did this at hacktech, see above video.

Head motion Tracking

Autonomous Robot Waypoints

Let me know if there are any questions or comments and I will help out as much as I can. I got alot of my information from these places.

http://translate.google.com/translate?u=http%3A%2F%2Fwww.kako.com%2Fneta%2F2007-001%2F2007-001.html&hl=en&ie=UTF-8&sl=ja&tl=en

http://makezine.com/2008/11/22/hacking-the-wiimote-ir-ca/

http://diydrones.com/profiles/blogs/3d-position-estimation-with-a-wii-remote-camera

Advertisements

8 thoughts on “Wiimote IR camera w/ Arduino and processing

  1. Diggy

    How can the circuit be modified for ir cameras with 10 or 12 pins. Please help, I can’t seem to find the pin out details for this type of cameras.

    Reply
    1. ssarbora Post author

      As far as I know, if the camera doesnt have 8 pins and it came from a wiimote, it is a unit not made by nintendo, Do you have any more information about it, like the part number?

      Reply
      1. Diggy

        Pardon my late reply, didn’t expect you to reply so quick. As for your question, no I don’t have any info, I just know that the only wii mote camera I have around has a 10 pin unlabeled connection. I’m considering getting one off eBay soon, but I’m not sure if it’ll be the 10pin or 12pin module or can one tell the original from fake by looking at the eBay pictures?… Secondly I’ll like to know the part number for the osc used. Thanks.

        Reply
        1. ssarbora Post author

          All of the official nintendo made ones are have 8 pins, I have only seen third part ones with 8 pins never 10 or 12, so i’m not very familiar with what any extra pins would do. The official camera functionality was reversed engineered, and I havent heard of anybody doing that for any 3rd party cameras, so anything that isn’t an official nintendo will be pretty hard to figure out without an oscilloscope. Also, unfortunately there isn’t really a good way to tell from pictures, as a lot of the 3rd party wiimotes look almost identical to genuine ones.

          The oscillator part # is ACHL 1319, but any oscillator in the 20-25mhz range should do. This was just one I had lying around, probably salvaged from a really old device.

  2. Anonymous

    I think, the part related to logic level converter connection in your schematic is converse; PixArt camera should be connected to the Low Voltage side …… ??!

    Reply
  3. Óscar

    Hello ssarbora,

    Thank you for this great tutorial. I have two questions… Still is your code up to date? Are the schematics correct (because last replies talk
    about logic design mistake)? I want to make a shooter game with the camera, arduino and everything connected to a 8 bit old home computer. Thank you very much! Greetings

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s