#include <Adafruit_CircuitPlayground.h>
#include <Adafruit_Circuit_Playground.h>
#include <Keyboard.h>
#include <KeyboardLayout.h>
#include <Keyboard_da_DK.h>
#include <Keyboard_de_DE.h>
#include <Keyboard_es_ES.h>
#include <Keyboard_fr_FR.h>
#include <Keyboard_it_IT.h>
#include <Keyboard_sv_SE.h>
// Final Team 1
// Peter Ochoa & Luke Bono
// Controller Description + Mappings:
// (+ and - vary depending on the switch toggle as we have an Ambidextrous mode for both L and R handed users)
// Accelerometer Y+ = "Tilt Forward" / Right Arrow Key (for L hand, inverse for R hand)
// Accelerometer Y- = "Tilt Backward" / Left Arrow Key (for L hand, inverse for R hand)
// Accelerometer Z+ = "Jump" / Space Bar (for L hand, inverse for R hand)
// Ultrasonic "Close" = "Forward" / Up Arrow Key (0-7cm)
// Ultrasonic "Far" = "Backward" / Down Arrow Key (10-15cm)
// Distances in cm for 7 and 10 are intentionally left blank to account for misinput by the player and to prevent accidental key inputs=
// Double Tap = "Eject" / Z
// pin numbers
const int trigPin = A2;
const int echoPin = A3;
const int btnA = 4; // Menu Button for pausing or restarting
const int btnB = 5; // Button for pressing 'R' to restart during Menu Button press
const int flipper = 7; // Determines if the Code runs in Left or right-handed mode for the accessibility of all users! :)
// Tap Variables
const int click = 120;
// Accelerometer Variables
float accelX;
float accelY;
float accelZ;
float flat;
float threshold = 5; // minimum amount of movement to trigger input from accelerometer
int jumpTimer = -1; // ensures that after a jump input is triggered, a tap or another jump can't be triggered for half a second
// Ultrasonic Variables
bool trig; // send message to ultrasound sensor, or not
float echo;
float distanceCM;
float closeMinCM = 0; float closeMaxCM = 7;
float farMinCM = 10; float farMaxCM = 15;
// Misc. Variables
int debounce = 100; // TEMP
bool test = false;
bool killcode = false;
bool isLeft = false;
// put your setup code here, to run once:
void setup() {
CircuitPlayground.begin();
// set in and out pins
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(btnA, INPUT_PULLDOWN);
pinMode(btnB, INPUT_PULLDOWN);
pinMode(flipper, INPUT_PULLUP);
// Begin
Keyboard.begin();
Serial.begin(9600);
// Initialize
calibrate();
}
// Runs at the start & reset of the CPE
void calibrate() {
// Release all keys
Keyboard.releaseAll();
// Stop voltage in the Trigger Pin
digitalWrite(trigPin, LOW);
// Determine if inputs should be interpreted for the left arm or right arm
if (digitalRead(flipper) == HIGH) {
isLeft = true;
}
else {
isLeft = false;
}
// Sets the current orientation of the CPE as "flat", and the accelerometer inputs are adjusted based on this
// (If the controller is on the left hand, usually the CPE isn't flat)
flat = accelY = CircuitPlayground.motionY();
// Sets up the booleans for the kill function
test = false;
killcode = false;
// Allow double taps to trigger the tapTime function
CircuitPlayground.setAccelTap(2, click);
attachInterrupt(digitalPinToInterrupt(CPLAY_LIS3DH_INTERRUPT), tapTime, FALLING);
// Audio signifier of calibration
CircuitPlayground.playTone(50, 100, true);
delay(10);
CircuitPlayground.playTone(50, 100, true);
delay(debounce);
}
// Triggers when the player taps, triggers kill
void tapTime(void) {
// Ensures the player isn't jumping
if (jumpTimer <= 0) {
killcode = true;
}
}
// Triggers after tapTime, prevents any inputs, except menu buttons
// (This is so tapping doesn't overlap with jumping. When you eject you are rendered useless anyways in game)
void kill(void) {
Keyboard.releaseAll();
Keyboard.press('z'); // press Z [EJECT]
delay(2 * debounce);
Keyboard.release('z');
delay(debounce);
// Stop double tap triggers
CircuitPlayground.setAccelTap(0, click);
// Stop the input code & prevent this code from running again
test = true;
killcode = false;
// Turn off all keys
Keyboard.releaseAll();
}
// put your main code here, to run repeatedly:
void loop() {
// PAUSE
if (digitalRead(btnA) == HIGH) {
Serial.println("tab");
Keyboard.press(KEY_TAB);
delay(debounce * 2);
Keyboard.release(KEY_TAB);
}
// RESTART (if paused)
if (digitalRead(btnB) == HIGH) {
Serial.println("r");
Keyboard.press('r');
delay(debounce * 2);
Keyboard.release('r');
calibrate();
}
// Triggers kill() after a tapTime
if(killcode){
kill();
}
// Will run until kill() is triggered
if (!test) {
// GET INPUTS
// send message to distance sensor for 10 milliseconds
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
echo = pulseIn(echoPin, HIGH);
distanceCM = (echo/2) / 29.1;
// get values from the accelerometer
accelX = CircuitPlayground.motionX();
accelY = CircuitPlayground.motionY();
accelZ = CircuitPlayground.motionZ();
// Adjusts values so we can determine rotation 180 degrees left and right from the current position
if (accelZ < 0) { // if the CPE is upside down
if (accelY >= 0) {
accelY = accelY + 10;
}
else {
accelY = accelY - 10;
}
}
// INTERPRET INPUTS
if (isLeft) {
// if the accelerometer Y is positive (if tilting right)
if (accelY > (flat + threshold)) {
Keyboard.press(KEY_RIGHT_ARROW); // release RIGHT ARROW [TILT BACKWARDS]
Keyboard.release(KEY_LEFT_ARROW); // press LEFT ARROW [TILT FORWARDS]
}
// if the accelerometer Y is negative (if tilting left)
else if (accelY < (flat - threshold)) {
Keyboard.press(KEY_LEFT_ARROW); // release LEFT ARROW [TILT BACKWARDS]
Keyboard.release(KEY_RIGHT_ARROW); // press RIGHT ARROW [TILT FORWARDS]
}
// if little to no accelerometer input (if no tilt)
else { // release both ARROW keys
Keyboard.release(KEY_LEFT_ARROW);
Keyboard.release(KEY_RIGHT_ARROW);
}
}
else { //isRight, inputs are inverse of isLeft
// (if tilting right)
if (accelY < (flat - threshold)) {
Keyboard.press(KEY_RIGHT_ARROW); // release RIGHT ARROW [TILT BACKWARDS]
Keyboard.release(KEY_LEFT_ARROW); // press LEFT ARROW [TILT FORWARDS]
}
// (if tiliting left)
else if (accelY > (flat + threshold)) {
Keyboard.press(KEY_LEFT_ARROW); // release LEFT ARROW [TILT BACKWARDS]
Keyboard.release(KEY_RIGHT_ARROW); // press RIGHT ARROW [TILT FORWARDS]
}
// (if no tilt)
else { // release both ARROW keys
Keyboard.release(KEY_LEFT_ARROW);
Keyboard.release(KEY_RIGHT_ARROW);
}
}
// if accelerometer Z is high (if hand raises up)
if (isLeft && accelZ > 11 && jumpTimer <= 0) {
Keyboard.press(' ');
jumpTimer = 500;
}
// isRight, inputs are inverse of isLeft (if hand raises up)
else if (!isLeft && accelZ < -11 && jumpTimer <= 0) {
Keyboard.press(' ');
jumpTimer = 500;
}
// if little to no accelerometer Z input (steady hand)
else {
Keyboard.release(' ');
}
// if ultrasonic senses something close to the accelerometer (0cm - 7cm)
if (distanceCM >= closeMinCM && distanceCM < closeMaxCM) {
Keyboard.press(KEY_UP_ARROW); // press UP ARROW [MOVE FORWARD]
Keyboard.release(KEY_DOWN_ARROW);
Serial.print(" forward");
}
// if ultrasonic senses something far from the accelerometer (10cm - 15cm)
else if (distanceCM >= farMinCM && distanceCM < farMaxCM) {
Keyboard.press(KEY_DOWN_ARROW); // press DOWN ARROW [MOVE BACKWARD]
Keyboard.release(KEY_UP_ARROW);
Serial.print(" backward");
}
// if ultrasonic senses something very far from the accelerometer or in the deadzone (7cm - 10cm && > 15cm)
else {
// release both ARROW keys
Keyboard.release(KEY_UP_ARROW);
Keyboard.release(KEY_DOWN_ARROW);
}
delay(debounce);
// if jumpTimer is on, jumpTimer decreases by the debounce time
if (jumpTimer > 0) {
jumpTimer = jumpTimer - debounce;
}
Serial.println("");
}
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.