//Final Group 13
//Aiden Pain, Victor Farrulla
//Updated 4/24/26
#include <Adafruit_CircuitPlayground.h>
#include <Adafruit_Circuit_Playground.h>
#include <Mouse.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_hu_HU.h>
#include <Keyboard_it_IT.h>
#include <Keyboard_pt_PT.h>
#include <Keyboard_sv_SE.h>
/*
Pinouts:
12 = A0
6 = A1
9 = A2
10 = A3
3 = A4
2 = A5
0 = A6
1 = A7
*/
//declare constants to represent pins
const int DIST_TRIG_PIN = 0; //A6 - trigger
const int DIST_ECHO_PIN = 1; //A7 - echo
#define INTERACT_PIN A0 //A0 for interact button
#define ESCAPE_PIN A1 //A1 for escape button
#define POTY_PIN A4 //A4 for potentiometer
//declare constants to compare to analog read values
const int MOUSE_X_SENS = 200; //how fast the mouse moves left or right when tilted left or right
const int MOUSE_Y_SENS = 30; //how fast the mouse moves up or down when the knob is twisted up or down
const int soundSensitivity = 1; //how much higher than soundBaseLevel the attack activates
//declare variables for analog read values
long distRead;
float tiltX;
int tiltXmapped;
int micRead;
int interactRead;
int interactReadMapped;
int escapeRead;
int escapeReadMapped;
int soundBaseLevel; // initial sound level to compare sound level to, set in setup
int tiltXbase; //variable to compare current X tilt, set in setup
int distBase; //initial distance to compare ultrasonic sensor data to, set in setup
int distSprint; //if distance is less than this, sprint (set to distBase/2 in setup)
//previous checks so events don't fire multiple times per button press
int prevInteractRead = false;
int prevEscapeRead = false;
int prevMainSwitch = false;
// ----------------- //
// ----- SETUP ----- //
// ----------------- //
void setup() {
// start CircuitPlayground and Serial Monitor
CircuitPlayground.begin();
Serial.begin(9600);
//set pin modes for pins attached to sensor and buttons
pinMode(DIST_TRIG_PIN, OUTPUT);
pinMode(DIST_ECHO_PIN, INPUT);
pinMode(INTERACT_PIN, INPUT_PULLUP);
pinMode(ESCAPE_PIN, INPUT_PULLUP);
delay(2000); //wait for setup
//read current environment sound and set a variable to act as the baseline for microphone input
int sum = 0;
for (int i = 0; i < 10; i++){
sum += CircuitPlayground.mic.soundPressureLevel(10);
}
soundBaseLevel = sum / 10;
//set up ultrasonic sensor to get the controller's initial distance from the screen
digitalWrite(DIST_TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(DIST_TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(DIST_TRIG_PIN, LOW);
distBase = pulseIn(DIST_ECHO_PIN, HIGH);
distBase = (distBase/2)/29.1; //distance in centimeters
distSprint = distBase/2; //half the distance from the screen for sprint
tiltXbase = CircuitPlayground.motionX(); //get initial accelerometer X tilt
}
// ---------------- //
// ----- LOOP ----- //
// ---------------- //
void loop() {
//only run code if the switch is active
if(CircuitPlayground.slideSwitch() == true){
//user-defined functions to handle distance sensing, x-tilt sensing, microphone sensing, button inputs, and potentiometer inputs
DistanceSense();
TiltSense();
MicSense();
ButtonsCheck();
PotYCheck();
//sets prevMainSwitch to true as the CPX switch is switched on
prevMainSwitch = true;
}
//if the CPX switch was just switched off, release all keys
else if(prevMainSwitch){
Keyboard.releaseAll();
prevMainSwitch = false; //sets prevMainSwitch to false as the CPX switch is switched off
}
Serial.println("---");
delay(100); //debounce
}
// --------------------- //
// ----- FUNCTIONS ----- //
// --------------------- //
//function that handles ultrasonic sensor input in loop()
void DistanceSense(){
//set distRead to the value of the ultrasonic sensor's reported distance
digitalWrite(DIST_TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(DIST_TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(DIST_TRIG_PIN, LOW);
distRead = pulseIn(DIST_ECHO_PIN, HIGH);
Serial.print("distRead: ");
Serial.println(distRead);
distRead = (distRead/2)/29.1; //distance in centimeters
Serial.print("distBase: ");
Serial.println(distBase);
//map it so it's negative when leaning backward, positive when leaning forward, and zero for staying still (in relation to distBase)
//if distBase-distRead is negative, map to -1
//if distBase-distRead is around 0 (i.e. they're about equal), map to 0
//else, check distRead for sprint
int distMapped = map(distBase-distRead, -distBase, distBase, -1, 2);
//use if-else statements with that variable to press S if negative, W if positive, or neither if zero
//if mapped distance is negative, move backwards by pressing S (and release W too)
if(distMapped < 0){
Keyboard.press('s');
Keyboard.release('w');
}
//if mapped distance is zero, stop moving by releasing S and W
else if(distMapped == 0){
Keyboard.release('s');
Keyboard.release('w');
}
//else, if mapped distance is positive, release S and move forwards by pressing W
else{
Keyboard.release('s');
//if mapped distance is less than the sprint threshold, sprint by pressing shift
if(distRead < distSprint){
Keyboard.press('W');
} else {
Keyboard.press('w');
}
}
//regardless of direction, if farther away than distSprint, release shift
if(distRead > distSprint){
Keyboard.release(KEY_LEFT_SHIFT);
}
}
void TiltSense(){
//set tiltX to correspond to accelerometer x-axis input, and map to mouse move-friendly values
tiltX = CircuitPlayground.motionX();
tiltXmapped = map(tiltXbase - tiltX, -3, 3, -2, 2);
//send the mouse move signals, inverting the up/down axis represented by the X axis tilt
Mouse.move(-tiltXmapped*MOUSE_X_SENS, 0, 0);
Serial.print("tiltX: ");
Serial.println(tiltX);
Serial.print("tiltXmapped: ");
Serial.println(tiltXmapped);
}
void MicSense(){
//set micRead to the recorded microphone input
micRead = CircuitPlayground.mic.soundPressureLevel(10);
//if the microphone input is significantly higher than the environmental baseline, press left-click (to attack)
if(micRead > soundBaseLevel + soundSensitivity){
Mouse.click(MOUSE_LEFT);
}
}
void ButtonsCheck(){
//set interactRead to read whether the interact button is pressed
interactRead = analogRead(INTERACT_PIN);
interactReadMapped = map(interactRead, 0, 1023, 0, 1);
//if the voltage reads high and wasn't previously high, press the E key (to interact)
if(interactReadMapped && !prevInteractRead){
Keyboard.press('e');
}
else{
Keyboard.release('e');
}
//set the chin button's previous state (to compare to the next read)
prevInteractRead = interactReadMapped;
//set escapeRead to read whether the escape button is pressed
escapeRead = analogRead(ESCAPE_PIN);
escapeReadMapped = map(escapeRead, 0, 1023, 0, 1);
//if the voltage reads high and wasn't previously high, press the escape key (to get to the pause menu)
if(escapeReadMapped && !prevInteractRead){
Keyboard.press(KEY_ESC);
}
else{
Keyboard.release(KEY_ESC);
}
//set the chin button's previous state (to compare to the next read)
prevEscapeRead = escapeReadMapped;
}
//check potentiometer value for looking up and down
void PotYCheck(){
//read in potentiometer value and map to usable integers
int potYreading = analogRead(POTY_PIN);
int potYreadingMapped = map(potYreading, 0, 1023, -1, 2);
//if potentiometer is turned downward, look down
if(potYreadingMapped < 0){
Mouse.move(0, MOUSE_Y_SENS, 0);
}
//if potentiometer is turned upward, look up
else if(potYreadingMapped > 0){
Mouse.move(0, -MOUSE_Y_SENS, 0);
}
//if potentiometer is more or less in the middle, do not move the mouse up or down
Serial.println(potYreadingMapped); //debug print to make sure the controller is on and working
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.