Created
December 11, 2017 15:58
-
-
Save samsch/1174d95057e0ee701ebe1a534c929fd6 to your computer and use it in GitHub Desktop.
Laser Gun Module V1 (file is actually .ino, but... github)
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
#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