概述
国内网络上关于手柄制作的资料感觉特别的少,最近参加华东交通大学校电赛,其中一个题目是运用单片机制作游戏手柄,所以我打算用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/
引脚连接方式:
// 左摇杆
// A0 --------------------------- VRX
// A1 --------------------------- VRY
// D14 --------------------------- SW
// 5V --------------------------- 5V
// GND --------------------------- GND
// 右摇杆
// A2 --------------------------- VRX
// A3 --------------------------- VRY
// D16 --------------------------- SW
// 5V --------------------------- 5V
// GND --------------------------- GND
// 4X4矩阵键盘
// D2 --------------------------- C1
// D3 --------------------------- C2
// D4 --------------------------- C3
// D5 --------------------------- C4
// D6 --------------------------- R1
// D7 --------------------------- R2
// D8 --------------------------- R3
// D9 --------------------------- R4
// 字符键盘指示灯
// D15 --------------------------- +
// 数字键盘指示灯
// D10 --------------------------- +
矩阵键盘的连接方式
实现的代码
#include <Keypad.h>
#include "Keyboard.h"
#include "Mouse.h"
const byte ROWS = 4; // four rows
const byte COLS = 4; // four columns
// Define the symbols on the buttons of the keypads.
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}; // Connect to the row pinouts of the keypad.
byte colPins[COLS] = {2, 3, 4, 5}; // Connect to the column pinouts of the keypad.
// Initialize an instance of class NewKeypad for each keypad setting - letter and number.
Keypad letterKeypad = Keypad( makeKeymap(letterKeys), rowPins, colPins, ROWS, COLS);
Keypad numberKeypad = Keypad( makeKeymap(numberKeys), rowPins, colPins, ROWS, COLS);
// Define pinouts of joysticks.
#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 keypad LED pins:
#define let_LED 15
#define num_LED 10
// Define dynamic keypad options - letter and number.
volatile boolean letter = true;
volatile boolean number = false;
// Define the data holders:
int joystick_left_x, joystick_left_y, joystick_left_button, joystick_right_x, joystick_right_y, joystick_right_button;
void setup() {
Serial.begin(9600);
// Initialize mouse and keyboard control:
Mouse.begin();
Keyboard.begin();
// Joystick button settings:
pinMode(SW_L, INPUT);
digitalWrite(SW_L, HIGH);
pinMode(SW_R, INPUT);
digitalWrite(SW_R, HIGH);
// Keypad LEDs:
pinMode(let_LED, OUTPUT);
digitalWrite(let_LED, HIGH);
pinMode(num_LED, OUTPUT);
digitalWrite(num_LED, LOW);
}
void loop() {
// Read joystick positions:
read_joysticks();
// Mouse:
mouse_controls();
// Keyboard:
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);
/*
Serial.print(joystick_right_x);
Serial.print("\t");
Serial.print(joystick_right_y);
Serial.print("\t\t");
Serial.print(joystick_right_button);
Serial.print("\n\n");
*/
}
void mouse_controls(){
// Move mouse according to the left joystick movements.
if(joystick_left_y > 700) Mouse.move(0, -15); // UP
if(joystick_left_y < 300) Mouse.move(0, 15); // DOWN
if(joystick_left_x > 700) Mouse.move(-15, 0); // LEFT
if(joystick_left_x < 300) Mouse.move(15, 0); // RIGHT
if(joystick_left_button == 0) Mouse.click(MOUSE_LEFT); // LEFT CLICK
if(joystick_right_button == 0) Mouse.click(MOUSE_RIGHT); // RIGHT CLICK
delay(100);
}
void keyboard_controls(){
// Change keypad settings (letter or number) and press modifier keys according to the right joystick movements.
if(joystick_right_y > 700){ Keyboard.press(KEY_RETURN); delay(100); Keyboard.releaseAll(); } // RETURN
if(joystick_right_y < 300){ Keyboard.press(KEY_BACKSPACE); delay(100); Keyboard.releaseAll(); } // BACKSPACE
if(joystick_right_x > 700){ letter = true; number = false; digitalWrite(let_LED, HIGH); digitalWrite(num_LED, LOW); } // Letter Keypad
if(joystick_right_x < 300){ letter = false; number = true; digitalWrite(let_LED, LOW); digitalWrite(num_LED, HIGH); } // Number Keypad
// Get the custom key depending on the selected keypad type - letter or number.
char customKey;
if(letter == true) customKey = letterKeypad.getKey();
if(number == true) customKey = numberKeypad.getKey();
// Write the custom key.
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] = {0};
char KeyboardNum_1[8] = {
'q',
'w',
'e',
'r',
'a',
's',
'd',
' ',
};
char KeyboardNum_2[8] = {
'y',
'u',
'i',
'o',
'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();
// Joystick button settings:
pinMode(SW_L, INPUT);
digitalWrite(SW_L, HIGH);
pinMode(SW_R, INPUT);
digitalWrite(SW_R, HIGH);
// Keypad LEDs:
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() {
// joystick positions:
read_joysticks();
// Mouse:
mouse_controls();
// Keyboard:
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);
/*
Serial.print(joystick_right_x);
Serial.print("\t");
Serial.print(joystick_right_y);
Serial.print("\t\t");
Serial.print(joystick_right_button);
Serial.print("\n\n");
*/
}
void mouse_controls(){
if(joystick_left_y > 700) Mouse.move(-15,0); // UP
if(joystick_left_y < 300) Mouse.move(15,0); // DOWN
if(joystick_left_x > 700) Mouse.move(0,15); // LEFT
if(joystick_left_x < 300) Mouse.move(0,-15); // RIGHT
if(joystick_left_button == 0) Mouse.click(MOUSE_LEFT); // LEFT CLICK
if(joystick_right_button == 0) Mouse.click(MOUSE_RIGHT); // RIGHT CLICK
}
void keyboard_controls(){
if(joystick_right_y > 700){ Keyboard.press(KEY_RETURN); delay(100); Keyboard.releaseAll(); } // RETURN
if(joystick_right_y < 300){ Keyboard.press(KEY_BACKSPACE); delay(100); Keyboard.releaseAll(); } // BACKSPACE
if(joystick_right_x > 700){
digitalWrite(let_LED, HIGH);
digitalWrite(num_LED, LOW);
for(int i=0;i<8;i++)
KeyboardNum[i] = KeyboardNum_1[i] ;
} // Letter Keypad
if(joystick_right_x < 300){
digitalWrite(let_LED, LOW);
digitalWrite(num_LED, HIGH);
for(int i=0;i<8;i++)
KeyboardNum[i] = KeyboardNum_2[i] ;
} // Number Keypad
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个引脚控制。