概述
国内网络上关于手柄制作的资料感觉特别的少,最近参加校电赛,其中一个题目是运用单片机制作游戏手柄,所以我打算用atmega32u4单片机运用arduino的ide来实现这些功能。下面的参考链接是我能找到的最符合要求的项目,但是这其中有很多的问题,我先把实现的流程和大家说,出现的问题我留在文章末尾。
参考链接
实现过程
用到的元件:
Arduino Pro Micro * 1
5个引脚的PS2游戏手柄 * 2
轻触按键 * 16
5mm绿色LED * 1
5mm蓝色LED * 1
220Ω电阻 * 2
Arduino IDE的配置
点击Tools > the Board selection tab > Boards Manager.
找到SparkFun AVR Boards package并下载
选择Sparkfun Pro Micro
在arduino官网下载Keypad库并安装
https://www.arduino.cc/reference/en/libraries/keypad/
引脚连接方式:
矩阵键盘的连接方式
实现的代码
#include <Keypad.h>
#include "Keyboard.h"
#include "Mouse.h"
const byte ROWS = 4;
const byte COLS = 4;
char letterKeys[ROWS][COLS] = {
{'e','a','r','i'},
{'o','t','n','s'},
{'p','m','h','w'},
{'l','c','u','d'}
};
char numberKeys[ROWS][COLS] = {
{'1','2','3','+'},
{'4','5','6','-'},
{'#','0','*','%'},
{'7','8','9','/'}
};
byte rowPins[ROWS] = {6, 7, 8, 9};
byte colPins[COLS] = {2, 3, 4, 5};
Keypad letterKeypad = Keypad( makeKeymap(letterKeys), rowPins, colPins, ROWS, COLS);
Keypad numberKeypad = Keypad( makeKeymap(numberKeys), rowPins, colPins, ROWS, COLS);
#define VRX_L A0
#define VRY_L A1
#define SW_L 14
#define VRX_R A2
#define VRY_R A3
#define SW_R 16
#define let_LED 15
#define num_LED 10
volatile boolean letter = true;
volatile boolean number = false;
int joystick_left_x, joystick_left_y, joystick_left_button, joystick_right_x, joystick_right_y, joystick_right_button;
void setup() {
Serial.begin(9600);
Mouse.begin();
Keyboard.begin();
pinMode(SW_L, INPUT);
digitalWrite(SW_L, HIGH);
pinMode(SW_R, INPUT);
digitalWrite(SW_R, HIGH);
pinMode(let_LED, OUTPUT);
digitalWrite(let_LED, HIGH);
pinMode(num_LED, OUTPUT);
digitalWrite(num_LED, LOW);
}
void loop() {
read_joysticks();
mouse_controls();
keyboard_controls();
}
void read_joysticks(){
joystick_left_x = analogRead(VRX_L);
joystick_left_y = analogRead(VRY_L);
joystick_left_button = digitalRead(SW_L);
joystick_right_x = analogRead(VRX_R);
joystick_right_y = analogRead(VRY_R);
joystick_right_button = digitalRead(SW_R);
}
void mouse_controls(){
if(joystick_left_y > 700) Mouse.move(0, -15);
if(joystick_left_y < 300) Mouse.move(0, 15);
if(joystick_left_x > 700) Mouse.move(-15, 0);
if(joystick_left_x < 300) Mouse.move(15, 0);
if(joystick_left_button == 0) Mouse.click(MOUSE_LEFT);
if(joystick_right_button == 0) Mouse.click(MOUSE_RIGHT);
delay(100);
}
void keyboard_controls(){
if(joystick_right_y > 700){ Keyboard.press(KEY_RETURN); delay(100); Keyboard.releaseAll(); }
if(joystick_right_y < 300){ Keyboard.press(KEY_BACKSPACE); delay(100); Keyboard.releaseAll(); }
if(joystick_right_x > 700){ letter = true; number = false; digitalWrite(let_LED, HIGH); digitalWrite(num_LED, LOW); }
if(joystick_right_x < 300){ letter = false; number = true; digitalWrite(let_LED, LOW); digitalWrite(num_LED, HIGH); }
char customKey;
if(letter == true) customKey = letterKeypad.getKey();
if(number == true) customKey = numberKeypad.getKey();
if (customKey){
Keyboard.write(customKey);
}
}
存在的问题
如果你只是跟着上面的步骤去制作的话,你会发现根本大不了游戏,因为键盘没有接地,单片机无法扫描,代码的倒数第九行的getkey()只会触发一次。但是启用引脚的pull up功能,然后把按键独立接地,这些功能就可以实现了,经过我几个夜晚的调试,最终完成了以下代码:
射击游戏:
#include <Key.h>
#include <Keypad.h>
#include <Mouse.h>
#include <Keyboard.h>
#define VRX_L A0
#define VRY_L A1
#define SW_L 14
#define VRX_R A2
#define VRY_R A3
#define SW_R 16
#define let_LED 15
#define num_LED 10
char KeyboardNum[8] = {
'q',
'w',
'e',
'r',
'a',
's',
'd',
' ',
};
int joystick_left_x, joystick_left_y, joystick_left_button, joystick_right_x, joystick_right_y, joystick_right_button;
void setup() {
Serial.begin(9600);
Mouse.begin();
Keyboard.begin();
pinMode(SW_L, INPUT);
digitalWrite(SW_L, HIGH);
pinMode(SW_R, INPUT);
digitalWrite(SW_R, HIGH);
pinMode(let_LED, OUTPUT);
digitalWrite(let_LED, HIGH);
pinMode(num_LED, OUTPUT);
digitalWrite(num_LED, LOW);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
}
void loop() {
read_joysticks();
mouse_controls();
keyboard_controls();
}
void read_joysticks(){
joystick_left_x = analogRead(VRX_L);
joystick_left_y = analogRead(VRY_L);
joystick_left_button = digitalRead(SW_L);
joystick_right_x = analogRead(VRX_R);
joystick_right_y = analogRead(VRY_R);
joystick_right_button = digitalRead(SW_R);
}
void mouse_controls(){
if(joystick_left_y > 700) Mouse.move(-15,0);
if(joystick_left_y < 300) Mouse.move(15,0);
if(joystick_left_x > 700) Mouse.move(0,15);
if(joystick_left_x < 300) Mouse.move(0,-15);
if(joystick_left_button == 0) Mouse.click(MOUSE_LEFT);
if(joystick_right_button == 0) Mouse.click(MOUSE_RIGHT);
}
void keyboard_controls(){
if(joystick_right_y > 700){ Keyboard.press(KEY_RETURN); delay(100); Keyboard.releaseAll(); }
if(joystick_right_y < 300){ Keyboard.press(KEY_BACKSPACE); delay(100); Keyboard.releaseAll(); }
if(joystick_right_x > 700){ digitalWrite(let_LED, HIGH); digitalWrite(num_LED, LOW); }
if(joystick_right_x < 300){ digitalWrite(let_LED, LOW); digitalWrite(num_LED, HIGH); }
if(digitalRead(2) == LOW) {Keyboard.press(KeyboardNum[0]);}
if(digitalRead(2)==HIGH){Keyboard.release(KeyboardNum[0]);}
if(digitalRead(3) == LOW) {Keyboard.press(KeyboardNum[1]);}
if(digitalRead(3)==HIGH){Keyboard.release(KeyboardNum[1]);}
if(digitalRead(4) == LOW) {Keyboard.press(KeyboardNum[2]);}
if(digitalRead(4)==HIGH){Keyboard.release(KeyboardNum[2]);}
if(digitalRead(5) == LOW) {Keyboard.press(KeyboardNum[3]);}
if(digitalRead(5)==HIGH){Keyboard.release(KeyboardNum[3]);}
if(digitalRead(6) == LOW) {Keyboard.press(KeyboardNum[4]);}
if(digitalRead(6)==HIGH){Keyboard.release(KeyboardNum[4]);}
if(digitalRead(7) == LOW) {Keyboard.press(KeyboardNum[5]);}
if(digitalRead(7)==HIGH){Keyboard.release(KeyboardNum[5]);}
if(digitalRead(8) == LOW) {Keyboard.press(KeyboardNum[6]);}
if(digitalRead(8)==HIGH){Keyboard.release(KeyboardNum[6]);}
if(digitalRead(9) == LOW) {Keyboard.press(KeyboardNum[7]);}
if(digitalRead(9)==HIGH){Keyboard.release(KeyboardNum[7]);}
}
格斗游戏
#include <Key.h>
#include <Keypad.h>
#include <Mouse.h>
#include <Keyboard.h>
#define VRX_L A0
#define VRY_L A1
#define SW_L 14
#define VRX_R A2
#define VRY_R A3
#define SW_R 16
#define let_LED 15
#define num_LED 10
char KeyboardNum[8] = {
'u',
'i',
'o',
'p',
'h',
'j',
'k',
'l',
};
int joystick_left_x, joystick_left_y, joystick_left_button, joystick_right_x, joystick_right_y, joystick_right_button;
void setup() {
Serial.begin(9600);
Mouse.begin();
Keyboard.begin();
pinMode(SW_L, INPUT);
digitalWrite(SW_L, HIGH);
pinMode(SW_R, INPUT);
digitalWrite(SW_R, HIGH);
pinMode(let_LED, OUTPUT);
digitalWrite(let_LED, HIGH);
pinMode(num_LED, OUTPUT);
digitalWrite(num_LED, LOW);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
}
void loop() {
read_joysticks();
mouse_controls();
keyboard_controls();
}
void read_joysticks(){
joystick_left_x = analogRead(VRX_L);
joystick_left_y = analogRead(VRY_L);
joystick_left_button = digitalRead(SW_L);
joystick_right_x = analogRead(VRX_R);
joystick_right_y = analogRead(VRY_R);
joystick_right_button = digitalRead(SW_R);
}
void mouse_controls(){
if(joystick_left_y > 700) { Keyboard.press(KEY_LEFT_ARROW); delay(100); Keyboard.releaseAll(); }
if(joystick_left_y < 300) { Keyboard.press(KEY_RIGHT_ARROW); delay(100); Keyboard.releaseAll(); }
if(joystick_left_x > 700) { Keyboard.press(KEY_DOWN_ARROW); delay(100); Keyboard.releaseAll(); }
if(joystick_left_x < 300) { Keyboard.press(KEY_UP_ARROW); delay(100); Keyboard.releaseAll(); }
if(joystick_left_button == 0) Mouse.click(MOUSE_LEFT);
if(joystick_right_button == 0) Mouse.click(MOUSE_RIGHT);
}
void keyboard_controls(){
if(joystick_right_y > 700){ Keyboard.press(KEY_RETURN); delay(100); Keyboard.releaseAll(); }
if(joystick_right_y < 300){ Keyboard.press(KEY_BACKSPACE); delay(100); Keyboard.releaseAll(); }
if(joystick_right_x > 700){ digitalWrite(let_LED, HIGH); digitalWrite(num_LED, LOW); }
if(joystick_right_x < 300){ digitalWrite(let_LED, LOW); digitalWrite(num_LED, HIGH); }
if(digitalRead(2) == LOW) {Keyboard.press(KeyboardNum[0]);}
if(digitalRead(2)==HIGH){Keyboard.release(KeyboardNum[0]);}
if(digitalRead(3) == LOW) {Keyboard.press(KeyboardNum[1]);}
if(digitalRead(3)==HIGH){Keyboard.release(KeyboardNum[1]);}
if(digitalRead(4) == LOW) {Keyboard.press(KeyboardNum[2]);}
if(digitalRead(4)==HIGH){Keyboard.release(KeyboardNum[2]);}
if(digitalRead(5) == LOW) {Keyboard.press(KeyboardNum[3]);}
if(digitalRead(5)==HIGH){Keyboard.release(KeyboardNum[3]);}
if(digitalRead(6) == LOW) {Keyboard.press(KeyboardNum[4]);}
if(digitalRead(6)==HIGH){Keyboard.release(KeyboardNum[4]);}
if(digitalRead(7) == LOW) {Keyboard.press(KeyboardNum[5]);}
if(digitalRead(7)==HIGH){Keyboard.release(KeyboardNum[5]);}
if(digitalRead(8) == LOW) {Keyboard.press(KeyboardNum[6]);}
if(digitalRead(8)==HIGH){Keyboard.release(KeyboardNum[6]);}
if(digitalRead(9) == LOW) {Keyboard.press(KeyboardNum[7]);}
if(digitalRead(9)==HIGH){Keyboard.release(KeyboardNum[7]);}
}
使用以上代码时,按键相对独立,8个按键分别由8个引脚控制。
成品图:
|