Pages

Friday, January 3, 2014

Tutorial: Xbox 360 wireless controller to PC (via RF module and Attiny 45/85)

For some time I've been working on a self made way to connect my Xbox 360 controller to my pc. I could have gone on eBay or other similar places and bought a receiver for the controller but then what kind of a geek would have I been:)). So I've gone on the not so difficult road of modifying a xbox 360 phat RF module.

Well I've started off buying a RF module off a dead Xbox 360 since I didn't have any laying around the house, prior to that the guy that I got the RF module from was kind enough to pair one of my controllers to it and let me test out the module so we could be sure everything was working correctly.

VERY IMPORTANT. If you are planning to get an RF module but not get the Attiny chip remember once you UNPAIR the controller from the RF module it is impossible to pair it back up without a console atached to the RF module.

Well to get all things out of the way and slim it down a bit I took the connector off the module and therefor made it a bit smaller the way to connect it is very simple for testing purposes, you have the schematic below (ignore the Arduino).
The module is running on 3.3V so you'll have to take the 5V provided by the USB plug and take it a bit down so that you don't fry the board, 2x 1N4001 diodes in series should be enough to get the board working and test it out.
Now that we have that sorted out we can take care of the software side on the PC, now if you plug the module in a USB port you will soon find out that it doesn't work, don't be alarmed you just have to point out the PC to the correct drivers;) since the module doesn't have a hardware id and is not recognized.


There are 2 easy methods of doing this and both start with installing the xbox 360 wireless controller drivers for windows found here.

Method nr 1:
After this you can do it either by going into device manager (right click on My Computer => Properties => Device Manager) and there you will see your RF Module with a yellow exclamation mark on it from there you can click Update Drivers => Browse my computer for driver software => Let me pick from a list of device drivers on my computer and now you have to browse for Xbox 360 Wireless Controller.

Method nr 2:
Prior to this method you need to have the RF Module unplugged from the PC, go to the install folder (Microsoft Xbox 360 Acessories) in your program files and find Xusb21.inf this is the driver file for the software you will be modifying it so it will recognize your hardware.
Open it with a text editor or a program like Notepad++ (recomended) and find these headers [MSFT.NTx86.6.0], [MSFT.NTamd64.6.0], [MSFT.NTx86], and [MSFT.NTamd64].

you are going to replace the 5 lines of code under each of them, the original code looks like this:

%XUSB21.DeviceName.Wired%=CC_Install, USB\Vid_045E&Pid_028E
%XUSB21.DeviceName%=CC_Install, USB\Vid_045E&Pid_0719
%XUSB21.DeviceName.Wired%=CC_Install, USB\MS_COMP_XUSB10
%XUSB21.DeviceName%=CC_Install, USB\MS_COMP_XUSB20
%XUSB21.DeviceName.Jump%=CC_Install, USB\Vid_045E&Pid_028F



what you will put in its place looks like this
%XUSB21.DeviceName.Wired%=CC_Install, USB\Vid_045E&Pid_0291
%XUSB21.DeviceName%=CC_Install, USB\Vid_045E&Pid_0291
%XUSB21.DeviceName.Wired%=CC_Install, USB\UNKNOWN
%XUSB21.DeviceName%=CC_Install, USB\UNKNOWN


now save it (make sure you save as a .inf file or it wont work).
After that plug in your RF module and is should find drivers all on it's own;).

Also if you have a arduino laying around and you are not using it for anything you can give it a try and test it out to see if it's working;), all you have to do is hook it up like in the schematic above and load the following code to your Arduino.

CODE:

#include <avr/sleep.h>
#define sync_pin 2 //power button repurposed for sync button (pin 5 on the module)
#define data_pin 3 //data line (pin 6 on the module)

#define clock_pin 4 //clock line (pin 7 on module)

int led_cmd[10] = {0,0,1,0,0,0,0,1,0,0}; //Activates/initialises the LEDs, leaving the center LED lit.

int anim_cmd[10] = {0,0,1,0,0,0,0,1,0,1}; //Makes the startup animation on the ring of light.
int sync_cmd[10] = {0,0,0,0,0,0,0,1,0,0}; //Initiates the sync process.
volatile boolean sync_enable = 0;
void sendData(int cmd_do[]) {
pinMode(data_pin, OUTPUT);
digitalWrite(data_pin, LOW); //start sending data.
int prev = 1;
for(int i = 0; i < 10; i++){
while (prev == digitalRead(clock_pin)){} //detects change in clock
prev = digitalRead(clock_pin);
// should be after downward edge of clock, so send bit of data now
digitalWrite(data_pin, cmd_do[i]);
while (prev == digitalRead(clock_pin)){} //detects upward edge of clock
prev = digitalRead(clock_pin);
}
digitalWrite(data_pin, HIGH);
pinMode(data_pin, INPUT);
}
void initLEDs(){
sendData(led_cmd);
delay(50);
sendData(anim_cmd);
delay(50);
}
void wakeUp(){
sync_enable = 1;
}
void sleepNow() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set sleep mode
sleep_enable(); //enable sleep bit
attachInterrupt(0, wakeUp, LOW);
sleep_mode();
sleep_disable(); //disable sleep bit
detachInterrupt(0); // disables interrupt 0 on pin 2
}
void setup() {
Serial.begin(9600);
pinMode(sync_pin, INPUT);
digitalWrite(sync_pin,HIGH);
pinMode(data_pin, INPUT);
pinMode(clock_pin, INPUT);
delay(2000);
initLEDs();
// sendData(sync_cmd);
}
void loop(){
Serial.println("Sleeping.");
sleepNow();
delay(200);
if(sync_enable==1) {
Serial.println("Syncing.");
sendData(sync_cmd);
sync_enable = 0;
}
}

Lets say that's a step forward now and you can sync any controller you want with the board as long as you have the Arduino connected. I wanted to get the RF Module to have it's own Atmel chip that would handle those functions including syncing and a 3.3V voltage regulator to get rid of those ugly looking diodes, since it's only a 1.7V drop and not a lot of current going trough, it wouldn't required a heatsink or some way of dissipating heat so i went with this method.

So my choice of parts for this build was a Atmel Attiny 85 20su (you can also go for the Attiny 45) meaning it was surface mounted and a voltage regulator LM1117-33 also surface mounted. Since my build was meant to be as compact as possbile and as sturdy as possible I printed my own circuit board, designed in Eagle (I will be covering making your own circuit boards in another tutorial tho there are a few around on the internet and it's a pretty straight forward).
I'll be also posting the files for the circuit and the modified code for the chip since it's got a different pinout as the Atmega328. Pick your pins correctly otherwise it won't work as planned. Only some pins of the Attiny are able to wake the chip out of sleep so if you don't pick your pins correctly the chip will not wake up from sleep and won't do the syncing procedure.

The only modification to the code is that the first few lines have to be replaced with these ones:

#include <avr/sleep.h>
#define sync_pin 2 //power button repurposed for sync button (pin 5 on the module)
#define data_pin 1 //data line (pin 6 on the module)
#define clock_pin 0 //clock line (pin 7 on module)
I've designed the board in such way that it can be programmed on the spot, you will just have to solder some wires to the program pins.
The final product. It ain't pretty it's a bit bigger and it's not almost plug and play as is the original one but it gets the job done and it has a lot of pretty lights:). All you will have to do after it is programmed is hook up the wires, ground wire from the USB connector, 5V to power the Attiny and the voltage regulator and on the output side first you will have to solder the 3.3V coming from the voltage regulator to the RF Module so the electronics on the board are powered and after that the 3 wires coming from the Attiny going RF Module. That's all.

Well now to add to all of this I haven't been able to play a lot with the functionability tho it is possible to add other functions to the board with the help of this:

//GREEN EDGE LEDs
0010100001 = "upper left"
0010100010 = "upper right"
0010100100 = "lower left"
0010101000 = "lower right"

//RED EDGE LEDs
0010110001 = "upper left"
0010110010 = "upper right"
0010110100 = "lower left"
0010111000 = "lower right"

//RED EDGE LEDs blink
0011010001 = "all"
0011010010 = "upper left"
0011010011 = "upper right"
0011010101 = "lower left"
0011010100 = "lower right"

//CONTROLLER
0000001000 = "Syncing"
0000001001 = "shutdown controller"

//MISC
0010000101 = "Start Animation"
0010000100 = "init Leds - leave middle LED on"

These are the binary codes that drive the board and are sent by the Attiny with a bit of change in the code it's able to make the board do other things also.
Have fun;) and let me know what you've tried and what has worked or didn't work for you.

Finally got around to uploading the files have fun and enjoy;)
Attiny85 Xbox 360 controller sketch
Xbox 360 controller sketch

16 comments:

  1. brilliant work. i have just built one of these following your process, but i don't get any led sequences for initialising or syncing etc.
    the rf board drivers are installed and the board is detected in device manager.
    i am using your code on an arduino uno, and the on board 3.3v regulator to power the rf board. can you offer any tips on debugging?

    i assume the led sequences should initialise even if the rf board was not connected on the usb?

    cheers

    ReplyDelete
  2. Sure no problem. Well there could be one of two problems. You didn't power the RF board (which needs to be powered before you power the arduino) or it doesn't have a common ground (the ground of the arduino has to be connected to the ground of the RF board/USB

    ReplyDelete
  3. PS: to answer you question yes it should power up even if its not connected to the usb, as long as it has power;)
    Double check for faulty wiring I've done that a few times :) happens to everyone .... if it still doesn't work... leave a meesage or a photo :D

    ReplyDelete
  4. Hi there, This looks really amazing, and I had to try it out myself! But sadly enough I am encountering the same problem as calum richings.

    It's not a wiring problem, I am pretty sure it's something in the "sendData" function.

    ReplyDelete
    Replies
    1. Well it should work as is. I will double check the code and give it a go. But it has worked for me as is without any modifications. If you have any trouble and you haven't fixed it by now please give me a picture of your layout and we will try to figure it out together :p

      Delete
    2. I have already managed to fixed it. There is a pull up resistor needed for the DATA and CLOCK pin when using the Arduino UNO. That solved the problem for me!

      Delete
    3. Could be ... I used an arduino Mini pro for mock up and the final version used a ATTINY85 and none of them needed anything. Great thing you figured it out. Congrats and thanks for the update.

      Delete
  5. Hello,

    Have you tried to sync 2 or more controller at the same time ?

    Cheers.

    ReplyDelete
    Replies
    1. Hello, I think i've connected a maximum of 3 controller to it.

      Have a great day and sorry for the huge ass delay:))

      Delete
  6. After finishing and connecting the circuit to the pc, the board lights up 2 LEDs red and nothing really happens.

    I was a bit clumsy taking off the serial plug thing. I kind of scorched the board the slightest bit (a faulty 25W soldering iron that thinks it's a 100W).

    Please tell me I haven't ruined my board.

    PS: sorry if this is a double post, I have been having issues posting a comment.

    ReplyDelete
    Replies
    1. Hello, you could have ... try to follow the traces on the pcb and connect to those or to the nearest via. Try not to power the board with more than 3.3v or you will fry the board and from that point there is nothing you can do for it. Gl and leave an update if you got it to work;)

      Delete
    2. Ok here's my update so far:

      I can't believe this, but I mis-wired my usb cable. Like .. out of all the mistakes I could have done, it's the cable.

      Spliced and wired correctly

      I decided to check all possible mistakes, so I breadboarded the circuit again, and flashed a new attiny85 (checked blink example working, then uploaded your files). The board is being detected by the pc. That's a good start. However, the button didn't seem to do anything. Now I am doubting that the traces on the RF module might have been damaged. I am waiting for my father to return from travel so I can nick his Fluke for testing.

      By the way, are you flashing the attiny as 8Mhz or 1Mhz? Does it even matter?

      Any ideas on what could be going wrong?

      I'll keep you updated if you are interested in knowing where this goes.

      I need not mention how grateful I am for your work. Let's just hope I can get mine to function.

      Delete
    3. Awesome work... you know Murphy and his laws:)) it's always the simple thing... happened to me also a couple of times;). I think if you flash an attiny85 with the 1mhz bootloader the blink sketch will be a bit off (haven't played with them in a while :D). I'm certain it was 8mhz.
      Try on another attiny if you have laying around in combination with the blink sketch: if they look the same it shouldn't be any problem and flash it with the 8mhz just to be certain.

      And for the sync button ... be sure you got your wires correct coming out of the attiny, be certain they are not mirrored;) pin 2 on the attiny is the sync button (7th pin on the attiny chip) and going to the farthest right as you look at the module from the back, or farthest left as from the front ( lower row). GL with it and keep me updated if you have any trouble give me a message.

      Delete
    4. New update:

      IT LIVES!!!!

      I just successfully connected a wireless controller to the RF module (I haven't tested the functionality though .. one step at a time). I hooked up my Arduino Uno to test before trying the ATtiny85 again. I read on another blog's comments that people with the same revision board as I am needed pull-up resistors on the DATA and CLOCK Arduino pins. Has to do with the voltage this revision uses.

      The board is X802779-013 Xbox360 RF Module RF01 (apparently called Rev. H or something).

      How does that translate to my ATtiny85 setup/code? I am just about to try it out as is, and then will try the pull-ups (although from what I understand it has to do with the logic of the UNO specifically ..)

      As you can notice I am not very educated on this subject matter. Just started getting my hand dirty lately, and I'm loving it!

      Any ideas how I should proceed?

      Delete
    5. To connect the attiny you need to modify the first part fo the code that defines the pins for the attiny with this:
      #include
      #define sync_pin 2 //power button repurposed for sync button (pin 5 on the module)
      #define data_pin 1 //data line (pin 6 on the module)
      #define clock_pin 0 //clock line (pin 7 on module)
      good luck;)

      Delete
    6. Done. Finito.

      1k pull-up resistors on DATA and CLOCK .. it is fixed, working like a charm.

      I want to hug random people on the street now. This definitely took MUCH longer than it should have. But it was fun.

      Thanks for all the help!

      Delete