18-2 Grupo 5

Jaime Ramiro de Oliveira Júnior - 0040961713028

Maurício Ferreira Benatti - 0040961713025

Vinícius Carli Bustamanti - 0040961713050

Wellington Neves da Silva - 0040961713046

### **Resumo**

Projeto para configurar o arduino UNO juntamente com um controle(joystick) para ser utilizado em jogos para PC.

### **Software/materiais utilizados**

Materiais

* Arduino UNO;
* Joystick shield;
* Jumper;
* Cabo USB;
* Caixa de mdf (madeira).

Software

* IDE do arduino;
* FLIP 3.4.7 (Software);
* JRE FLIP 3.4.7 (Software);
* Game ou software de sua preferência para configuração dos comandos e botões.

### **Metodologia**

No arduino UNO unimos um *shield* que contém um joystick com quatro botões e um *Axis* (analógico com eixos X e Y) para comando das direções. A conexão do arduino com o computador é realizada através do Cabo USB, saindo da conexão de alimentação da placa e entrando diretamente no PC.

### **Desenvolvimento**

##### **Iniciando a configuração**

Primeiramente no Windows instalamos o software FLIP e o JRE do mesmo como mostra na figura 1, através do link a seguir.

Download

Feito isso, fizemos o download do arquivo UnoJoy como mostra na figura 2, que irá auxiliar no desenvolvimento da configuração de nosso projeto. Segue link: UnoJoyWin  **Obs.:** Descompacte a pasta do download em um local de sua preferência.

Prosseguindo com o projeto, o próximo passo foi alocar o *shield*Joystick sobre o Arduino Uno conectando todos os pinos lógicos fazendo com que a energia passe de uma placa para outra, como mostra na figura 3 e 4.

Segue imagem da conexão do Arduino com o PC (Figura 5):

##### **Testando as teclas**

Após feita a instalação dos softwares citados acima e descompactado a pasta do UnoJoy, utilizamos o script abaixo e carregamos o mesmo na placa do Arduino, fazendo com que esteja configurada com a programação necessária para a configuração do Joystick.

```
#include "UnoJoy.h"

void setup(){
  setupPins(); //Configura os pinos do Arduino
  setupUnoJoy(); //Inicializa as funções do UnoJoy
}

void loop(){
  // Sempre fica atualizando o dado a ser enviado ao computador
  dataForController_t controllerData = getControllerData();
  setControllerData(controllerData);
}

void setupPins(void){
  //Configura os pinos digitais 2-12
  //como entrada e com pull-up ativado
  for (int i = 2; i <= 12; i++){
    pinMode(i, INPUT);
    digitalWrite(i, HIGH);
  }
}

dataForController_t getControllerData(void){

  //  Configura local onde dados do controle são armazenados
  //  Serve para limpar o buffer onde esses dados são armazenados
  dataForController_t controllerData = getBlankDataForController();

  //  Associa os pinos digitais com o botão do shield Joystick
  //  A "!" inverte a leitura
  controllerData.triangleOn = !digitalRead(4);
  controllerData.circleOn = !digitalRead(3);
  controllerData.squareOn = !digitalRead(6);
  controllerData.crossOn = !digitalRead(5);
  controllerData.selectOn = !digitalRead(2);
  controllerData.startOn = !digitalRead(7);

  //  Configura o joystick Analógico
  //  A leitura "analogRead(pin)" retorna um valor de 10 bits(0-1023),
  //  Nós usamos um o "map" para deixar na faixa de 8 bits (0-255)
  //  Aproveitamos o map para inverte a leitura no eixo Y (opcional)
  controllerData.leftStickX = map((analogRead(A0)),0,1023,0,255);
  controllerData.leftStickY = map((analogRead(A1)),0,1023,255,0);

  return controllerData;
}

```

Para compor o script utilizamos a seguinte biblioteca do arduino, incluindo a mesma ao código acima.

**Obs.:**Para utilizar a biblioteca, copie o código abaixo para o NotePad++, mude a linguagem para C++ e salve o arquivo com a extensão ".h" (C++), deixe o arquivo na mesma pasta em que está o código acima que será carregado no Arduino.

```
#ifndef UNOJOY_H
#define UNOJOY_H
    #include <stdint.h>
    #include <util/atomic.h>
    #include <Arduino.h>

    // This struct is the core of the library.
    //  You'll create an instance of this and manipulate it,
    //  then use the setControllerData function to send that data out.
    //  Don't change this - the order of the fields is important for
    //  the communication between the Arduino and it's communications chip.
    typedef struct dataForController_t
    {
        uint8_t triangleOn : 1;  // Each of these member variables
        uint8_t circleOn : 1;    //  control if a button is off or on
        uint8_t squareOn : 1;    // For the buttons,
        uint8_t crossOn : 1;     //  0 is off
        uint8_t l1On : 1;        //  1 is on
        uint8_t l2On : 1;
        uint8_t l3On : 1;        // The : 1 here just tells the compiler
        uint8_t r1On : 1;        //  to only have 1 bit for each variable.
                                 //  This saves a lot of space for our type!
        uint8_t r2On : 1;
        uint8_t r3On : 1;
        uint8_t selectOn : 1;
        uint8_t startOn : 1;
        uint8_t homeOn : 1;
        uint8_t dpadLeftOn : 1;
        uint8_t dpadUpOn : 1;
        uint8_t dpadRightOn : 1;

        uint8_t dpadDownOn : 1;
        uint8_t padding : 7;     // We end with 7 bytes of padding to make sure we get our data aligned in bytes

        uint8_t leftStickX : 8;  // Each of the analog stick values can range from 0 to 255
        uint8_t leftStickY : 8;  //  0 is fully left or up
        uint8_t rightStickX : 8; //  255 is fully right or down
        uint8_t rightStickY : 8; //  128 is centered.
                                 // Important - analogRead(pin) returns a 10 bit value, so if you're getting strange
                                 //  results from analogRead, you may need to do (analogRead(pin) >> 2) to get good data
    } dataForController_t;

    // Call setupUnoJoy in the setup block of your program.
    //  It sets up the hardware UnoJoy needs to work properly
    void setupUnoJoy(void);

    // You can also call the set
    void setupUnoJoy(int);

    // This sets the controller to reflect the button and
    // joystick positions you input (as a dataForController_t).
    // The controller will just send a zeroed (joysticks centered)
    // signal until you tell it otherwise with this function.
    void setControllerData(dataForController_t);

    // This function gives you a quick way to get a fresh
    //  dataForController_t with:
    //    No buttons pressed
    //    Joysticks centered
    // Very useful for starting each loop with a blank controller, for instance.
    // It returns a dataForController_t, so you want to call it like:
    //    myControllerData = getBlankDataForController();
    dataForController_t getBlankDataForController(void);

//----- End of the interface code you should be using -----//
//----- Below here is the actual implementation of

  // This dataForController_t is used to store
  //  the controller data that you want to send
  //  out to the controller.  You shouldn't mess
  //  with this directly - call setControllerData instead
  dataForController_t controllerDataBuffer;

  // This updates the data that the controller is sending out.
  //  The system actually works as following:
  //  The UnoJoy firmware on the ATmega8u2 regularly polls the
  //  Arduino chip for individual bytes of a dataForController_t.
  //
  void setControllerData(dataForController_t controllerData){
    // Probably unecessary, but this guarantees that the data
    //  gets copied to our buffer all at once.
    ATOMIC_BLOCK(ATOMIC_FORCEON){
      controllerDataBuffer = controllerData;
    }
  }

  // serialCheckInterval governs how many ms between
  //  checks to the serial port for data.
  //  It shouldn't go above 20 or so, otherwise you might
  //  get unreliable data transmission to the UnoJoy firmware,
  //  since after it sends a request, it waits 25 ms for a response.
  //  If you really need to make it bigger than that, you'll have to
  //  adjust that timeout in the UnoJoy ATmega8u2 firmware code as well.
  volatile int serialCheckInterval = 1;
  // This is an internal counter variable to count ms between
  //  serial check times
  int serialCheckCounter = 0;

  // This is the setup function - it sets up the serial communication
  //  and the timer interrupt for actually sending the data back and forth.
  void setupUnoJoy(void){
    // First, let's zero out our controller data buffer (center the sticks)
    controllerDataBuffer = getBlankDataForController();

    // Start the serial port at the specific, low-error rate UnoJoy uses.
    //  If you want to change the rate, you'll have to change it in the
    //  firmware for the ATmega8u2 as well.  250,000 is actually the best rate,
    //  but it's not supported on Macs, breaking the processing debugger.
    Serial.begin(38400);

    // Now set up the Timer 0 compare register A
    //  so that Timer0 (used for millis() and such)
    //  also fires an interrupt when it's equal to
    //  128, not just on overflow.
    // This will fire our timer interrupt almost
    //  every 1 ms (1024 us to be exact).
    OCR0A = 128;
    TIMSK0 |= (1 << OCIE0A);
  }

  // If you really need to change the serial polling
  //  interval, use this function to initialize UnoJoy.
  //  interval is the polling frequency, in ms.
  void setupUnoJoy(int interval){
    serialCheckInterval = interval;
    setupUnoJoy();
  }

  // This interrupt gets called approximately once per ms.
  //  It counts how many ms between serial port polls,
  //  and if it's been long enough, polls the serial
  //  port to see if the UnoJoy firmware requested data.
  //  If it did, it transmits the appropriate data back.
  ISR(TIMER0_COMPA_vect){
    serialCheckCounter++;
    if (serialCheckCounter >= serialCheckInterval){
      serialCheckCounter = 0;
      // If there is incoming data stored in the Arduino serial buffer
      while (Serial.available() > 0) {
        pinMode(13, OUTPUT);
        //digitalWrite(13, HIGH);
        // Get incoming byte from the ATmega8u2
        byte inByte = Serial.read();
        // That number tells us which byte of the dataForController_t struct
        //  to send out.
        Serial.write(((uint8_t*)&controllerDataBuffer)[inByte]);
        //digitalWrite(13, LOW);
      }
    }
  }

  // Returns a zeroed out (joysticks centered)
  //  dataForController_t variable
  dataForController_t getBlankDataForController(void){
    // Create a dataForController_t
    dataForController_t controllerData;
    // Make the buttons zero
    controllerData.triangleOn = 0;
    controllerData.circleOn = 0;
    controllerData.squareOn = 0;
    controllerData.crossOn = 0;
    controllerData.l1On = 0;
    controllerData.l2On = 0;
    controllerData.l3On = 0;
    controllerData.r1On = 0;
    controllerData.r2On = 0;
    controllerData.r3On = 0;
    controllerData.dpadLeftOn = 0;
    controllerData.dpadUpOn = 0;
    controllerData.dpadRightOn = 0;
    controllerData.dpadDownOn = 0;
    controllerData.selectOn = 0;
    controllerData.startOn = 0;
    controllerData.homeOn = 0;
    //Set the sticks to 128 - centered
    controllerData.leftStickX = 128;
    controllerData.leftStickY = 128;
    controllerData.rightStickX = 128;
    controllerData.rightStickY = 128;
    // And return the data!
    return controllerData;
  }

#endif

```

Feito isso, com o Arduino ainda conectado ao PC, executamos um programa que está na pasta descompactada do UnoJoy. Segue caminho do programa:

*UnoJoyWin > UnoJoyProcessingVisualizer > UnoJoyProcessingVisualizer.exe*

Após aberto, aparecerá a seguinte tela (Figura 6):

Pressionando os botões e o mexendo o analógico, percebemos o acionamento dos mesmos pelo seguinte resultado (Figura 7):

Com as teclas testadas, desconectamos o Arduino do PC e em seguida retiramos/desalocamos o Joystick *shield*​​​​​​, separando as duas placas.

##### **Transformando o Arduino UNO em Joystick**

**Cuidado!**

* Ao fazer o procedimento abaixo modificamos o firmware do conversor USB/Serial que está na placa do Arduino. Isto vai mudar a forma como ele é reconhecido pelo computador.

**Obs.:**Evite manusear o Arduino com anel ou qualquer outro material metálico.

Reconectamos o Arduino (apenas) ao PC, e com o Jumper, encostamos/jumpeiamos (demos um "curto-circuito") nos pinos mostrados na Figura 8:

Tiramos o jumper de perto do Arduino para evitar problemas, mas mantivemos o Arduino conectado ao PC. Isto serve para poder ser reprogramado o chip de comunicação USB/Serial e deixá-lo em modo DFU(Device Firmware Update).

Posteriormente, clicamos no programa:

*UnoJoyWin > UnoJoyDriverInstaller.bat*

Se o driver ainda não foi instalado, procure nessa pasta:

*UnoJoyWin > Drivers*

Instalado o dispositivo, nos certificamos de que instalamos o software FLIP e executamos o seguinte arquivo:

*UnoJoyWin > TurnIntoAJoystick.bat*

Irá aparecer uma tela como mostra a Figura 9:

Desconectamos o Arduino da USB, realocamos o Joystick *shield* sobre o mesmo, e reconectamos ao PC. Abrindo a pasta *Dispositivos e Impressoras,*podemos perceber que o Joystick já está instalado e reconhecido pelo computador (Figura 10).

O Arduino está pronto para ser utilizado como Joystick, basta configurar em qualquer emulador de sua preferência.

Utilizamos uma caixa de madeira (mdf), para alocação do Joystick, tanto no transporte quanto em seu uso (Figura 11 e 12).

### **NOTA**

Para reverter o processo, é necessário repetir os passos do item "**Transformando o Arduino UNO em Joystick**" e ao chegar no ponto de executar o arquivo *"TurnIntoAJoystick.bat"* execute *"TurnIntoAnArduino.bat"* que esta dentro da pasta do UnoJoyWin.

## **Resultados**

O resultado do projeto foi atingido de maneira satisfatória, pois todos os objetivos foram alcançados, transformando nosso Arduino Uno em um controle Joystick para ser utilizado de forma positiva em qualquer jogo de computador, apenas configurando a função dos botões no game em qualquer emulador (de sua preferência) como mostra o vídeo abaixo:

No próximo vídeo, podemos ver nosso projeto sendo executado em dois tipos diferentes de jogos, primeiro jogo (Super Mário World) de SNES no modo 2D e o segundo jogo (Air Force) no modo 3D, sendo ele produzido pela nossa equipe no software da Unity3D.

## **Conclusão**

O trabalho realizado pelo grupo foi executado com sucesso, cujo principal objetivo era fazer deste projeto, um projeto interdisciplinar onde trabalhamos simultaneamente com duas matérias: Laboratório de Programação (Arduíno) e Física Aplicada aos Jogos Digitais. Com conhecimentos obtidos na matéria de Física desenvolvemos o jogo "Air Force", um jogo de aviões onde vimos a oportunidade perfeita de unir a matéria de Arduíno implementando um controlador Joystick para nosso jogo. Durante a etapa de testes tudo ocorreu dentro do esperado e felizmente não tivemos grandes problemas.

Quanto a possíveis alterações futuras, dentro do objetivo do qual nosso trabalho foi destinado, ainda não há propostas para melhorá-lo, visto que é um projeto não tão complexo que visa transformar o Arduíno em um controle para o player que vier a utilizá-lo. Acreditamos que apesar do projeto ser relativamente simples, seu diferencial está na pesquisa e tempo que dedicamos para que essa junção entre dois projetos distintos de duas disciplinas diferentes pudessem se comunicar.

É essencial destacar a importância do projeto como aprendizado para todos os integrantes do grupo, pois através dele, pudemos adquirir e compartilhar conhecimentos sobre Arduíno e sobre todos os softwares envolvidos durante todo o processo de desenvolvimento. Não há dúvidas que esses conhecimentos aqui citados serão utilizados para realização de futuros projetos a serem desenvolvidos pela nossa equipe ou até mesmo entre membros individuais.

Ao fazer uma análise de todos esses processos, vimos de maneira bastante positiva e podemos considerar que o projeto foi um sucesso e desejamos que cada leitor deste artigo, sendo professores, alunos, etc, possam tirar proveito deste trabalho e que possa ser tão prazeroso quanto foi para nós desenvolvê-lo.