Arduino Tutorial - Custom Game Controller
by Crazy Taz Projects in Circuits > Arduino
1536 Views, 4 Favorites, 0 Comments
Arduino Tutorial - Custom Game Controller
Sejam bem vindos novamente a mais um tutorial sobre o Arduino, neste tutorial vamos explicar o funcionamento de uma funcionalidade que apenas alguns tipos de Arduino a possuem. Essa funcionalidade permite ligar o Arduino a um PC podendo este ser utilizado como se fosse um "Game Pad" ou um "Mouse", permitindo assim criarmos controladores periféricos personalizados, tanto para jogos ou para qualquer outro tipo de actividade no nosso PC.
Esta montagem utilizará vários botões do tipo "Push Button" e um pequeno "Joystick", sendo através destes que iremos realizar esse controlo, ambos os componentes já foram mencionados em tutoriais anteriores onde estes controlam opções de menu num LCD, como também pequenos servo motores (Ver datasheet abaixo).
Arduino Tutorial - LDC - Menu
https://www.instructables.com/id/Arduino-Tutorial-LDC-Menu/
Arduino Tutorial - Control Servo Motor - Joystick
https://www.instructables.com/id/Arduino-Tutorial-Control-Servo-Motor-Joystick/
O componente principal neste tutorial será o Arduino MICRO, este pertence a uma categoria de Arduino que permite a sua instalação, configuração ficando assim a funcionar como um periférico de PC. Netas categoria de Arduino encontram-se o Arduino LEONARDO, o MICRO, o ESPLORA, o ZERO e o DUE, pois estes têm incorporada uma função de comunicação USB nos seus Microcontroladores.
As restantes funcionalidades e características do Arduino MICRO são muito idêntico a outros tipos de Arduino utilizado nos nossos tutoriais, sendo apenas muito mais pequeno que um Arduino UNO e um pouco mais comprido que um Arduino NANO, o que o torna ideal para estes tipos de projectos (Ver imagem acima).
Existem 2 funções distintas para tornar o Arduino um periférico de PC, assim iremos explicar ambos os funcionamentos através de 2 tipos de montagem também distintas, sendo uma das montagens para controlar o "Mouse" do nosso PC através de um pequeno "Joystick" e os seus 2 respectivos botões.
Já a outra a montagem terá vários botões que iremos configurar de formas a utiliza-los como um teclado simples ou então como um pequeno "Game Pad".
Caso queiram saber mais sobre o Arduino MICRO vejam as especificações detalhadas, através da seguinte ligação https://www.arduino.cc/en/pmwiki.php?n=Main/arduinoBoardMicro.
Downloads
Supplies
Montagem
Começamos a montagem desta vez não com 1, mas sim com 2 "Breadboards", ficando numa destas a montagem que irá controlar o "Mouse" com o seu respectivo "Joystick" e o nosso Arduino MICRO, já na outra ficará a montagem do "Game Pad", sendo desta forma muito mais fácil de organizar e de realizar as ligações de todos os componentes necessários à montagem.
Material necessário:
- 1x Arduino MICRO;
- 1x Cabo USB;
- 2x Breadboard;
- 1x Joystick KY-023;
- 8x Botão (Push Button);
- 10x Resistência 1KΩ;
- 1x LED Vermelho.
Instalação do Joysitck KY-023 e os Push Button (Mouse):
Para instalarmos o "Joystick" KY-023 na montagem começamos por realizar as ligações das suas respectivas alimentações, depois ligamos os pinos de saída de sinal VRX e VRY aos pinos de sinal analógico do Arduino tendo escolhidos os pinos A0 e A1 respectivamente (Ver imagens acima).
Sempre que o "Joystick" é movimentado é alterado o valor nas suas resistências, ou seja, sempre que se o movimenta o eixo do X ou Y é alterado o seu valor da resistência correspondente (Ver imagem acima). Estas resistências variáveis estando instaladas em circuitos de divisores de tensão à medida que os seus valores de resistência são alterados também são alterados os valores de tensão, podendo variar esse valor entre 0 e 5V (Ver imagem acima).
Arduino Tutorial - Control Servo Motor - Joystick
https://www.instructables.com/id/Arduino-Tutorial-Control-Servo-Motor-Joystick/
Depois colocamos e realizamos a suas ligações na montagem relativas aos botões do tipo "Push Button", esta montagem terá 3 botões e cada um terá uma funcionalidade especifica, assim um dos botões montados na "Breadboard" será designado de M de "Mouse" e será responsável por activar e desactivar o "Joystick" inibindo a movimentação do "Mouse" no PC, o outro botão montado na "Breadboard" será designado por R de "Right" e terá a funcionalidade equivalente ao "Click" direito, já o botão incorporado no "Joystick" terá a funcionalidade equivalente ao "Click" esquerdo (Ver imagem acima).
Estes 3 botões serão ligados em paralelo às suas resistências de 1KΩ, sendo o botão do "Joystick" ligado através do pino SW e depois esse mesmo pino será ligado a um dos pinos de sinal digital do Arduino ficando no pino D2, já o botão R será também ligado a um dos pinos de sinal digital mas agora será ao pino D3 e por ultimo o botão M será ligado ao pino D4. Caso tenham duvidas ou queiram saber mais sobre os pinos de sinal digital como entradas vejam o seguinte tutorial:
Arduino Tutorial - Digital Input - Button - Monitor Serial
https://www.instructables.com/id/Arduino-Tutorial-Digital-Input-Button-Monitor-Seri/
Por fim, para que seja possível identificar mais facilmente a activação "Mouse", colocamos também na montagem um LED e a sua respectiva resistência de 1KΩ ficando estes ligados ao pino de sinal digital D13.
Instalação dos Push Button (Game Pad):
Na segunda "Breadboard" colocamos os restantes 6 "Push Button" e as respectivas resistências de 1KΩ criando assim os controlos do nosso "Game Pad", estes botões são todos ligados aos pinos de sinal digital do Arduino nomeadamente D5, D6, D7, D8, D9 e D10.
Para terminando só falta apenas atribuir as respectivas funcionalidades e identifica-los de forma a configurar as teclas do "Game Pad" para os nossos jogos mais adequadamente (Ver imagem acima).
Resumindo a montagem do lado esquerdo ficará a funcionar como um comando idêntico a de um antigo NINTENDO e a montagem do lado direito como um simples "Mouse".
Código
Para terminarmos a montagem ligamos o cabo Micro USB, sendo assim apenas necessário carregar o código no Arduino. Antes de carregarmos o código é necessário confirmar se estão instaladas as "Drives" do Arduino MICRO no nosso PC, para que este possa ser identificado como um dispositivo periférico.
Normalmente estas "Drives" são instaladas automaticamente assim que ligamos o Arduino ao PC, pois os sistemas operativos mais recentes já têm essas "Drives" inseridas no sistema, mas caso estejam a utilizar um sistema operativo mais antigos podem instalar-las manualmente (Ver ficheiro abaixo).
Bem estando as "Drives" correctamente instaladas, vamos abrir o programa do Arduino e de seguida configura-lo para este funcione com o tipo de Arduino que estamos a utilizar e finalmente carregar o código.
Vamos então agora explicar os detalhes do nosso código, como sempre começamos por importar as bibliotecas necessárias para a nossa montagem, neste caso vamos importar as bibliotecas Mouse.h e Keyboard.h, estas bibliotecas foram concebidas especificamente para este tipo de projectos onde queremos criar dispositivos periféricos de controlo para PC.
Para trabalhar com esta biblioteca Mouse.h é necessário também declarar e nomear as variáveis para as definições de parâmetros do "Mouse", nestas variáveis serão atribuídos valores que alteram a sua sensibilidade de movimento, tendo cada um destes parâmetros uma finalidade especifica como o tempo de resposta entre impulsos e a distancia percorrida entre impulsos.
Por fim é colocada em Setup() a função Mouse.begin() sendo esta responsável pela inicialização pelo sistema de controlo do "Mouse" no PC.
#include "Mouse.h" //Importar a "Mouse" library. //Definição dos parâmetros do Mouse: //Controla a velocidade de movimento do Mouse através do tempo (mSeg) de resposta entre impulsos: //(Colocar valor entre 5 e 56=(Rápido=Tempo_Resposta <28/Lento=Tempo_Resposta >28). int Tempo_resposta = 28; //Controla a velocidade de movimento do Mouse através da distância percorrida entre impulsos: //(Colocar valor entre 4 e 44=(Rápido=Distancia >22/Lento=Distancia <22). int Distancia = 22; //Controla a sensibilidade do Joystick através do valor de Sensibilidade: //(Colocar valor entre 4 e 20=(Maior=Sensibilidade >8/Menor=Sensibilidade <8). int Sensibilidade = Distancia / 8; //Determina a posição central do Joystick. int Posicao_Central = Distancia / 2; //Correr a função SETUP apenas uma vez após ser pressionado Reset: void setup(){ //Iniciar a função de controlo do Mouse: Mouse.begin(); }
Já na biblioteca Keyboard.h a atribuição das utilidades do teclado em cada um dos botões do nosso "Game Pad" podem dividir-se em 2 grupos distintos, um dos grupos será formado por todos os caracteres existentes no teclado do nosso PC, o outro grupo será formado por todos os comandos para cada uma das suas funcionalidades (Ver listas acima).
Da mesma forma que iniciamos o sistema de controlo do Mouse também colocamos em Setup() a função Keyboard.begin() mas agora para inicializar o controlo do teclado no PC.
Para controlar as funcionalidades atribuídas a cada um dos botões do nosso "Game Pad" basta colocar na função Loop() a activação dessa funcionalidade numa condição que permite verificar se esses são pressionados colocando logo de seguida a função Keyboard.press(). Agora para desactivar essa funcionalidade quando deixamos de premir esse mesmo botão basta colocamos no final a função Keyboard.releaseAll().
#include "Keyboard.h" //Importar a "Keyboard" library. //Correr a função SETUP apenas uma vez após ser pressionado Reset: void setup(){ Keyboard.begin(); } //Correr a função LOOP repetidamente: void loop(){ //Funções para o GAME PAD: //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao) == LOW){ //Activa um carácter ou funcionalidade do teclado. Keyboard.press(KEY_LEFT_ARROW); //Determina o tempo (mSeg) entre acções das teclas do teclado. delay(150); //Desactiva as teclas do teclado. Keyboard.releaseAll(); }
Um pouco mais complexas são as condições para o controlo do "Mouse", em primeiro lugar na função Loop() teremos de realizar a leitura e respectivos cálculos dos valores enviados pelo "Joystick" em cada um dos eixos X e Y, só depois é realizado o controlo do "Mouse" no PC, através da função Mouse.move(), esta função irá movimentar o "Mouse" irá movimentar a quantidade de movimento determinada anteriormente, tornando-se assim possível visualizar esse movimento no écran.
De seguida, colocamos as condições para a activação das funcionalidades dos botões do "Mouse", para isso activamos essa funcionalidade sempre que o seu respectivo botão é pressionado, através da função Mouse.press() que no caso do "Mouse" será apenas o botão esquerdo ou o direito.
Não nos podemos esquecer que no final da função Loop() está um dos principais parâmetros do "Mouse" que é o tempo de resposta em mSeg entre os impulsos de movimento, ficando assim responsável pela sua velocidade de movimento, ou seja, será mais rápido quanto menor for este valor e consequentemente mais sensível.
//Correr a função LOOP repetidamente: void loop(){ //Realiza a leitura dos eixos do Joystick através dos pinos do Arduino atribuídos: int xReading = readAxis(Pino_Joystick_X); int yReading = readAxis(Pino_Joystick_Y); //Começa a movimentação do Mouse (Eixo X, Eixo Y e Roda de Scroll): Mouse.move(xReading, yReading, 0); //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao) == LOW){ //Se o botão for pressionado: if (!Mouse.isPressed(MOUSE_LEFT)){ //Activa uma funcionalidade do Mouse. Mouse.press(MOUSE_LEFT); } } else { //Se o botão não for pressionado: if (Mouse.isPressed(MOUSE_LEFT)){ //Desactiva uma funcionalidade do Mouse. Mouse.release(MOUSE_LEFT); } } //Controla a velocidade de movimento do Mouse através do tempo (mSeg): delay(Tempo_Resposta); } }
No final do nosso código encontramos tanto a leitura como os cálculos para determinação da distância percorrida pelo "Mouse" entre impulsos, esta leitura e respectivos cálculos são efectuados em cada um dos eixos individualmente e alternadamente, utilizando os valores atribuídos às variáveis de definições inicialmente.
Em primeiro lugar é realizada a respectiva leitura do eixo X ou Y do nosso "Joystick", controlando assim a quantidade de movimento que desejamos que o "Mouse" se movimente. Estando esse valor determinado, que estará compreendido entre 0 e 1023, utilizamos a função map() que irá relacionar este intervalo de valores com o intervalo de 0 e 22, este ultimo é dos valores atribuídos inicialmente no nosso código, sendo este especificamente o valor da variável Distância (Ver Cálculos acima).
Agora vamos calcular a quantidade de movimento que será executada no écran, como também a sua direcção, ou seja, cima, baixo, esquerda ou direita, através da subtracção do valor de leitura obtido estando este já mapeado pelo valor da segunda variável definida inicialmente que é o valor da variável Posição Central.
Assim este cálculo determinará a direcção desse movimento, pois quando o seu resultado tiver valores negativos será atribuída uma direcção (Por exemplo: Cima ou Esquerda), já quando ao resultado tiver valores positivos será atribuída a direcção contraria (Por exemplo: Baixo ou Direita). Quanto à quantidade de movimento será maior quanto mais afastado estiver de 0 (zero) estiver esse valor (Ver Cálculos acima).
//Definição do Movimento do Mouse através a biblioteca "Mouse.h". //A biblioteca "Mouse.h" altera o valor da variável "Eixos" //entre 0 e 1 alternado a leitura dos eixos do Joystick. int readAxis(int Eixos){ //Realiza a leitura dos eixos do Joystick um de cada vez. int Leitura_Joystick = analogRead(Eixos); //Relaciona os valores de Leitura dos eixos Joystick com os valores de Distancia. Leitura_Joystick = map(Leitura_Joystick, 0, 1023, 0, Distancia); //Determina o valor de Movimento do Mouse. int Movimento_Mouse = Leitura_Joystick - Posicao_Central; //Se o valor de Movimento for inferior ao valor mínimo de Sensibilidade. if (abs(Movimento_Mouse) < Sensibilidade){ //Coloca o valor de movimento. Movimento_Mouse = 0; } //Realiza o Movimento do Mouse. return Movimento_Mouse; }
Como o nosso "Joystick" tem um ponto central de descanso e a sua precisão de movimento é um pouco reduzida, pode existir alguma movimentação indesejável quando este se encontra nesse mesmo ponto. Para eliminar este eventualidade colocamos uma ultima condição que permite a existência de movimento apenas quando esse valor for superior ao valor da variável Sensibilidade.
Visto que o valor de movimento pode ser positivo ou negativo e o valor de sensibilidade atribuído é apenas positivo utilizamos a função matemática abs(), ou seja, esta função determina o valor absoluto, o que na prática para este caso especifico irá devolver como resultado o valor absoluto do valor calculado de movimento do "Mouse" tornando os valor negativos em positivos e mantendo o positivos como positivos.
Isto torna assim possível e lógica a comparação de valores nesta condição devolvendo um valor de movimento igual a 0 (zero) caso esse valor seja inferior ao da sensibilidade atribuído ao nosso "Joystick" (Ver Cálculos acima).
#include "Mouse.h" //Importar a "Mouse" library. #include "Keyboard.h" //Importar a "Keyboard" library. //Variáveis para controlo do MOUSE: int Activacao_Mouse = 0; //Variável para a activação do Mouse. int Pino_Botao_Act_Mouse = 4; //Variável para selecção do pino do botão de activação do Mouse. int Pino_LED_Activar_Mouse = 13; //Variável para selecção do pino do LED de indicação de activação do Mouse. int Pino_Botao_Joysitck = 2; //Variável para selecção do pino do botão esquerdo do Mouse. int Pino_Botao_Direito_Mouse = 3; //Variável para selecção do pino do botão direito do Mouse. int Pino_Joystick_X = A0; //Variável para selecção do pino Joystick no eixo X. int Pino_Joystick_Y = A1; //Variável para selecção do pino Joystick no eixo Y. //Definição dos parâmetros do Mouse: //Controla a velocidade de movimento através do tempo (mSeg) de resposta entre impulsos: int Tempo_Resposta = 28; //(Colocar valor entre 5 e 56=(Rápido=Tempo_Resposta <28/Lento=Tempo_Resposta >28). //Controla a velocidade de movimento do Mouse através da distância percorrida entre impulsos: int Distancia = 22; //(Colocar valor entre 4 e 44=(Maior=Distancia >22/Menor=Distancia <22). //Controla a sensibilidade do Joystick através do valor de Sensibilidade: int Sensibilidade = Distancia/8; //(Colocar valor entre 4 e 20=(Maior=Sensibilidade >8/Menor=Sensibilidade <8). //Determina a posição central do Joystick. int Posicao_Central = Distancia / 2; //Variáveis para controlo do GAME PAD: int Pino_Botao_1 = 10; //Variável para selecção do pino do botão seta esquerda do teclado. int Pino_Botao_2 = 9; //Variável para selecção do pino do botão seta direita do teclado. int Pino_Botao_3 = 8; //Variável para selecção do pino do botão seta cima do teclado. int Pino_Botao_4 = 7; //Variável para selecção do pino do botão seta direita do teclado. int Pino_Botao_5 = 6; //Variável para selecção do pino do botão tecla "A" do teclado. int Pino_Botao_6 = 5; //Variável para selecção do pino do botão tecla "B" do teclado. //Definição das funções das teclas do Teclado: char Botao_1 = KEY_LEFT_ARROW; char Botao_2 = KEY_DOWN_ARROW; char Botao_3 = KEY_UP_ARROW; char Botao_4 = KEY_RIGHT_ARROW; char Botao_5 = 'a'; char Botao_6 = 'b'; //Correr a função SETUP apenas uma vez após ser pressionado Reset: void setup(){ //Definição dos tipos de pinos de sinal digital (Saída ou Entrada): pinMode(Pino_Botao_Act_Mouse, INPUT); pinMode(Pino_LED_Activar_Mouse, OUTPUT); pinMode(Pino_Botao_Joysitck, INPUT); pinMode(Pino_Botao_Direito_Mouse, INPUT); pinMode(Pino_Botao_1, INPUT); pinMode(Pino_Botao_2, INPUT); pinMode(Pino_Botao_3, INPUT); pinMode(Pino_Botao_4, INPUT); pinMode(Pino_Botao_5, INPUT); pinMode(Pino_Botao_6, INPUT); //Iniciar a função de controlo do Mouse e teclado: Mouse.begin(); Keyboard.begin(); } //Correr a função LOOP repetidamente: void loop(){ //Funções para o GAME PAD: //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_1) == LOW){ //Activa o botão Seta Esquerda do teclado. Keyboard.press(Botao_1); //Determina o tempo (mSeg) entre acções das teclas do teclado. delay(150); //Desactiva as teclas do teclado. Keyboard.releaseAll(); } //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_2) == LOW){ //Activa o botão Seta Baixo do teclado. Keyboard.press(Botao_2); //Determina o tempo (mSeg) entre acções das teclas do teclado. delay(150); //Desactiva as teclas do teclado. Keyboard.releaseAll(); } //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_3) == LOW){ //Activa o botão Seta Cima do teclado. Keyboard.press(Botao_3); //Determina o tempo (mSeg) entre acções das teclas do teclado. delay(150); //Desactiva as teclas do teclado. Keyboard.releaseAll(); } //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_4) == LOW){ //Activa o botão Seta Direita do teclado. Keyboard.press(Botao_4); //Determina o tempo (mSeg) entre acções das teclas do teclado. delay(150); //Desactiva as teclas do teclado. Keyboard.releaseAll(); } //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_5) == LOW){ //Activa o botão tecla letra A do teclado. Keyboard.press(Botao_5); //Determina o tempo (mSeg) entre acções das teclas do teclado. delay(150); //Desactiva as teclas do teclado. Keyboard.releaseAll(); } //Se a leitura do pino botão for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_6) == LOW){ //Activa o botão tecla letra B do teclado. Keyboard.press(Botao_6); //Determina o tempo (mSeg) entre acções das teclas do teclado. delay(150); //Desactiva as teclas do teclado. Keyboard.releaseAll(); } //Funções para o Mouse: //Se a leitura do pino botão de activação do Mouse for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_Act_Mouse) == LOW){ //Altera o valor da variavel para um valor oposto. Activacao_Mouse = !Activacao_Mouse; //Atraso para o próximo passo: delay(500); //Condição para activação do Mouse. if (Activacao_Mouse == 1){ //Liga o LED (HIGH é nível alto): digitalWrite(Pino_LED_Activar_Mouse, HIGH); } //Condição para desactivação do Mouse. else if (Activacao_Mouse == 0){ //Desliga o LED (LOW é nível baixo): digitalWrite(Pino_LED_Activar_Mouse, LOW); } } //Realiza a leitura dos eixos do Joystick através dos pinos do Arduino atribuídos: int xReading = readAxis(Pino_Joystick_X); int yReading = readAxis(Pino_Joystick_Y); //Se o Mouse for activado: if (Activacao_Mouse){ //Começa a movimentação do Mouse (Eixo X, Eixo Y, Roda de Scroll): Mouse.move(xReading, yReading, 0); //Se a leitura do pino botão esquerdo integrado no Joystick for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_Joysitck) == LOW){ //Se o botão esquerdo do Mouse for pressionado: if (!Mouse.isPressed(MOUSE_LEFT)){ //Activa o botão esquerdo do Mouse. Mouse.press(MOUSE_LEFT); } } else { //Se o botão do Mouse esquerdo não for pressionado: if (Mouse.isPressed(MOUSE_LEFT)){ //Desactiva o botão esquerdo do Mouse. Mouse.release(MOUSE_LEFT); } } //Se a leitura do pino botão direito do Mouse for igual a LOW ou nível baixo: if (digitalRead(Pino_Botao_Direito_Mouse) == LOW){ //Se o botão direito do Mouse for pressionado: if (!Mouse.isPressed(MOUSE_RIGHT)){ //Ativa o botão direito do Mouse. Mouse.press(MOUSE_RIGHT); } } else { //Se o botão do Mouse direito for pressionado: if (Mouse.isPressed(MOUSE_RIGHT)){ //Desactiva o botão direito do Mouse. Mouse.release(MOUSE_RIGHT); } } //Controla a velocidade de movimento do Mouse através do tempo (mSeg) de resposta entre impulsos: delay(Tempo_Resposta); } } //Definição do Movimento do Mouse através a biblioteca "Mouse.h". //A biblioteca "Mouse.h" altera o valor da variável "Eixos" entre 0 e 1 alternado a leitura dos eixos do Joystick. int readAxis(int Eixos){ //Realiza a leitura dos eixos do Joystick um de cada vez. int Leitura_Joystick = analogRead(Eixos); //Relaciona os valores de Leitura dos eixos Joystick com os valores de Distancia. Leitura_Joystick = map(Leitura_Joystick, 0, 1023, 0, Distancia); //Determina o valor de Movimento do Mouse. int Movimento_Mouse = Leitura_Joystick - Posicao_Central; //Se o valor de Movimento do Mouse for inferior de Sensibilidade. if (abs(Movimento_Mouse) < Sensibilidade){ //Coloca o valor de movimento. Movimento_Mouse = 0; } //Realiza o Movimento do Mouse. return Movimento_Mouse; }
Para saber mais ou caso tenham dúvidas sobre estas e outras referências no código, vejam a sua explicação detalhada no site oficial do Arduino, através da ligação https://www.arduino.cc/en/Reference/HomePage.
Procurem os nossos tutoriais acerca do Arduino, onde explicamos diversas montagens como também o funcionamento dos seus componentes e já agora visitem o nosso canal no Youtube, Instagram, Facebook ou Twitter.
Abraço e bons projectos.