PhysComp Final Project Documentation
Apex Legends Motion Controller
Concept: A handheld motion controller that replaces the mouse functions in Apex Legends.
Hardware: I used the Arduino Micro for it's native usb functions with a MPU 6050 accelerometer to mimic the movements of a mouse and control the camera movement. There are 3 buttons: one to control aiming, one to control shooting, and a button to turn around 180 degrees. When the game is not open, it can also just function as a mouse and control the cursor. Since it is just replacing the mouse it also functions in other games as well.
Final Product:
Code
---------------------------------------------------
#include <MPU6050.h>
#include <Wire.h>
#include <I2Cdev.h>
#include <Mouse.h>
#include <Keyboard.h>
MPU6050 mpu;
int16_t ax, ay, az, gx, gy, gz;
int16_t accx, accy, accz;
int vx, vy;
int TRIGGER_BUTTON = 5;
int AIM_BUTTON = 6;
int TURN_BUTTON = 8;
int lastTurnPushed = 0;
bool weaponModeOn = true;
float angle;
//code for smoothing input
int readIndex = 0;
const int numReadings = 20;
int angleReadings[numReadings];
int total = 0;
float averageAngle = 0.0;
int oldZ = 0;
int newZ = 0;
void setup() {
Serial.begin(115200);
Wire.begin();
mpu.initialize();
if (!mpu.testConnection()) {
while (1);
}
pinMode(TRIGGER_BUTTON, INPUT_PULLUP);
pinMode(AIM_BUTTON, INPUT_PULLUP);
pinMode(TURN_BUTTON, INPUT_PULLUP);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
angleReadings[thisReading] = 0;
}
}
void loop() {
int triggerPushed = digitalRead(TRIGGER_BUTTON);
int aimPushed = digitalRead(AIM_BUTTON);
int turnPushed = digitalRead(TURN_BUTTON);
total = total - angleReadings[readIndex];
angleReadings[readIndex] = angle;
total = total + angleReadings[readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0;
}
if (triggerPushed == HIGH) {
if (Mouse.isPressed()) {
Mouse.release();
}
} else {
Serial.println("trigger pushed");
Mouse.press();
}
if (aimPushed == HIGH) {
if (Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.release(MOUSE_RIGHT);
}
} else {
Serial.println("aim pushed");
Mouse.press(MOUSE_RIGHT);
}
if (turnPushed == HIGH) {
if (turnPushed != lastTurnPushed){
for(int i = 0; i < 32trrrr; i++){
Mouse.move(50,0);
}
}
}
lastTurnPushed = turnPushed;
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
mpu.getAcceleration(&accx, &accy, &accz);
oldZ = newZ;
vx = (gx + 900) / 150; // "+300" because the x axis of gyroscope give values about -350 while it's not moving. Change this value if you get something different using the TEST code, chacking if there are values far from zero.
vy = -(gz + 230) / 150; // same here about "-100"
Mouse.move(vx, vy);
Serial.println(vx);
angle = atan2((float) ay, (float) ~ax) * (180.0 / PI);
delay(20);
#include <Wire.h>
#include <I2Cdev.h>
#include <Mouse.h>
#include <Keyboard.h>
MPU6050 mpu;
int16_t ax, ay, az, gx, gy, gz;
int16_t accx, accy, accz;
int vx, vy;
int TRIGGER_BUTTON = 5;
int AIM_BUTTON = 6;
int TURN_BUTTON = 8;
int lastTurnPushed = 0;
bool weaponModeOn = true;
float angle;
//code for smoothing input
int readIndex = 0;
const int numReadings = 20;
int angleReadings[numReadings];
int total = 0;
float averageAngle = 0.0;
int oldZ = 0;
int newZ = 0;
void setup() {
Serial.begin(115200);
Wire.begin();
mpu.initialize();
if (!mpu.testConnection()) {
while (1);
}
pinMode(TRIGGER_BUTTON, INPUT_PULLUP);
pinMode(AIM_BUTTON, INPUT_PULLUP);
pinMode(TURN_BUTTON, INPUT_PULLUP);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
angleReadings[thisReading] = 0;
}
}
void loop() {
int triggerPushed = digitalRead(TRIGGER_BUTTON);
int aimPushed = digitalRead(AIM_BUTTON);
int turnPushed = digitalRead(TURN_BUTTON);
total = total - angleReadings[readIndex];
angleReadings[readIndex] = angle;
total = total + angleReadings[readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0;
}
if (triggerPushed == HIGH) {
if (Mouse.isPressed()) {
Mouse.release();
}
} else {
Serial.println("trigger pushed");
Mouse.press();
}
if (aimPushed == HIGH) {
if (Mouse.isPressed(MOUSE_RIGHT)) {
Mouse.release(MOUSE_RIGHT);
}
} else {
Serial.println("aim pushed");
Mouse.press(MOUSE_RIGHT);
}
if (turnPushed == HIGH) {
if (turnPushed != lastTurnPushed){
for(int i = 0; i < 32trrrr; i++){
Mouse.move(50,0);
}
}
}
lastTurnPushed = turnPushed;
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
mpu.getAcceleration(&accx, &accy, &accz);
oldZ = newZ;
vx = (gx + 900) / 150; // "+300" because the x axis of gyroscope give values about -350 while it's not moving. Change this value if you get something different using the TEST code, chacking if there are values far from zero.
vy = -(gz + 230) / 150; // same here about "-100"
Mouse.move(vx, vy);
Serial.println(vx);
angle = atan2((float) ay, (float) ~ax) * (180.0 / PI);
delay(20);
}
Comments
Post a Comment