18 April 2021

Final Project: UNO Controller

 




    This is a controller made to work for the UNO game on Steam. The controller was conceptualized as one that used a card reader to perform all of the actions in the game, but complications with the reader resulted in what I have today. Instead of using actual cards to perform actions, I instead used gestures from different card games to fit the various actions in UNO. For example, to play a card you must place you hand over the CPE as though you're placing a card on a table. In order to draw a card, you have to tap the CPE because that's how you gesture to the dealer to deal you another card in Blackjack. Shouting to make the game call UNO is directly from UNO itself, as in real life you'd be doing that in that exact situation. The tilting isn't reminiscent of any game that I know of at the moment, but it did line up with how the game handles wild cards and I took advantage of that fact. When a player plays a wild card, the four colors appear in the cardinal directions, allowing you to choose what color you want to change to. Simply tilt the controller to whatever color you want, and it will become that color! Finally, the knob allows you to select cards or options with greater precision. The CPE lights up when you move the knob past its dead zone and turns off when it's in the dead zone. This functions as both feedback and as a preventative measure to keep the user from trying to select an option while the selection is moving. The play/confirm option only fires when the CPE detects no light, so if the CPE has lights on when the knob is in use it's theoretically impossible to move and select at the same time.  

    The enclosure of the controller is made to resemble a card tin, which is a common container for the real UNO card game. The black color is based on the classic UNO design, which was black and white with the four card colors. The white color is used with the CPE and the card colors appear when the knob is used. 

    Does this sound more interesting than scanning cards? I really liked the idea and would like to try it again with hopefully better results the next time.


// UNO controller by Devin Fitzgerald
// This code is used to create a controller using a potentiometer knob,
// a light sensor, accelerometer, and voice controls.

#include <Adafruit_CircuitPlayground.h> //Add CPE functions
#include <Keyboard.h> // Add keyboard library
#include <Wire.h>
#include <SPI.h>

#define CLICKTHRESHHOLD 120

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

int lightValue;             // light sensor value
int sensorValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)

float soundValue = 0.0;     // value that corresponds to the mic
float X,Y;                  // motion sensor values


void setup() {
  CircuitPlayground.begin(); // Initialize CPE library
  
  Keyboard.begin(); // Initialize the keyboard library
  
  CircuitPlayground.setAccelRange(LIS3DH_RANGE_2_G); // Sets sensitivity that tap must be to register
  
  CircuitPlayground.setAccelTap(1, CLICKTHRESHHOLD); // Single tap triggers effect.

  attachInterrupt(digitalPinToInterrupt(CPLAY_LIS3DH_INTERRUPT), tapTime, FALLING); // Funtion called when tap is detected.
}
 
void loop() {
  X = CircuitPlayground.motionX(); // X axis variable
  Y = CircuitPlayground.motionY(); // Y axis variable
 
  lightValue = CircuitPlayground.lightSensor(); // Light sensor variable
  
  // Take 10 milliseconds of sound data to calculate
  soundValue = CircuitPlayground.mic.soundPressureLevel(10);
  
  // read the analog in value:
  sensorValue = analogRead(analogInPin);
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 0, 1023, -127, 127);
 
  if(outputValue > 42){ 
    CircuitPlayground.setPixelColor(0, 100, 0, 0);
    CircuitPlayground.setPixelColor(1, 100, 0, 0);
    CircuitPlayground.setPixelColor(3, 50, 50, 0);
    CircuitPlayground.setPixelColor(4, 50, 50, 0);
    CircuitPlayground.setPixelColor(5, 0, 100, 0);
    CircuitPlayground.setPixelColor(6, 0, 100, 0);
    CircuitPlayground.setPixelColor(8, 0, 0, 100);
    CircuitPlayground.setPixelColor(9, 0, 0, 100);
    // Alongside visual flair, the colors on the CPE while the pot is in use prevent the player from playing or accepting while moving the selection.
    
    Keyboard.write(215); // Left arrow
    Serial.println("LEFT - Yellow"); 
    delay(500);
  }
  
  if(outputValue < -42){
    CircuitPlayground.setPixelColor(0, 100, 0, 0);
    CircuitPlayground.setPixelColor(1, 100, 0, 0);
    CircuitPlayground.setPixelColor(3, 50, 50, 0);
    CircuitPlayground.setPixelColor(4, 50, 50, 0);
    CircuitPlayground.setPixelColor(5, 0, 100, 0);
    CircuitPlayground.setPixelColor(6, 0, 100, 0);
    CircuitPlayground.setPixelColor(8, 0, 0, 100);
    CircuitPlayground.setPixelColor(9, 0, 0, 100);

    Keyboard.write(216); // Right arrow
    Serial.println("RIGHT - Blue");
    delay(500);
  }

  if(outputValue > -42 && outputValue < 42){
    CircuitPlayground.clearPixels(); // Lights turn off when the pot is not being used. This allows the player to confirm their selection.
  }

  if(soundValue > 90){ // Shout to call UNO for yourself or the opponent
    Keyboard.write(85); // U key
    Keyboard.write(67); // C key 
    Serial.println("UNO!");
    delay(500);
  }

  if(lightValue == 0){ //Cover the CPE in darkness to play a card.
    Keyboard.write(32); // Space bar
    Serial.println("SPACE - Play");
    delay(500);
  }

  if(X > 2){ //Tilt enclosure left
    Keyboard.write(215); // Left arrow
    Serial.println("LEFT - Blue");
    delay(500);
  }

  if(X < -2){ //Tilt enclosure right
    Keyboard.write(216); // Right arrow
    Serial.println("RIGHT - Yellow");
    delay(500);
  }

  if(Y > 0){ //Tilt enclosure down (Top toward you)
    Keyboard.write(217); // Down arrow
    Serial.println("DOWN - Red");
    delay(500);
  }

  if(Y < -2){ //Tilt enclosure up (Top away from you
    Keyboard.write(218); // Up arrow
    Serial.println("UP - Green");
    delay(500);
  }

}
void tapTime(void) {
  // When a tap is detected...
   Serial.print("CTRL - Draw ");
   Keyboard.write(128); // Control key
}



No comments:

Post a Comment

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