Creating a Bluetooth game controller for Windows Phone with ATTiny + Arduino

Tweet about this on TwitterShare on FacebookShare on RedditShare on Google+Email this to someonePin on Pinterest

It is 2014 and control-schemes on touch screens still pretty much suck. Yes, touch is suited for a lot of games, but it just doesn’t work for shooters and racing games. That’s why there are companies like MOGA making game controllers specifically designed for phones.

I decided to make my own with an ATTiny connected to Windows Phone over Bluetooth.

Hardware

ATTiny 44
– 0.1uF capacitor (used to smooth out the power)

4xAA battery pack with 1.2v batteries (Anything around 3.3v to 5v total will work fine).
Serial Bluetooth module (DX for $7)

2 thumbstick modules (DX for $3 each)

 

Setup

I decided to use an ATTiny because it was nice and small, and the 44 has enough pins for what we need. An ATMega chip would obviously work fine too.

If you’ve never used an ATTiny with Arduino then before continuing head over to my blog post on the ATTiny 45. The only difference is that the pinout is different. Take a look at this to see the pin numbers for all the different ATTiny chips.

To lay it out I cut up a small prototype board and soldered some headers onto it. It is hard to see, but there is a 0.1uF capacitor between the GND and VCC very close to the ATTiny.

board1

With the wires and ATTiny plugged in, here is what it looks like:

board

(Using the ATTiny because of its size seems pretty pointless with the wires taking up so much space, but that’s a post for when I get time to etch a nice PCB for it and 3D print a cover.)

OK, so here is how you wire it all up:

Sketch_bb

Make sure you use a BT module that can take the voltage that you are using. The DX ones linked above work between 3.3v and 6v fine. One other thing to note is that these thumbsticks have an extra pin for the button (clicking in the stick) that I am not using.

Now onto the code!

Arduino code

All the ATTiny needs to do is read the values for the X and Y axes of both controllers and then send it along to the BT module.

When using analogRead the value we get back is between 0 and 1023 representing how much the thumbstick is tilted. The most efficient way to send this value that I could think of was to reduce it to a value between 0 and 255 and send it over as a byte. So what the code below does is divide each value by 4 (to get it to the 255 range) then send each axis in sequence. After all 4 axes (2 per thumbstick) have been sent it sends a null byte (a zero) to let the phone know that it has reached the end of the sequence. Without this end byte there would be no way of knowing which value was which (short of sending over strings with letters attached).

Note that the code also checks that the value read from the stick is not a zero. If it is then the phone will confuse the axis with the end byte, so we just add 1 (making 1 the minimum).

The code constantly sends the values in a loop with a delay of 20milliseconds each time. This could probably be reduced based on the ping between the phone and ATTiny.

 

The code is using SoftwareSerial because the ATTiny does not have proper hardware Rx and Tx lines.
Go ahead and upload that code to the ATTiny 44. I’ve burned mine at 8MHz.

Windows Phone code

The code for connecting to a Bluetooth device is detailed in a previous post here, so I won’t explain too much.

Create a new Windows Phone 8 app and go into MainPage.xaml.cs. Add the following method which will connect to the BT module:

We want the phone to try connect as soon as the app launches, so add this line of code to the constructor:

Next we need to actually receive the data and do something with it. As mentioned, the values will come in 5 parts (4 are values, last one is the null end byte). So we have a queue here and add the values to it as they come in. When the end byte is reached we check whether we successfully received 4 values before that, and if so, do something with them.

To handle the values we add two last methods, one converts each value from a byte into a float between -1 and 1, and the other instructs the UI to change.

Notice in the HandleGamepadMovements method that we are referencing leftStick and rightStick? Those are the little square blocks with the red X that you can see in the gif at the top. Let’s create that UserControl now.

Add a new UserControl to the project in a folder called Controls and and call it ThumbStick. The XAML for the control is basically just a Rectangle and a vector “X” that we move around with a TranslateTransform.

The code is just as simple, and just sets the transform of the X when we call a method:

Once you’ve added that code in ThumbStick.xaml.cs, build the project. This will make the control available to the rest of your app.

Head back to MainPage.XAML where we need to add these controls. At the top of the XAML add the following XML Namespace pointing to your Controls folder:

Remember to change that accordingly if your project is not called BluetoothController.

While you’re at the top of the XAML, you should set the Orientation to Landscape too.

Lastly, we need to define the UI of MainPage.XAML (including the left and right thumbstick that our code already references:

 

And that’s everything! Yup, it really is that simple 🙂

You can grab the source HERE.

 

I added the code to my new Windows Phone game (VALA: Alpha – out soon!) and it works pretty awesomely. I’ll definitely be adding MOGA support for the game when I get my hands on a controller.

CQRofDC

If you enjoy Bluetooth, checkout my other posts on the topic.

 

Got questions? Ask me in the comments below or on the Twitter machine: @roguecode

Tweet about this on TwitterShare on FacebookShare on RedditShare on Google+Email this to someonePin on Pinterest
  • Atheba

    Great stuff… Do you plan to add additional buttons for a full controller? Ideally they should be mapped using software on the phone?

    • RogueCode

      Yeah, when I get time I’m going to add that and put it in a proper case (plus find a smaller powersource).

  • Roco

    Good job!
    Can you explain me why is not necessary use a external oscillator? the serial is reliable without it?
    There’s some way to use the bytes trasmited by the attiny as a touch in the screen?
    I think of using a old snes or genesis controller that have libraries on arduino and use them with emulators, but don’t know nothing about windows phone programming yet.
    Loved your blog because i can undestand and learn how it works.
    Thanks!