Wanderer v2, with Wireless Wii Nunchuck


After building my little autonomous wanderer robot, I saw this iPad-controlled blimp and went ahead and added iPad control to my robot too. I had a Python script on my iMac which took commands from the iPad over Wifi and relayed them to the Arduino using XBee. I demo'ed this at BitNorth 2010, but I'm not sure if the video is up yet. That said, the fact that all the commands were relayed through a 'base station' bothered me, and I saw a cheap wireless Wii Nunchuk which I immediately bought, thinking I could make it into a really ergonomic remote control for my little robot. I probably could have gotten a Wifi shield instead, but I was up for a different kind of challenge.

The Wii Nunchuck (wired or wireless) communicates using the I2C protocol, which the Arduino supports quite nicely. There exists a cheap little hardware Arduino/Nunchuck interface but I had no use for the little white casing around the receiver that's supposed to plug into the WiiMote so I cracked it open and interfaced the little circuit board inside directly to my Arduino. After a lot of experimentation and reading of forum posts and wikis, I found a magic incantation of bytes to send to my particular Nunchuck that would enable me to pull data from it reliably, and I packaged it up into a little object-oriented Nunchuck library here. While I was at it, I also packaged up my Pololu motor controller interface code. The robot code sketch itself is on GitHub as well.

So after all this hardware and software work, I have remote-controllable wanderer robot! In the video above you can see that it's capable of autonomous and controlled modes. I used the joystick to control motion, the C button to stop and the Z button to turn on autonomous mode. It's pretty convenient to have a remote for a bot like this, so I can bring it back if it wanders underneath the bed, or turn it around if it gets stuck in a corner or something.

For reference, and because I want to try out my syntax highlighter plugin, here is the initialization code that works for my 'Intec' wireless Wii Nunchuck (look in GitHub at how I handle retrying after failing initialization):

void WiiChuck::init()
{
    Wire.beginTransmission(0x52);
    Wire.send (0xF0);
    Wire.send (0x55);
    Wire.endTransmission();
    delay(30);

    Wire.beginTransmission (0x52);
    Wire.send (0xFB);
    Wire.send (0x00);
    Wire.endTransmission();
    delay(30);

    Wire.beginTransmission(0x52);
    Wire.send (0xFA);
    Wire.endTransmission();
    delay(30);

    Wire.requestFrom(0x52, 6);
    boolean allFF = true;
    int bytesReceived = 0;
    while(Wire.available())
    {
        byte c = Wire.receive();
        bytesReceived++;
        if(c != 0xFF) {
            allFF = false;
        }
    }

    if(bytesReceived == 0)
    {
        return;
    }
    delay(30);

    if(allFF)
    {
        delay(1000);
    }
    else
    {

        Wire.beginTransmission(0x52);
        Wire.send (0xF0);
        Wire.send (0xAA);
        Wire.endTransmission();
        delay(30);

        Wire.beginTransmission(0x52);
        Wire.send (0x40);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.endTransmission();
        delay(30);

        Wire.beginTransmission(0x52);
        Wire.send (0x46);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.endTransmission();
        delay(30);

        Wire.beginTransmission(0x52);
        Wire.send (0x4C);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.send (0x00);
        Wire.endTransmission();
        delay(30);

        inSync = true;
    }
}


© Nicolas Kruchten 2010-2024