18 April 2021

Final Project: RC Motion Controller for Art of Rally

 Picture

 Description

This is my game controller for Art of Rally. The conceptual model for the controller is based off the design of RC car controllers that uses a steering "wheel" and a trigger to move forward. A trigger is really just a different type of button, so instead I went with motion controls for controlling the acceleration and braking of the cars in-game. As such, this controller primarily uses the accelorometer on the CPE and a potentiometer hooked up to pin A1. I picked this as a conceptual model because even though Art of Rally has more realistic car physics and control than most other racing games, the perspective of the game and the graphics makes it look like you are playing with toy cars, or RC cars. As such, I figured what better way to control video game RC cars than with a RC video game controller.

The way the controller works is simple: tilting the controller forward accelerates the car, tilting it backwards brakes and reverses the car, and the wheel at the back, which is really a potentiometer connected to pin A1, controls the steering. There are several signifiers for each function of the controller: for accelerating and braking, there is a graphic on both sides of the controller showing a speedometer and which directions can the controller be tilted. The CPE also lights up, glowing green when the controller is tilting forward and the car is accelerating and red when the car is tilting backwards and the car is reversing. For the wheel, there is an arrow painted on top of the wheel to show which direction you are going in. This was necessary, as real RC controllers that use a steering 'wheel' similar to mine usually has the wheel snap back to its forward position automatically. Since the wheel on my controller is attached to a potentiometer, it was not really possible to add that kind of functionality. The arrow on top of the wheel gives the user a chance to know which way the car should be turning at a glance.

There is one problem with how the controller works: accelerating and braking/reversing works okay, but turning the car can be tricky. The potentiometer that's used for steering does not really have the same kind of fine control as a joystick or even as keys on a keyboard. You may be able to see it in the video, but the car can start making a right turn when I wanted to go left. I have tested multiple methods for adding more fine tuning to the steering, and what I wrote in the code below is the best solution I could find for the time that I had.

Question: Is there a better method for using the potentiometer to steer the car in-game than the one I posted below, or should I have picked a different type of sensor to control steering? Is so, what sensor should I have used and why?

Schematic


Code

// Final Project for Physical Computing - Art of Rally RC Controller
// DIG 3602
// Austin Acosta

// References to necessary libraries and definition of pin connected to potentiometer
#include <Adafruit_CircuitPlayground.h>
#include <Keyboard.h>
#define POTENPIN A1

// Variables to use for accelerometer and potentiometer input
float Y;
float poten;
int potenMapped;

void setup() {
  //Serial.begin(9600);       // This is used to ensure that the CPE was making the correct keypresses
  CircuitPlayground.begin();  // Turning on CircuitPlayground funtionality
  Keyboard.begin();           // Turning on Keyboard functionality
}

void loop() {
  Y = CircuitPlayground.motionY();              // Get Y-axis input from accelerometer
  poten = analogRead(POTENPIN);                 // Get potentiometer input from POTENPIN
  potenMapped = map(poten, 1, 1023, -2, 3);     // Map the poten value to fine-tune steering
 
//--------------------------------------------------------------
  if (CircuitPlayground.slideSwitch() == true)        // If the CPE switch is on
  {
      if (Y < -4.00)                                  // And the CPE is tilting forward
      {
        Keyboard.press('W');                          // Press "W" and light the CPE green
        CircuitPlayground.setPixelColor(0, 0x00FF00);
        CircuitPlayground.setPixelColor(1, 0x00FF00);
        CircuitPlayground.setPixelColor(2, 0x00FF00);
        CircuitPlayground.setPixelColor(3, 0x00FF00);
        CircuitPlayground.setPixelColor(4, 0x00FF00);
        CircuitPlayground.setPixelColor(5, 0x00FF00);
        CircuitPlayground.setPixelColor(6, 0x00FF00);
        CircuitPlayground.setPixelColor(7, 0x00FF00);
        CircuitPlayground.setPixelColor(8, 0x00FF00);
        CircuitPlayground.setPixelColor(9, 0x00FF00);   
      }
      else if (Y > 4.00)                            // And the CPE is tilting backward
      {
        Keyboard.press('S');                        // Press "S" and light the CPE red
        CircuitPlayground.setPixelColor(0, 0xFF0000);
        CircuitPlayground.setPixelColor(1, 0xFF0000);
        CircuitPlayground.setPixelColor(2, 0xFF0000);
        CircuitPlayground.setPixelColor(3, 0xFF0000);
        CircuitPlayground.setPixelColor(4, 0xFF0000);
        CircuitPlayground.setPixelColor(5, 0xFF0000);
        CircuitPlayground.setPixelColor(6, 0xFF0000);
        CircuitPlayground.setPixelColor(7, 0xFF0000);
        CircuitPlayground.setPixelColor(8, 0xFF0000);
        CircuitPlayground.setPixelColor(9, 0xFF0000);  
      }
      else                                          // If not, release both "W" and "S", and turn the CPE neopixels off
      {
        Keyboard.release('W');
        Keyboard.release('S');
        CircuitPlayground.clearPixels();
      }
//--------------------------------------------------------------
      if (potenMapped > 1)            // If the potenMapped value is more than 1
      {
        Keyboard.write('A');          // Press "A" once and wait 10 ms
        delay(10);
      }
      else if (potenMapped < -1)      // If the potenMapped value is less than -1
      {
        Keyboard.write('D');          // Press "D" once and wait 10 ms
        delay(10);
      }
  }
//--------------------------------------------------------------
  //Serial.println(potenMapped);      // This was used for testing how the potentiometer was working

 
    
}

Video




No comments:

Post a Comment

Note: Only a member of this blog may post a comment.