Skip to content

Instantly share code, notes, and snippets.

@dragonlock2
Created September 1, 2019 03:21
Show Gist options
  • Save dragonlock2/43a271a353125fc9af5b1cd2af89acf9 to your computer and use it in GitHub Desktop.
Save dragonlock2/43a271a353125fc9af5b1cd2af89acf9 to your computer and use it in GitHub Desktop.
Code for my 4th gen Arduino based lightsaber.
#include <TMRpcm.h>
#include <SdFat.h>
//#include <CapacitiveSensor.h>
File file;
SdFat SD;
TMRpcm audio;
//CapacitiveSensor top = CapacitiveSensor(A0, A1); //20M resistor between, antenna on A1
//CapacitiveSensor bot = CapacitiveSensor(A3, A2); //20M resistor between, antenna on A2
const byte clashSens = 7; //medium sensor
const byte swingSens = 2; //fast sensor
const byte blade = 3;
const byte acc1 = 5;
const byte acc2 = 6;
//constants
int ON_TIME; //delay when turning on
int OFF_TIME; // delay when turning off
int BLASTER_DELAY; //min time to play lockup
const int ACCENT_DELAY = 7;
int TOP; //for capacitive switches
int BOT;
//local variables
boolean state = false;
long pulseTime; //used to keep track of time while fading
boolean goinDown; //check if fade up or down
byte curBrightBlade;
long blasterTime; //check to see if pressed long enough to play lockup
byte curBrightAcc1 = 255;
//byte curBrightAcc2 = 255;
long accTime = 0;
boolean accDown = true;
//int diff; //for cap switch
//long total1;
//long total2;
//attribute stuff
byte font;
byte numBoot;
byte numClash;
byte numOff;
byte numOn;
byte numSwing;
byte curVolume;
byte numBlast;
byte PULSE_DELAY; //length of pulse change from bright to dim of blade
byte MIN_BRIGHT_BLADE; //from 0-255
const int MAX_BRIGHT_BLADE = 255;
const int MIN_BRIGHT_ACC1 = 128;
//const int MIN_BRIGHT_ACC2 = 128;
//used to get config stuff
const char configFile[11] = "config.txt";
const char setFont[8] = "set.txt";
char blast[11] = "blast0.wav";
char zero = '0';
char newLine = '\n';
char boot[16];
char clash[17];
char hum[14];
char lockup[17];
char off[15];
char on[14];
char swing[17];
const int factor = 4; //factor to change delay bc pwm
void setup() {
//Serial.begin(9600);
TCCR2B = TCCR2B & B11111000 | B00000010; //set pwm to inaudible
TCCR0B = TCCR0B & B11111000 | B00000010; //why all delays are xfactor
pinMode(A0, OUTPUT);
pinMode(A3, OUTPUT);
digitalWrite(A0, HIGH);
digitalWrite(A3, HIGH);
pinMode(acc1, OUTPUT);
pinMode(acc2, OUTPUT);
//analogWrite(acc1, curBrightAcc1);
//analogWrite(acc2, curBrightAcc1);
//top.set_CS_AutocaL_Millis(0xFFFFFFFF);
//bot.set_CS_AutocaL_Millis(0xFFFFFFFF);
SD.begin(8, SPI_FULL_SPEED);
pinMode(clashSens, INPUT_PULLUP);
pinMode(swingSens, INPUT_PULLUP);
audio.speakerPin = 9;
pinMode(10, OUTPUT);
audio.setVolume(3);
//audio.quality(1); //not sure if affects ram usage or speed
delay(50*factor);
getSwitchAttributes();
//BOT = -1000; //testing purposes
//TOP = 1000;
//getDiff(); getDiff(); //do twice
if(topSW()) {
audio.play("choose.wav", 0);
while(audio.isPlaying(0));
chooseFont();
}
delay(50*factor);
getAttributes();
audio.setVolume(curVolume);
randomSeed(analogRead(A5));
boot[10] = zero + random(0, numBoot);
audio.play(boot, 0);
while(audio.isPlaying(0));
audio.loop(1, 1);
//BOT = -200; //testing purposes
//TOP = 200;
}
void loop() {
if(topSW()) { //check activation
state = !state;
if(state)
onAnim();
else
offAnim();
}
if(state) { //if on do this stuff //when on accents and blade have same brightness
if(botSW()) {
blasterTime = millis();
while(botSW()) {
delay(10); //debounce
if(millis() - blasterTime >= BLASTER_DELAY * factor) { //lockup time
analogWrite(blade, MAX_BRIGHT_BLADE);
analogWrite(acc1, MAX_BRIGHT_BLADE);
analogWrite(acc2, MAX_BRIGHT_BLADE);
audio.play(lockup, 0);
audio.loop(1, 0);
while(botSW());
audio.loop(0, 0);
}
}
if(millis() - blasterTime < BLASTER_DELAY * factor) {
analogWrite(blade, MAX_BRIGHT_BLADE);
analogWrite(acc1, MAX_BRIGHT_BLADE);
analogWrite(acc2, MAX_BRIGHT_BLADE);
blast[5] = zero + random(0, numBlast); //need to make settable
audio.play(blast, 0);
while(audio.isPlaying(0));
analogWrite(blade, curBrightBlade);
analogWrite(acc1, curBrightBlade);
analogWrite(acc2, curBrightBlade);
}
audio.stopPlayback(0);
}
if(!digitalRead(swingSens) && digitalRead(clashSens)) { //make sure its only a swing
swing[11] = zero + random(0, numSwing);
audio.play(swing, 0);
Serial.println("swing");
while(audio.isPlaying(0))
updateBlade();
}
if(!digitalRead(clashSens)) {
Serial.println("clash");
analogWrite(blade, MAX_BRIGHT_BLADE);
analogWrite(acc1, MAX_BRIGHT_BLADE);
analogWrite(acc2, MAX_BRIGHT_BLADE);
clash[11] = zero + random(0, numClash);
audio.play(clash, 0);
while(audio.isPlaying(0));
analogWrite(blade, curBrightBlade);
analogWrite(acc1, curBrightBlade);
analogWrite(acc2, curBrightBlade);
}
updateBlade();
}
//Serial.println(diff);
if(!state) updateAccents();
}
void onAnim() {
on[8] = zero + random(0, numOn);
audio.play(on, 0);
for(int i = 0; i <= MAX_BRIGHT_BLADE; i++) {
analogWrite(blade, i);
if(i > curBrightAcc1) {
analogWrite(acc1, i);
analogWrite(acc2, i);
}
delay(ON_TIME/(MAX_BRIGHT_BLADE + 1)*factor);
}
audio.play(hum, 1);
goinDown = true;
curBrightBlade = MAX_BRIGHT_BLADE;
while(audio.isPlaying(0))
updateBlade();
}
void offAnim() {
off[9] = zero + random(0, numOff);
audio.play(off, 0);
audio.stopPlayback(1);
for(int i = curBrightBlade; i >= 0; i--) {
analogWrite(blade, i);
analogWrite(acc1, i);
analogWrite(acc2, i);
delay(OFF_TIME/(curBrightBlade + 1)*factor);
}
while(audio.isPlaying());
for(int i = 0; i <= curBrightAcc1; i++) {
analogWrite(acc1, i);
analogWrite(acc2, i);
delay(ACCENT_DELAY*factor);
}
}
/*
void getDiff() {
total1 = top.capacitiveSensorRaw(15);
total2 = bot.capacitiveSensorRaw(15);
diff = total1 - total2;
}
*/
bool topSW() {
return analogRead(A2) < TOP;
}
bool botSW() {
return analogRead(A1) < BOT;
}
void updateBlade() {
if(millis() - pulseTime >= PULSE_DELAY*factor) {
pulseTime = millis();
if(goinDown) {
curBrightBlade--;
if(curBrightBlade <= MIN_BRIGHT_BLADE) {
goinDown = false;
curBrightBlade = MIN_BRIGHT_BLADE;
}
} else {
curBrightBlade++;
if(curBrightBlade >= MAX_BRIGHT_BLADE) {
goinDown = true;
curBrightBlade = MAX_BRIGHT_BLADE;
}
}
analogWrite(blade, curBrightBlade);
analogWrite(acc1, curBrightBlade);
analogWrite(acc2, curBrightBlade);
}
}
void updateAccents() { //currently making both same
/*
if(millis() - accTime >= ACCENT_DELAY*factor) {
accTime = millis();
if(accDown) {
curBrightAcc1--;
if(curBrightAcc1 <= MIN_BRIGHT_ACC1) {
accDown = false;
curBrightAcc1 = MIN_BRIGHT_ACC1;
}
} else {
curBrightAcc1++;
if(curBrightAcc1 >= 255) {
accDown = true;
curBrightAcc1 = 255;
}
}
analogWrite(acc1, curBrightAcc1);
analogWrite(acc2, curBrightAcc1);
}
*/
analogWrite(acc1, 255);
analogWrite(acc2, 255);
}
void chooseFont() {
file = SD.open(setFont);
font = (file.readStringUntil(newLine).charAt(0) - zero); //gets current font
file.close();
file = SD.open(configFile);
int totalFont = file.readStringUntil(newLine).charAt(0) - zero;
file.close();
char bootFile[16]; //files need to be char arrays
(String("font" + String(font) + F("/boot0.wav"))).toCharArray(bootFile, 16);
//Serial.println(font);
audio.play(bootFile);
while(!botSW()) { //waits for aux press to confirm font
if(topSW()) { //increments through fonts
font = (font + 1) % totalFont;
bootFile[4] = zero + font;
audio.play(bootFile);
//Serial.println(bootFile);
delay(250*factor);
}
}
saveFont();
}
void saveFont() {
//Serial.println(font);
audio.play("selected.wav", 0);
while(audio.isPlaying(0));
file = SD.open(setFont);
String selectedFont = file.readStringUntil(newLine);
selectedFont.setCharAt(0, zero + font);
file.close();
SD.remove(setFont);
file = SD.open(setFont, FILE_WRITE);
file.println(selectedFont);
file.close();
file = SD.open(setFont); //don't know why i have to open and close again
//while(file.available())
// Serial.write(file.read());
file.close();
}
void getSwitchAttributes() {
file = SD.open(configFile);
file.readStringUntil(newLine); //skip the total font line;
TOP = file.readStringUntil(newLine).substring(0, 3).toInt();
BOT = file.readStringUntil(newLine).substring(0, 3).toInt();
//Serial.println(TOP);
//Serial.println(BOT);
}
void getAttributes() {
file = SD.open(setFont);
font = file.readStringUntil(newLine).charAt(0) - zero;
file.close();
file = SD.open(configFile);
file.readStringUntil(newLine); //skip the total font line;
file.readStringUntil(newLine); //and switch lines
file.readStringUntil(newLine);
BLASTER_DELAY = file.readStringUntil(newLine).substring(0, 3).toInt();
numBlast = file.readStringUntil(newLine).substring(0, 1).toInt();
//TOP_ON = file.readStringUntil(newLine).substring(0, 3).toInt();
file.close();
String base;
base.reserve(7);
base = "font" + String(font) + F("/");
char configFont[18]; //attribute file
(String(base + F("numbers.txt"))).toCharArray(configFont, 18);
file = SD.open(configFont);
numBoot = file.readStringUntil(newLine).charAt(0) - zero;
numClash = file.readStringUntil(newLine).charAt(0) - zero;
numOff = file.readStringUntil(newLine).charAt(0) - zero;
numOn = file.readStringUntil(newLine).charAt(0) - zero;
numSwing = file.readStringUntil(newLine).charAt(0) - zero;
curVolume = file.readStringUntil(newLine).charAt(0) - zero;
ON_TIME = file.readStringUntil(newLine).substring(0, 4).toInt();
OFF_TIME = file.readStringUntil(newLine).substring(0, 4).toInt();
PULSE_DELAY = file.readStringUntil(newLine).substring(0, 2).toInt();
MIN_BRIGHT_BLADE = file.readStringUntil(newLine).substring(0, 3).toInt();
MIN_BRIGHT_BLADE = MAX_BRIGHT_BLADE * MIN_BRIGHT_BLADE / 100; //calculate now so not later
file.close();
String manip;
manip.reserve(18);
manip = base + F("boot0.wav");
manip.toCharArray(boot, 16);
manip = base + F("clash0.wav");
manip.toCharArray(clash, 17);
manip = base + F("hum.wav");
manip.toCharArray(hum, 14);
manip = base + F("lockup.wav");
manip.toCharArray(lockup, 17);
manip = base + F("off0.wav");
manip.toCharArray(off, 15);
manip = base + F("on0.wav");
manip.toCharArray(on, 14);
manip = base + F("swing0.wav");
manip.toCharArray(swing, 17);
/*
Serial.println(boot);
Serial.println(clash);
Serial.println(hum);
Serial.println(lockup);
Serial.println(off);
Serial.println(on);
Serial.println(swing); */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment