Laser Gun Module V1 (file is actually .ino, but... github)
#include <Wire.h> | |
#include <LSM303.h> | |
#include <L3G.h> | |
L3G gyro; | |
LSM303 acc; | |
void setup() { | |
pinMode(3, OUTPUT); | |
pinMode(4, INPUT); | |
pinMode(5, INPUT); | |
pinMode(10, OUTPUT); | |
pinMode(11, OUTPUT); | |
pinMode(12, OUTPUT); | |
// Serial.begin(9600); | |
Wire.begin(); | |
if (!gyro.init()) | |
{ | |
// Serial.println("Failed to autodetect gyro type!"); | |
while (1); | |
} | |
gyro.enableDefault(); | |
acc.init(); | |
acc.enableDefault(); | |
acc.writeMagReg(0x02, 0b00000011); | |
acc.writeAccReg(0x23, 0b00010000); | |
startUpSound(); | |
} | |
#define S_READY 0 | |
#define S_FIRING 1 | |
#define S_NEED_RELOAD 2 | |
#define S_RELOADING 3 | |
#define MAX_AMMO 24 | |
#define NR_START 0 | |
#define NR_STEP1 1 | |
#define NR_STEP2 2 | |
#define NR_STEP3 3 | |
#define FM_FAST 0 | |
#define FM_SINGLE 1 | |
#define FM_CHARGE 3 | |
#define MOSTLY_DOWN 25 | |
#define SPIN_THRESH 50 | |
bool soundOn = false; | |
char gx = 0; | |
char gy = 0; | |
char gz = 0; | |
char ax = 0; | |
char ay = 0; | |
char az = 0; | |
byte state = S_READY; | |
byte ammo = MAX_AMMO; | |
byte reloadState = NR_START; | |
byte fireMode = FM_FAST; | |
unsigned long nextSample = 0; | |
unsigned long waitUntilTime = 0; | |
void loop() { | |
if (isModePressed()) { | |
switch (fireMode) { | |
case FM_FAST: | |
fireMode = FM_SINGLE; | |
tone(3, 1000, 100); | |
delay(100); | |
break; | |
case FM_SINGLE: | |
fireMode = FM_FAST; | |
tone(3, 1000, 100); | |
delay(200); | |
tone(3, 1000, 100); | |
delay(100); | |
break; | |
case FM_CHARGE: // Not yet used | |
fireMode = FM_FAST; | |
break; | |
} | |
} | |
unsigned long now = millis(); | |
if (now < nextSample) { | |
return; | |
} | |
nextSample = now + 50; | |
if (isWaiting()) { | |
return; | |
} | |
gyro.read(); | |
acc.read(); | |
gx = gyro.g.x / 255; | |
gy = gyro.g.y / 255; | |
gz = gyro.g.z / 255; | |
ax = acc.a.x / 255; | |
ay = acc.a.y / 255; | |
az = -acc.a.z / 255; | |
// Serial.print("State: "); | |
// Serial.print(state); | |
// Serial.print(" RLS: "); | |
// Serial.print(reloadState); | |
// Serial.print(" Ammo: "); | |
// Serial.print(ammo); | |
// Serial.print(" "); | |
// debugMotionData(); | |
digitalWrite(10, LOW); | |
switch (state) { | |
case S_READY: | |
digitalWrite(11, LOW); | |
digitalWrite(10, HIGH); | |
if (ammo < 1) { | |
state = S_NEED_RELOAD; | |
digitalWrite(11, HIGH); | |
break; | |
} | |
if (isTriggerOn()) { | |
fire(); | |
} | |
break; | |
case S_FIRING: | |
case S_NEED_RELOAD: | |
if (gy > SPIN_THRESH) { | |
state = S_RELOADING; | |
reloadState = NR_STEP1; | |
waitFor(100); | |
} | |
dryFireCheck(isTriggerOn()); | |
break; | |
case S_RELOADING: | |
needReload(); | |
break; | |
} | |
} | |
void needReload() { | |
switch (reloadState) { | |
case NR_STEP1: | |
if (gy < SPIN_THRESH) { | |
if (ax > MOSTLY_DOWN) { | |
reloadState = NR_STEP2; | |
} else { | |
state = S_NEED_RELOAD; | |
} | |
} | |
break; | |
case NR_STEP2: | |
waitFor(500); | |
startReloadSound(); | |
reloadState = NR_STEP3; | |
break; | |
case NR_STEP3: | |
if (ammo < MAX_AMMO && ax > MOSTLY_DOWN && abs(gx) < SPIN_THRESH && abs(gy) < SPIN_THRESH && abs(gz) < SPIN_THRESH) { | |
addAmmo(); | |
waitFor(100); | |
} else { | |
noTone(3); | |
if (ammo > 1) { | |
state = S_READY; | |
} else { | |
state = S_NEED_RELOAD; | |
} | |
} | |
break; | |
} | |
} | |
void fire() { | |
ammo--; | |
switch (fireMode) { | |
case FM_FAST: | |
laserEffect(); | |
break; | |
case FM_SINGLE: | |
singleFireEffect(); | |
delay(10); | |
while (isTriggerOn()) {} | |
delay(10); | |
break; | |
} | |
} | |
bool hasFired = false; | |
void dryFireCheck(bool triggerOn) { | |
if (!hasFired && triggerOn) { | |
dryFireSound(); | |
hasFired = true; | |
} else if (hasFired && !triggerOn) { | |
hasFired = false; | |
} | |
} | |
bool modeToggle = true; | |
bool isModePressed() { | |
bool pressed = digitalRead(5) == false; | |
if (modeToggle && pressed) { | |
modeToggle = false; | |
return true; | |
} | |
if (!modeToggle && !pressed) { | |
modeToggle = true; | |
} | |
return false; | |
} | |
bool isTriggerOn() { | |
return digitalRead(4) == false; | |
} | |
void addAmmo() { | |
addAmmoSound(); | |
ammo++; | |
} | |
void startReloadSound() { | |
tone(3, 1000, 80); | |
delay(180); | |
tone(3, 500, 150); | |
delay(300); | |
noTone(3); | |
} | |
void addAmmoSound() { | |
// tone(3, 800, 50); | |
int min = map(ammo, 0, 24, 500, 700); | |
int max = map(ammo, 0, 24, 800, 900); | |
for (int t = min; t < max; t += 36) { | |
tone(3, t); | |
delay(2); | |
} | |
noTone(3); | |
} | |
void singleFireEffect() { | |
digitalWrite(12, HIGH); | |
for (int t = 4000; t < 5000; t += 100) { | |
tone(3, t); | |
delay(2); | |
} | |
int soundStep = 1000; | |
for (int t = 5000; t > 500; t -= 50) { | |
tone(3, t); | |
delayMicroseconds(soundStep); | |
soundStep += 22; | |
} | |
digitalWrite(12, LOW); | |
noTone(3); | |
} | |
void laserEffect() { | |
digitalWrite(12, HIGH); | |
for (int t = 5000; t > 500; t -= 125) { | |
tone(3, t); | |
delay(2); | |
} | |
digitalWrite(12, LOW); | |
noTone(3); | |
} | |
void dryFireSound() { | |
for (int t = 1000; t > 500; t -= 100) { | |
tone(3, t); | |
delay(10); | |
} | |
noTone(3); | |
} | |
void outSound() { | |
tone(3, 500, 100); | |
tone(3, 1000, 100); | |
tone(3, 500, 100); | |
tone(3, 1000, 100); | |
noTone(3); | |
} | |
void startUpSound() { | |
// Serial.println("Startup!"); | |
for (int t = 100; t < 800; t += 10) { | |
tone(3, t); | |
delay(5); | |
} | |
noTone(3); | |
delay(100); | |
tone(3, 500, 50); | |
delay(100); | |
tone(3, 1000, 50); | |
delay(1000); | |
} | |
void waitFor(int timeMs) { | |
waitUntilTime = millis() + timeMs; | |
} | |
bool isWaiting() { | |
return millis() < waitUntilTime; | |
} | |
void debugMotionData() { | |
Serial.print("X: g: "); | |
Serial.print((int)gx); | |
Serial.print(" a: "); | |
Serial.print((int)ax); | |
Serial.print(" Y: "); | |
Serial.print((int)gy); | |
Serial.print(" a: "); | |
Serial.print((int)ay); | |
Serial.print(" Z: "); | |
Serial.print((int)gz); | |
Serial.print(" a: "); | |
Serial.println((int)az); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment