Created
December 14, 2021 20:37
-
-
Save ItsMichal/a0e3c76776388fc8ad6c5e681297bef3 to your computer and use it in GitHub Desktop.
Pressure Puncher Code!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* PressurePuncher Code v1 | |
* by Michal Bodzianowski - 2021 | |
*/ | |
//Library Imports | |
#include <Arduino_LSM6DS3.h> | |
#include <Adafruit_NeoPixel.h> | |
#include <map> | |
#include <MadgwickAHRS.h> | |
#include <SamdAudio.h> | |
#include <SdFat.h> | |
#include <SPI.h> | |
//Our pins- | |
// LED 9 | |
// SCK 13 | |
// MISO 12 | |
// MOSI 11 | |
// CS 10 | |
const uint8_t SD_CS_PIN = 10; //CS pin on the SD card reader | |
const unsigned int sampleRate = 41000; //Sample rate. All clips are 41khz mono | |
#define AUDIO_BUFFER_SIZE 1024 //Audio buffer size | |
#define NUM_AUDIOCHAN 4 //Audio channels. Default is 4. 0 is reserved for BG music. | |
#define SAMPLE_RATE 10 //Sample Rate for IMU | |
#define LED_PIN 9 //Pin for the LED strip | |
#define NUM_PIXELS 30 //Number of LED pixel | |
#define ALPHA 0.95 // Smoothing factor for input - 0-1, 0 more smooth, 1 less smooth | |
float ax,ay,az; //Raw accelerometer values | |
float gx,gy,gz; //Raw gyrometer values | |
// int degreesX = 0; //DEPREC | |
// int degreesY = 0; //DEPREC | |
//Tracks whether on cooldown so audio doesn't spam | |
bool cooldown = false; | |
//Current audio channel- we alternate | |
//so audios don't overwrite each other | |
int curChannel = 1; | |
//Global timer | |
int timer = 0; | |
//Smoothed Pitch, Yaw, and Roll values | |
float ppitch = 0, pyaw = 0, proll = 0; | |
float pitch = 0, yaw = 0, roll = 0; | |
int lastHit =0; | |
SamdAudio AudioPlayer; //The AudioPlayer object. | |
SdFat memory; //the sd card object to use for all our file access | |
Madgwick filter; // Madgwick Algorithm filter to interpret IMU values | |
Adafruit_NeoPixel ledStrip(NUM_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800); //LEDstrip object | |
//Using code reference from https://github.com/hydronics2/SamdAudio/blob/master/examples/play_wav_from_SD_card/play_wav_from_SD_card.ino | |
//First time setup | |
void setup() { | |
//Set SD card to output | |
pinMode(SD_CS_PIN, OUTPUT); | |
//Begin serial monitoring | |
Serial.begin(115200); | |
// while(!Serial); //DEBUG - comment for production | |
//Begin the madgwick filtering | |
filter.begin(SAMPLE_RATE); | |
// Initialize SD card | |
Serial.print("Initializing SD card..."); | |
//Look for SD card | |
bool sdGood = memory.begin(SD_CS_PIN, SD_SCK_MHZ(12)); | |
while ( !sdGood ) //this command blocks if there is no sd card inserted | |
{ | |
Serial.println(F("Unable To read SD card")); | |
delay(1000); | |
sdGood = memory.begin(SD_CS_PIN, SD_SCK_MHZ(12)); | |
} | |
Serial.println(F("SD Ready")); | |
// Set up AudioPlayer | |
Serial.print("Initializing SD card..."); | |
if (AudioPlayer.begin(sampleRate, NUM_AUDIOCHAN, AUDIO_BUFFER_SIZE) == -1) | |
{ | |
Serial.println(" failed!"); | |
return; | |
} | |
Serial.println(" done."); | |
//Play initial BGM | |
playInitialAudio(); | |
//Make IMU | |
if (!IMU.begin()) { | |
Serial.println("Failed to initialize IMU!"); | |
while (1); | |
} | |
//Begin LED Strip | |
ledStrip.begin(); | |
} | |
void loop() { | |
determineCooldown(); | |
readAngle(); | |
basicModeLoop(); | |
// lightLoop(); | |
timer++; | |
} | |
void playInitialAudio(){ | |
AudioPlayer.play("wiibox.wav", 0); | |
AudioPlayer.play("intro.wav", 3); | |
} | |
void determineCooldown(){ | |
//Cooldown checker | |
if(cooldown){ | |
cooldown = !offCooldown(); | |
}else{ | |
cooldown = detectHit(); | |
} | |
} | |
//Code from woolseyworkshop.com/2020/02/12/using-the-arduino_lsm6ds3-library-to-access-the-arduino-uno-wifi-rev2-imu/ | |
void readAngle(){ | |
static unsigned long previousTime = millis(); | |
unsigned long currentTime = millis(); | |
if (currentTime - previousTime >= 1000/SAMPLE_RATE) { | |
// printValues(); //DEBUG | |
printRotationAngles(); | |
previousTime = millis(); | |
} | |
} | |
//Audio Helper function | |
void playAudio(const char* audioName){ | |
AudioPlayer.play(audioName, curChannel); | |
curChannel++; | |
if(curChannel > NUM_AUDIOCHAN - 1){ | |
curChannel = 1; | |
} | |
} | |
//Print the rotation angles for debugging | |
void printRotationAngles() { | |
char buffer[5]; | |
float ax, ay, az; | |
float gx, gy, gz; | |
if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable() | |
&& IMU.readAcceleration(ax, ay, az) && IMU.readGyroscope(gx, gy, gz)) { | |
filter.updateIMU(gx, gy, gz, ax, ay, az); | |
proll = roll; | |
ppitch = pitch; | |
pyaw = yaw; | |
//Weighted | |
roll = filter.getRoll() * ALPHA + (1-ALPHA) * roll; | |
pitch = filter.getPitch() * ALPHA + (1-ALPHA) * pitch; | |
yaw = filter.getYaw() * ALPHA + (1-ALPHA) * yaw; | |
// Serial.print("Roll = "); | |
// Serial.print(abs(proll-roll)); | |
// Serial.print(" °, "); | |
// Serial.print("Pitch = "); | |
// Serial.print(abs(ppitch-pitch)); | |
// Serial.print(" °, "); | |
// Serial.print("Yaw = "); | |
// Serial.print(abs(pyaw-yaw)); | |
// Serial.println(" °"); | |
} | |
} | |
bool offCooldown(){ | |
if(abs(pyaw-yaw) < 15 && abs(proll-roll) < 15){ | |
return true; | |
}else{ | |
return false; | |
} | |
} | |
bool detectHit(){ | |
if((abs(pyaw-yaw) > 25 && abs(pyaw-yaw) < 200) || (abs(proll-roll) > 25 && abs(proll-roll) < 200)){ | |
return true; | |
}else{ | |
return false; | |
} | |
} | |
void lightAllLEDs(int r, int g, int b){ | |
for(int i = 0; i < NUM_PIXELS; i++){ | |
ledStrip.setPixelColor(i,r,g,b); | |
} | |
ledStrip.show(); | |
} | |
void lightLEDRange(int r, int g, int b, int start, int end){ | |
for(int i = start; i < end; i++){ | |
ledStrip.setPixelColor(i,r,g,b); | |
} | |
ledStrip.show(); | |
} | |
int curLed = 0; | |
int curHue = 0; | |
void lightLoop(){ | |
// if(timer % 500 == 0){ | |
int H=curHue; | |
int S=100; | |
int V=100; | |
float s = S/100; | |
float v = V/100; | |
float C = s*v; | |
float X = C*(1-abs(fmod(H/60.0, 2)-1)); | |
float m = v-C; | |
float r,g,b; | |
if(H >= 0 && H < 60){ | |
r = C,g = X,b = 0; | |
} | |
else if(H >= 60 && H < 120){ | |
r = X,g = C,b = 0; | |
} | |
else if(H >= 120 && H < 180){ | |
r = 0,g = C,b = X; | |
} | |
else if(H >= 180 && H < 240){ | |
r = 0,g = X,b = C; | |
} | |
else if(H >= 240 && H < 300){ | |
r = X,g = 0,b = C; | |
} | |
else{ | |
r = C,g = 0,b = X; | |
} | |
int R = (r+m)*255; | |
int G = (g+m)*255; | |
int B = (b+m)*255; | |
// Serial.println("DEBUG"); | |
// Serial.println(R); | |
// Serial.println(G); | |
// Serial.println(B); | |
lightLEDRange(R, G, B, 0, 30); | |
curHue+=20; | |
curLed++; | |
if(curHue > 360){ | |
curHue =0; | |
} | |
if(curLed > NUM_PIXELS-1){ | |
curLed =0; | |
} | |
// } | |
} | |
void playRandomAudio(){ | |
const char* audioNames[] = {"calm-down.wav", "classic_hurt.wav", "gnome.wav", "mario.wav", "scout.wav", "wow.wav"}; | |
playAudio(audioNames[random(6)]); | |
} | |
void basicModeLoop(){ | |
int back = map(roll, -10, 50, 0, 255); | |
int forward = map(roll, -10, -100, 0, 255); | |
int left = map(yaw, 60, 10, 0,255); | |
int right = map(yaw, 60, 200, 0,255); | |
// int negpitchr = map(roll, 0, -100, 0, 255); | |
// Serial.print("Roll - "); | |
// Serial.println(roll); | |
// Serial.print("Yaw -"); | |
// Serial.println(yaw); | |
ledStrip.clear(); | |
if(detectHit() && !cooldown){ | |
lightLoop(); | |
playRandomAudio(); | |
} | |
} | |
//https://www.codespeedy.com/hsv-to-rgb-in-cpp/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment