Showing posts with label wii. Show all posts
Showing posts with label wii. Show all posts

Thursday, July 8, 2010

Hacking the Wii MotionPlus

So its been two days since I got my Nintendo Wii MotionPlus (henceforth simply ‘WM+’; yeah, I know I called it the ‘M+’ earlier :-|) clone from DealExtreme. And I’ve been itching to get some data off it.

The WM+ uses I2C to send and receive data from a host, which is normally a WiiMote, but in my case it is a PIC16F877.

The hacked WM+. I desoldered the pass-through port (normally used to connect a Wii Nunchuck) and used it as a mating female connecter for the WM+’s male connector.

On the net, I couldn’t find a single site that used a PIC as the host. And most sites had code specific to the microcontroller used by the site’s creator (which was more often than not an Arduino). So after cracking my nut trying to figure out what in the heck these Arduino chaps were doing, I decided to post pseudo-code so that others working with the WM+ can easily write code for their micros.

*        *        *

Pseudo-code:

//initialize the WM+
i2c_start
i2c_write(0xA6)
i2c_write(0xFE)
i2c_write(0x04)
i2c_stop
  
//read data
while(true)
{
    i2c_start
    i2c_write(0xA4)
    i2c_write(0x00)
    i2c_stop
   
    i2c_start
    i2c_write(0xA5)
    yaw_lo_byte = i2c_read(ack)
    roll_lo_byte = i2c_read(ack)
    pitch_lo_byte = i2c_read(ack)
    yaw_hi_byte = i2c_read(ack)
    roll_hi_byte = i2c_read(ack)
    pitch_hi_byte = i2c_read(nack)
    i2c_stop
   
   
//this is necessary since the last two bits
    //in the high bytes are useless

    roll_hi_byte = roll_hi_byte >> 2
    pitch_hi_byte = pitch_hi_byte >> 2
    yaw_hi_byte = yaw_hi_byte >> 2
   
    //send to computer for displaying
    putc
    printf
}

A few words about the pseudo-code. You’ll find that the hex value that you write in line 3 is 0xA6. Some websites say the WM+ ‘starts off at address 0x53’. This is confusing since 0xA6 is not equal to 0x53. To figure this out you need to know a little about the I2C protocol.

*        *        *

A little about I2C:

Quite often, I2C devices use 7-bit addressing, and a 1-bit read/write indicator. 7+1=8 bits=1 byte. All I2C communications start with the host sending a ‘start condition’, followed by the 7-bit address, followed by a 1 or a 0, telling the device that data is either to be written to, or read from that address. This may be followed by additional reads or writes. Between reads and writes, an ‘acknowledge (1)’ or ‘not acknowledge (0)’ is sent. Communication is terminated with a ‘stop condition’.

*        *        *

Anyway, so how is 0x53 equal to 0xA6? Simple. 0x53 is the address that we want to write to. So the first seven bits are 0x53, and since we are writing the next byte, we send a 1. In C this is written as:

(0x53<<1)+0

Which, in plain English reads as: “Shift 0x53 to the left by one bit; set the least significant bit to 0”.

Now we see that (0x53<<1)+0 = 0xA6. Do it yourself if you’re not convinced!

So once the WM+ is initialized, one can start reading gyro data. Some sites recommend that you wait 38ms before reading data, since the WM+ needs to initialize fully, but I haven’t done that and yet my WM+ gives me ‘nice’ data.

DSC00644 Close-up of the pass-through port female connector. Only four wires are needed. Red – Vcc; Black – Ground; Blue – SCL; Yellow – SDA. The pins that go into the bread board are scavenged from a broken DB25 male plug.

Gyro data is stored in six consecutive address. In my while loop, I set the address from which to start reading data from – this is 0x52 (which becomes 0xA4, since we’re writing). I write 0x00 to the register to indicate I ‘want’ data. Then I read data into the ‘hi’ and ‘lo’ bytes of the roll, pitch and yaw variables. Data reads are ‘ack-ed’, ie, acknowledged. The last byte is ‘nack-ed’. This is NOT to say that it is not acknowledged, rather the word ‘not’ in ‘not acknowledge’ actually refers to Boolean inversion. Since an ack is binary 1, a nack becomes binary 0.

In my actual code, I have a for loop inside the while loop. The for loop runs 32 times to average out the roll, pitch and yaw readings. After averaging, the data is sent out using a string of putc statements. Alternatively, printf may be used to print to a terminal program – the choice is yours. Infact, I threw together a simple LabVIEW program to display the roll, pitch and yaw on a dial. You can see that I am simultaneously also graphing the results.

Roll Pitch Yaw
The LabVIEW frontend. Roll, Pitch and Yaw are depicted.

My setup is pretty simple – just a PIC16F877 with the TinyBootloader on it, running at 20MHz; a MAX232 for serial comms; the PICKit2 provides 5v power to the PIC and the MAXIM chip; a TI LP2950 regulates the 5v to a safe 3.3v for the WM+. A cheap USB-to-Serial dongle is used to receive data @ 115.2Kbaud.

  The current setup - WM+ connected to a PIC16F877. Power provided by the PICKit2. Serial data sent to LabVIEW through a MAX232 and USB-Serial dongle.

I still need to calibrate the WiiMote, and see how accurate the data is. In the next few days I’ll be making my data acquisition board wireless (by including the RF code from an earlier project, and using a Li-ion battery). I’ll be going around the place, sticking the board to swivel chairs, on the wheel of a cycle, on a treadmill, to a fan blade, and whatever else I can think of :-P.

Updates, more pics and videos will be up in a while.

 

Credits:

Monday, July 5, 2010

I Love the Mailman

I think certain clarifications are in order - I am completely heterosexual; its just that today, one of the mailmen brought me a few parcels, which I have been eagerly waiting for. One of those parcels was a Sensiron SDP610 sample, which is a CMOS differential pressure sensor; the other parcel is the subject of this blog.

1 2
Left: The Sensirion SDP610 differential pressure sensor
Right: A Nintendo Wii MotionPlus clone

I’m building a quadrotor, and after doing a bit of searching online, found that IMUs cost a bomb. Not wanting to spend $$$ on commercial units I decided to go the DIY way. I got onto DealExtreme and purchased a Wii MotionPlus clone (hereafter simply ‘M+’). The original M+ was made by Nintendo (of the Super Mario/Contra/Space Invaders fame), as an accessory for its Wii gaming console.

The Wii revolutionized the way the world played video games. Nintendo introduced a motion controlled gaming device that took the world by storm. However soon, gamers wanted more, and when they found that the WiiMote controller gave inaccurate results when moved vigourously, they decide to add a piggy-back module to the controller.

The M+ is a 3 axis gyroscope to complement the 3 axis accelerometer already in the WiiMote. Simple maths says 3+3=6; the M+ coupled with the WiiMote gives a complete 6DOF motion controller, using which you can 'swing’ a simulated golf club, or ‘throw’ punches at the world’s deadliest boxer, maybe even ‘play’ a game of pool.

So I spent USD12~INR550, and DX shipped me the M+ along with a complimentary rubber sleeve to protect my (inexistent) WiiMote. Shipping was free, and was done via registered mail. The package took 23 days to ship from HK to Gurgaon, India.

Packaging was good – the M+ came plastic wrapped in a product box. The outer packaging was a bubble mailer. No damage other than a few wrinkles on the box’s surface.

3Good packaging by DX 

Also included in the product box were ‘documentation’ and leaflets – they’ll go straight to the raddi pile to be sold as scrap paper since I can’t read Chinese. Thoughtful of the manufacturers, but useless to me :-|

5
Decent build quality

The M+ itself looks solid, and build quality is good – no loose bits or clamps (not that it really matters since I’m gonna tear it apart anyway). The M+ presented me with a small problem – it was held together by tri-wing screws. Not one to be outsmarted by two screws, I took a small flathead screwdriver and gently got the screws out.

6 
The tri-wing and the flathead that got it out.


The pieces

Here are the innards of the M+:

 
The upper side of the PCB. Visible on the top left corner is the IXZ650 gyro. The black epoxy in the centre covers the microcontroller, in a CoB construction style. The connector is to the left, while the expansion port is to the flat cable on the right.

The bottom side of the PCB. In the centre is the IDG650. On the top right is what seems like an EEPROM chip.

It seems funny why the clone would have two 2-axis gyros when just a 2-axis and a 1-axis would suffice. I guess I’ll have to get my hands dirty to see if there’s any difference in its functioning.

Updates in a bit.

Visitors