Conectando o controle sem fio do XBox360 no PC ou Raspberry Pi
Autor: Daniel Tavares | Publicado: 2016-12-29T08:10:00-08:00


Obviamente se você veio até aqui, é porque não quer comprar o receptor original do controle sem fio XBox360, está procurando uma solução mais "alternativa", primeiramente pelo preço absurdo de um hardware simples, segundo pela dificuldade de achar, e terceiro que na maioria das vezes você não quer mais um controle que acompanha o receptor, quer apenas usar o controle que já tem.



Infelizmente a MS ao contrário da Sony, não desenvolveu os controles sem fio baseado no protocolo bluetooth, que inviabiliza tentar qualquer "gambiarra" igual é feito com os controles do PS3 e PS4, a única coisa que é possível fazer é usar a própria placa de RF do XBox360, mais especificamente a placa que fica na parte frontal, que tem o botão de liga desliga e os leds. Como as primeiras versões do XBox360 deram problema "a rodo"&nbsp;com o famoso 3RL, tem dessas plaquinhas aos montes por ai, com certeza se você for a alguma assistência técnica de video game, você encontrará facilmente ela, pois é justamente o módulo de RF do XBox360 FAT que iremos usar nesse projeto, eu particularmente encontrei essa placa no mercado livre por uma média de R$ 10,00 bem mais em conta do que gastar R$ 70,00 no receptor original da Microsoft.



Essa placa na verdade usa uma conexão USB para transmitir os dados do controle, a única diferença é que ela trabalha com 3.3V ao invés dos 5V de uma USB comum. Isso é facilmente corrigido usando um CI regulador de tensão 3.3V, ou um divisor de tensão usando resistores ou apenas 2 diodos comuns (1N4007) ligados em série. Porém o maior problema é que usando somente a USB, não é possível dar o comando de sincronismo entre a base e o controle para poder parear ambos. Esse comando de sincronismo é um código binário enviado em um outro pino na placa, e para enviar esse código sem o XBox360 é necessário um microcontrolador, nesse caso, o mais fácil seria usar um Arduíno.



Para resumir, temos 3 cenários:



1- Usar um XBox360 Fat funcional e puxar os 4 fios da USB da placa RF dele. É uma opção válida, você usa o próprio XBox360 para parear o controle, e como ele é funcional, você usa ele normalmente, quando quiser usar o modulo dele no seu PC, você teria que desligar ele da tomada, e conectar o cabo USB no computador. Como o controle já está pareado na placa, não é necessário mais nada para funcionar no PC



2- Usar uma placa de Arduíno temporariamente. Como é inviável usar uma placa de Arduíno exclusivamente somente para sincronizar o controle (por questão de tamanho e preço), é possível conectar uma placa de Arduíno somente para sincronizar o controle. Após parear o controle com a base, o Arduíno não é mais necessário, a não ser que você pareie esse controle em outro aparelho.



3- Utilizar um pequeno microcontrolador nesse caso o Attiny85 que é programado usando uma placa de Arduíno. Esta opção é deixar fixo um Attiny, que é um microcontrolador pequeno e barato para enviar o comando de sincronismo, a vantagem desta opção é ter sempre disponível a possibilidade de sincronizar qualquer controle, sem precisar de um XBox360.





Clique na imagem para ampliar



Basicamente vamos usar os 7 primeiros pinos do conector da placa RF. Os primeiros 4 primeiros pinos, olhando a placa de frente, e contando a partir do primeiro pino superior esquerdo, temos a conexão USB, com o diferencial de que a placa trabalha com 3.3V, como a USB trabalha com 5V vai ser necessário usar algo para baixar para 3.3V, nesse caso, foi usado 2 diodos de uso geral, ligados em série, a resistência interna somada dos diodos foi suficiente para baixar a tensão de 5 para 3.2V. Se você quer algo mais preciso, pode sem problema usar um CI regulador de tensão de 3.3V. Se você vai usar o modulo em conjunto com um XBox funcional, basta usar esses ligados na USB e pronto.



Os próximos 3 pinos, que seria a segunda fileira da esquerda pra direita, seria o pino do botão Power central, que será usado como entrada para dar o comando de sincronismo, o DATA e o CLOCK. Esses vão ser ligados ao Arduíno ou ao Attiny, para ser possível parear o controle sem ter um XBox360. Como deu pra ver, é bem simples, basta ligar 3 fios do modulo RF nas portas do Arduíno, como mostra a figura acima e programar o Arduíno com o seguinte código:



/* Arduino code to communicate with xbox 360 RF module.

&nbsp;* Original work by (yaywoop) / additional ideas from Alexander Martinez - modified by dilandou (www.dilandou.com, www.diru.org/wordpress)

&nbsp;* First sends LED initialisation code followed by LED startup animation code, then sleeps until a button press for sync command.

&nbsp;* RF module must be powered with 3.3V, two diodes in series with USB 5v will do. Connect the USB wires to a host computer, and the data and serial wires to Arduino.

&nbsp;* of course, make sure to have a common ground&nbsp;

&nbsp;*/



#include 



const int sync_pin = 2; //power button repurposed for sync button (pin 5 on the module)

const int data_pin = 3; //data line (pin 6 on the module)

const int clock_pin = 4; //clock line (pin 7 on module)&nbsp;



int led_cmd[10] = &nbsp;{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[]) {

&nbsp; pinMode(data_pin, OUTPUT);

&nbsp; digitalWrite(data_pin, LOW); &nbsp; &nbsp;//start sending data.

&nbsp; int prev = 1;

&nbsp; for(int i = 0; i &lt; 10; i++){



&nbsp; &nbsp; while (prev == digitalRead(clock_pin)){} //detects change in clock

&nbsp; &nbsp; prev = digitalRead(clock_pin);

&nbsp; &nbsp; &nbsp; // should be after downward edge of clock, so send bit of data now

&nbsp; &nbsp; digitalWrite(data_pin, cmd_do[i]);



&nbsp; &nbsp; while (prev == digitalRead(clock_pin)){} //detects upward edge of clock

&nbsp; &nbsp; prev = digitalRead(clock_pin);

&nbsp; }

&nbsp; digitalWrite(data_pin, HIGH);

&nbsp; pinMode(data_pin, INPUT);

}



void initLEDs(){

&nbsp; sendData(led_cmd);

&nbsp; delay(50);

&nbsp; sendData(anim_cmd);

&nbsp; delay(50);

}



void wakeUp(){

&nbsp; sync_enable = 1;

}



void sleepNow() {

&nbsp; set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set sleep mode

&nbsp; sleep_enable(); //enable sleep bit

&nbsp; attachInterrupt(0, wakeUp, LOW);

&nbsp; sleep_mode();

&nbsp; sleep_disable(); //disable sleep bit

&nbsp; detachInterrupt(0); // disables interrupt 0 on pin 2

}



void setup() {

&nbsp; Serial.begin(9600);

&nbsp; pinMode(sync_pin, INPUT);

&nbsp; digitalWrite(sync_pin,HIGH);

&nbsp; pinMode(data_pin, INPUT);

&nbsp; pinMode(clock_pin, INPUT);

&nbsp; delay(2000);

&nbsp; initLEDs();

}



void loop(){

&nbsp; Serial.println("Sleeping.");

&nbsp; sleepNow();

&nbsp; delay(200);

&nbsp; if(sync_enable==1) {

&nbsp; &nbsp; Serial.println("Syncing.");

&nbsp; &nbsp; sendData(sync_cmd);

&nbsp; &nbsp; sync_enable = 0;

&nbsp; }

}



Feito o upload do programa no Arduíno, agora é hora de ligar o módulo RF no computador, ligue primeiro o modulo RF e somente depois ligue o Arduíno, o LED central deve ficar aceso, se não ficar, algo deu errado com a comunicação do Arduíno, se você checou tudo e ainda assim o led não acende, no final do post eu tenho um macete que pode ajudar a fazer funcionar, lembrando que o Arduíno só é necessário para parear o controle, mesmo com todos os leds apagados, uma vez pareado o controle, ele funciona normal.&nbsp;



Ao conectar na USB, ele irá reconhecer (se não reconhecer ou ficar conectando e desconectando intermitentemente, tem algo errado), mas ao abrir o gerenciador de dispositivos, o windows vai mostrar que falta driver. O Driver que vamos usar é do próprio receptor wireless para controle XBox360, sendo assim entre na página da MS e baixe o driver conforme a versão do seu Windows:



https://www.microsoft.com/accessories/pt-br/d/xbox-360-wireless-controller-for-windows



Depois de baixar e instalar o driver, ao entrar no gerenciador de dispositivos, você vai ver que mesmo assim o receptor não está instalado, ele provavelmente vai estar como "dispositivo desconhecido" isso é devido que esse driver não foi feito específico para essa placa. Sendo assim vamos ter que forçar a instalação do driver neste dispositivo, o driver que você deverá instalar forçado está em:



C:\Program Files\Microsoft Xbox 360 Accessories



Se você não sabe como instalar um driver forçado, acompanhe esse video, ele usa o "cenário 1", sem a necessidade de ter um Arduíno, mas funciona em todos os casos:








Após o driver instalado e funcional, agora sim é hora de sincronizar o controle (se ele ainda não foi pareado), se o led central estiver aceso, basta apertar o pequeno botão da placa que seria o botão "Power" do XBox360 que os leds vão começa a rodar, dai você já sabe, basta apertar o botão sync do controle também, e pronto ! Para testar o controle, mande executar (Windows + R): joy.cpl que se tudo estiver Ok, ele irá aparecer lá.

Agora se mesmo depois de ter checado tudo e mesmo assim o LED não quer ligar, existe um macete que pode te ajudar. Alguns módulos de RF necessitam de 2 resistores Pull UP nos pinos DATA e CLOCK, se você não sabe o que é isso, não tem problema, basta ligar 2 resistores de 10K um no pino DATA e outro no pino CLOCK (pinos 6 e 7 do modulo RF), ambos os resistores ligados no&nbsp;+5V da USB, se esse for o seu caso (foi o meu caso ...), vai funcionar na hora.






Essa foi a plaquinha que eu montei, no meu caso eu usei um Attiny 85 permanente colado na placa. Repare que eu usei um pedaço de cabo flat que eu cortei de um cabo de HDD sata, e como eu não tinha a mão um CI regulador de 3.3V, acabei usando 2 diodos em série mesmo. Caso você também queira usar um Attiny para fazer o sincronismo eu aconselho você usar outro código:



/* Arduino code to communicate with xbox 360 RF module.

&nbsp;* Original work by (yaywoop) / additional ideas from Alexander Martinez - modified by dilandou (www.dilandou.com, www.diru.org/wordpress)

&nbsp;* First sends LED initialisation code followed by LED startup animation code, then sleeps until a button press for sync command.

&nbsp;* RF module must be powered with 3.3V, two diodes in series with USB 5v will do. Connect the USB wires to a host computer, and the data and serial wires to Arduino.

&nbsp;* of course, make sure to have a common ground

&nbsp;*&nbsp;

&nbsp;* Modified to the Attiny by dantavares

&nbsp;*/



#include 

#include 



const int sync_pin = 3; &nbsp;//power button repurposed for sync button (pin 5 on the module) do not change this !

const int data_pin = 2; &nbsp;//data line (pin 6 on the module)

const int clock_pin = 1; //clock line (pin 7 on module)&nbsp;



int led_cmd[10] = &nbsp;{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[]) {

&nbsp; pinMode(data_pin, OUTPUT);

&nbsp; digitalWrite(data_pin, LOW); &nbsp; &nbsp;//start sending data.

&nbsp; int prev = 1;

&nbsp; for (int i = 0; i &lt; 10; i++) {



&nbsp; &nbsp; while (prev == digitalRead(clock_pin)) {} //detects change in clock

&nbsp; &nbsp; prev = digitalRead(clock_pin);

&nbsp; &nbsp; // should be after downward edge of clock, so send bit of data now

&nbsp; &nbsp; digitalWrite(data_pin, cmd_do[i]);



&nbsp; &nbsp; while (prev == digitalRead(clock_pin)) {} //detects upward edge of clock

&nbsp; &nbsp; prev = digitalRead(clock_pin);

&nbsp; }

&nbsp; digitalWrite(data_pin, HIGH);

&nbsp; pinMode(data_pin, INPUT);

}



void initLEDs() {

&nbsp; sendData(led_cmd);

&nbsp; delay(50);

&nbsp; sendData(anim_cmd);

&nbsp; delay(50);

}



void sleep() {

&nbsp; &nbsp; GIMSK |= _BV(PCIE); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Enable Pin Change Interrupts

&nbsp; &nbsp; PCMSK |= _BV(PCINT3); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Use PB3 as interrupt pin

&nbsp; &nbsp; ADCSRA &amp;= ~_BV(ADEN); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // ADC off

&nbsp; &nbsp; set_sleep_mode(SLEEP_MODE_PWR_DOWN); &nbsp; &nbsp;// replaces above statement



&nbsp; &nbsp; sleep_enable(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)

&nbsp; &nbsp; sei(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Enable interrupts

&nbsp; &nbsp; sleep_cpu(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// sleep



&nbsp; &nbsp; cli(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Disable interrupts

&nbsp; &nbsp; PCMSK &amp;= ~_BV(PCINT3); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Turn off PB3 as interrupt pin

&nbsp; &nbsp; sleep_disable(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Clear SE bit

&nbsp; &nbsp; ADCSRA |= _BV(ADEN); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// ADC on



&nbsp; &nbsp; sei(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Enable interrupts

}



ISR(PCINT0_vect) {

&nbsp; // This is called when the interrupt occurs, but I don't need to do anything in it

&nbsp; sync_enable = 1;

}



void setup() {

&nbsp; pinMode(sync_pin, INPUT);

&nbsp; digitalWrite(sync_pin, HIGH);

&nbsp; pinMode(data_pin, INPUT);

&nbsp; pinMode(clock_pin, INPUT);

&nbsp; delay(2000);

&nbsp; initLEDs();

}



void loop() {

&nbsp; sleep();

&nbsp; delay(200);

&nbsp; if (sync_enable == 1) {

&nbsp; &nbsp; sendData(sync_cmd);

&nbsp; &nbsp; sync_enable = 0;

&nbsp; }

}



Lembrando que esse código deve ser compilado usando o Arduíno e pode usar a própria placa do Arduíno UNO para programa-lo. Se você não sabe fazer isso, o google esta ai cheio de tutorial pra você aprender. No meu caso, eu setei ele como 16Mhz Internal PPL.



Caso você queira usa-lo no Raspberry Pi, para mim funcionou perfeitamente no RecalBox, a única coisa que tive que fazer é editar o arquivo de configuração e desativar o suporte ao controle PS3 e habilitar o suporte ao controle XBox360.