Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Content Obsolete

This content is no longer current.

Wiimote Controlled Car

  In this article, Brian Peek will demonstrate how to use his Managed Wiimote Library and Microsoft Robotics Studio to create a "Wiimote-Controlled Car".
ASPSOFT, Inc.

Difficulty: Intermediate
Time Required: 2-3 hours
Cost: $50-$100
Software: Visual Basic or Visual C# Express Editions, Microsoft Robotics Studio, Phidgets .NET and MSRS libraries, Managed Wiimote Library
Hardware: A remote-controlled car, PhidgetInterfaceKit 0/0/4 OR PhidgetInterfaceKit 0/16/16Airlink101 AIC-250W wireless camera (optional), Nintendo Wii Remote (Wiimote), batteries, wire, and solder
Download: Download

 

Introduction

If you are a regular reader of Coding4Fun, you will probably have read my articles on creating a Managed Library for Nintendo's Wiimote and controlling an R/C Car using Microsoft Robotics Studio.  I have recently updated my Wiimote Library and in the process added a brand new Microsoft Robotics Studio service (with the help of David Lee) so that the Wiimote can be integrated into MSRS projects.

This article will demonstrate how to use this new service in conjunction with my previous article to create a Wiimote Controlled car.  This project was demonstrated at both Mix 07 and Maker Faire 2007 and was a big hit in both places, so it's sure to be a hit with your friends as well.

Wiimote Controlled Car 

A Wiimote Controlled Car at Mix 07- Pic thanks to Robert Burke

Previous Articles

To start with, it's essential that you read the two previous articles mentioned above because I will not be repeated their contents here.  I will simply demonstrate how to "put the chocolate in the peanut butter" to create the project described.  The two articles are:

What We've Learned

From the article on building the R/C car, please build the hardware portion that is described.  This will be used exactly as it is in the existing article.

From the Wiimote article, learn how the library is used and what it's capable of.  With the hardware in place and a knowledge of the library, we can begin writing the software.

The Software

Now that the hardware is complete, we need to write the software to control the car. First, the required software must be installed.  Install the software in the following order:

  1. Microsoft C# or Visual Basic 2005 Express Edition
  2. Microsoft Robotics Studio
  3. Phidgets libraries
  4. Phidgets Services for Microsoft Robotics Studio

Once all of the software is installed, the files phidget21.dll and Phidget21.NET.dll must be copied from the \Program Files\Phidgets directory to the bin directory of your MSRS installation.  If this is not done, the Phidget services will all fail to start when requested, causing you as much pain and torment as it caused me.

Make sure that the Wiimote library is installed in your Robotics Studio \bin\services directory.  You can do this by either loading and compiling the WiimoteMSRS project included in the original Wiimote library distribution, or by coping over the compiled Wiimote.Y2007.M06.*.dll files to the \bin\services directory by hand, all of which can also be found in the original Wiimote library distribution linked above.

The Code

To start, we must first create a service for our car. This can be done by opening the Microsoft Robotics Studio Command Prompt from the Microsoft Robotics Studio (1.0) program group on the Start menu.

To generate the template for our service, the command dssnewservice.exe is used. Change to the directory where you wish to create your project and type one of the following commands, depending on the language you wish to use, to create a new service named “WiimoteCar”:

C#:

dssnewservice /service:WiimoteCar

VB

dssnewservice /language:VB /service:WiimoteCar

This will generate a folder with several items, including project and solution files.

Open the generated WiimoteCar.sln file in Microsoft C# 2005 Express Edition or Microsoft Visual Basic 2005 Express Edition. You will see that several files were generated.

The first thing we will need to do is access the service which controls our Phidget Interface Kit. Robotics Studio includes a built-in service for this device. To access it, first, set a reference to the PhidgetBoards.Y2006.M08.proxy and Wiimote.Y2007.M06.proxy namespaces. This can be done by right-clicking on the project name in the Solution Explorer and selecting Add Reference from the context menu. When the Add Reference dialog appears, select PhidgetBoards.Y2006.M08.proxy and Wiimote.Y2007.M06.proxy, and click the OK button.

To use the contents of this library in our code, we need to import the libraries reference above.  This can be done by adding the following line to the WiimoteCar class.

C#

using wiimote = WiimoteLib.Proxy;
using phidgetinterfacekit = Phidgets.Robotics.Services.PhidgetInterfaceKitBoards.Proxy;
using phidgetcommon = Phidgets.Robotics.Services.Proxy;

VB

Imports phidgetinterfacekit = Phidgets.Robotics.Services.PhidgetInterfaceKitBoards.Proxy
Imports phidgetcommon = Phidgets.Robotics.Services.Proxy
Imports wiimote = WiimoteLib.Proxy

Next, we need to setup a partner relationship with the PhidgetInterfaceKit and Wiimote services and declare a port on which to communicate with it. At the top of the WiimoteCar class implementation, add the following code to the service:

C#

// partner with wiimote service
[Partner("Wiimote", Contract = wiimote.Contract.Identifier,
CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)] 
private wiimote.WiimoteOperations _wiimotePort = new wiimote.WiimoteOperations(); 

// partner with the phidgets service
[Partner("PhidgetInterfaceKit", Contract = phidgetinterfacekit.Contract.Identifier,
CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate)]
private phidgetinterfacekit.PhidgetInterfaceKitBoardsOperations _ikPort = 
    new phidgetinterfacekit.PhidgetInterfaceKitBoardsOperations();

VB

' partner with wiimote service
<Partner("Wiimote", Contract:=wiimote.Contract.Identifier, _
CreationPolicy:=PartnerCreationPolicy.UseExistingOrCreate)> _
Private _wiimotePort As New wiimote.WiimoteOperations()

' our communication port to the Phidget Interface Kit
<Partner("PhidgetInterfaceKit", Contract:=phidgetinterfacekit.Contract.Identifier, _
CreationPolicy:=PartnerCreationPolicy.UseExistingOrCreate)> _
Private _ikPort As New phidgetinterfacekit.PhidgetInterfaceKitBoardsOperations()

Next, we will setup a few items that will be required to talk to the Phidget controller and Wiimote.  We must subscribe to the PhidgetInterfaceKit service and Wiimote service.  Add the following to the Start method of the WiimoteCarService class:

C#

// subscribe to the phidget board
_ikPort.SelectiveSubscribe(null, new phidgetinterfacekit.PhidgetInterfaceKitBoardsOperations());

// create an internal notification port
wiimote.WiimoteOperations _wiimoteNotify = new wiimote.WiimoteOperations();

// setup to receive WiimoteChanged msgs
Activate(Arbiter.Receive<wiimote.WiimoteChanged>(true, _wiimoteNotify, WiimoteChangedHandler));

// subscribe to the Wiimote
Arbiter.Choice(
    _wiimotePort.Subscribe(_wiimoteNotify),
    delegate(SubscribeResponseType response) { LogInfo("Subscribed to Wiimote service"); },
    delegate(Fault fault) { LogError(fault); }
);

VB

' subscribe to the phidget board
_ikPort.SelectiveSubscribe(Nothing, New phidgetinterfacekit.PhidgetInterfaceKitBoardsOperations())

' create an internal notification port
Dim _wiimoteNotify As New wiimote.WiimoteOperations()

' setup to receive WiimoteChanged msgs
Activate(Arbiter.Receive(Of wiimote.WiimoteChanged)(True, _wiimoteNotify, AddressOf WiimoteChangedHandler))

' subscribe to the Wiimote
_wiimotePort.Subscribe(_wiimoteNotify)

This will subscribe to the PhidgetInterfaceKit service without requesting any notifications on events, as they will not be needed for this project.  It will also subscribe to the Wiimote service asking for the WiimoteChanged event to be sent to the WiimoteChangedHandler method that will be defined below.

Next, create an enumeration above the definition for the WiimoteCarService class for the possible directions:

C#

public enum Direction
{
    Forward = 0,
    Backward,
    Left,
    Right,
    None
}

VB
Public Enum Direction
    Forward = 0
    Backward
    Left
    Right
    None
End Enum

The value of each item in the enumeration will correspond to the relay used for that direction as described above.  Next, we will write a method named SetOutput to communicate with the Phidget Interface Kit and enable or disable the output relay as appropriate:

C#

public void SetOutput(Direction dir, bool enabled)
{
    // if no direction sent, return
    if(dir == Direction.None)
        return;

    // create a new request to send to the Phidgets service
    phidgetcommon.SetOutputRequestType req = new phidgetcommon.SetOutputRequestType();

    // assign the index and state (true/false)
    req.Index = (int)dir;
    req.State = enabled;

    // send the request to the port
    _ikPort.SetOutput(req);
}

VB

Public Sub SetOutput(ByVal dir As Direction, ByVal enabled As Boolean)
    ' if no direction sent, return
    If dir = Direction.None Then Return

    ' create a new request to send to the Phidgets service
    Dim req As New phidgetcommon.SetOutputRequestType

    ' assign the index and state (true/false)
    req.Index = dir
    req.State = enabled

    ' send the request to the port
    _ikPort.SetOutput(req)
End Sub

The SetOutput method creates a new SetOutputRequestType request object and fills in the appropriate Index and State. The Index refers to the index number of the relay to change, and the State property is a boolean of whether the switch should be opened or closed.

And finally, the WiimoteChangedHandler described above needs to be implemented.  This handler will be called every time the Wiimote service fires a WiimoteChanged event.  The incoming parameter will be identical to the WiimoteState structure defined and described in the previous Wiimote article.  Since you've already read that, this should be pretty easy:

C#

private void WiimoteChangedHandler(wiimote.WiimoteChanged msg)
{
    wiimote.WiimoteState state = msg.Body;

    // if 1 is pressed, move forward
    if(state.ButtonState.One != _stateLast.ButtonState.One)
        SetOutput(Direction.Forward, state.ButtonState.One);

    // if 2 is pressed, move backward
    if(state.ButtonState.Two != _stateLast.ButtonState.Two)
        SetOutput(Direction.Backward, state.ButtonState.Two);

    // based on thresholds, move the car left/right
    if(state.AccelState.Y != _stateLast.AccelState.Y)
    {
        SetOutput(Direction.Left, (state.AccelState.Y < -0.1f));
        SetOutput(Direction.Right, (state.AccelState.Y > 0.1f));
    }

    _stateLast = (wiimote.WiimoteState)state.Clone();
}

VB

Private Sub WiimoteChangedHandler(ByVal msg As wiimote.WiimoteChanged)
    Dim state As wiimote.WiimoteState = msg.Body

    ' if 1 is pressed, move forward
    If state.ButtonState.One <> _stateLast.ButtonState.One Then
        SetOutput(Direction.Forward, state.ButtonState.One)
    End If

    ' if 2 is pressed, move backward
    If state.ButtonState.Two <> _stateLast.ButtonState.Two Then
        SetOutput(Direction.Backward, state.ButtonState.Two)
    End If

    ' based on thresholds, move the car left/right
    If state.AccelState.Y <> _stateLast.AccelState.Y Then
        SetOutput(Direction.Left, (state.AccelState.Y < -0.1F))
        SetOutput(Direction.Right, (state.AccelState.Y > 0.1F))
    End If

    _stateLast = CType(state.Clone(), wiimote.WiimoteState)
End Sub

In this method, if the 1 button is pressed, the forward output is turned on.  If the 2 button is pressed, the reverse output is turned on.  For turning, the Y-axis accelerometer is read and if it's over a specific threshold, the left and right turn outputs are turned on.

That's It!

To run the project, connect the Wiimote as described in the original article above and press F5 to run this project.  Hold the Wiimote horizontally so that the IR end is in your left hand and the strap end is in your right hand.  The Wiimote itself should be face up and parallel to the ground.  Press 1 to move forward, 2 to move in reverse, and tilt (not twist!) the Wiimote to turn the car.  As long as the hardware is wired properly and the Wiimote is connected and compatible with your Bluetooth device, the car should go!

Now What?

Now that the basics are done, here are a few ideas for future enhancements:

  • Set the forward/backward motion of the car based on the Z-axis of the Wiimote accelerometers.  This way one can drive the car by tilting the controller forward and backward to move the car forward and backward.
  • Write the application in the Robotics Studio VPL language.
  • Add on the IP Camera in the original R/C car article.

Conclusion

As you can see, with a little effort and some existing libraries, one can create a pretty simple and cheap Wiimote controlled car.  Now try Wiimote controlling some other R/C devices...

Bio

Brian is a Microsoft C# MVP and a recognized .NET expert with over 6 years experience developing .NET solutions, and over 9 years of professional experience architecting and developing solutions using Microsoft technologies and platforms, although he has been "coding for fun" for as long as he can remember.  Outside the world of .NET and business applications, Brian enjoys developing both hardware and software projects in the areas of gaming, robotics, and whatever else strikes his fancy for the next ten minutes. He rarely passes up an opportunity to dive into a C/C++ or assembly language project.  You can reach Brian via his blog at http://www.brianpeek.com/.

Tags:

Follow the Discussion

  • Brian&#39;s BlogBrian's Blog

    Here is a list of my current Coding4Fun articles: Wiimote Controlled Car April Fools&#39; Day Application

  • Brian&#39;s BlogBrian's Blog

    My latest article has been posted at MSDN's Coding4Fun site . This article explains how to create a Wiimote

  • Roberto Sonnino on Windows, Tech, .netRoberto Sonnino on Windows, Tech, .net

    Fala galera,Não sei quantos de vocês são felizardos de terem um Nintendo Wii ou um Wiimote, mas esses...

  • ElBrunoElBruno

    very very cool ... I'll try to control my Lego Web Cam bot (http://tinyurl.com/yu3xdv) with the WiiMote .. thanks for the guidance Big Smile

    Bye from Spain

  • DimitriDimitri

    two of the software links are broken, how can I get that software?

  • DimitriDimitri

    i've just download the phidget software but i can't find the references you mentioned, what can i do? I really need them cause i'm working on it

  • Clint RutkasClint I'm a "developer"

    If you're not sure what you need for this holiday season, look no further. After a year of coding and

  • BrianPeek.comBrianPeek.​com

    Here is a list of my current Coding4Fun articles: WiiEarthVR Animated Musical Holiday Light Show - Version

  • Clint RutkasClint I'm a "developer"

    With every year, the Coding4Fun team has come up with a small army of gift ideas.&#160; If anyone wants,

  • johnc_glrojohnc_glro

    I want to control using my wiimote a robot in virtual environment. Could someone help me please?

  • Clint RutkasClint I'm a "developer"

    @johnc_glro all depends on how you want to do this and what you're running.

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.