Nie no kod to żaden wynalazek, trochę tylko uprościłem i usunąłem nie potrzebne funkcje. O to kod:
Kod:
/*
SUPER-DUPER COOL ARDUINO BASED MULTICOLOR SOUND PLAYING LIGHTSABER!
HARDWARE:
Addressable LED strip (WS2811) to get any blade color and smooth turn on effect
MicroSD card module to play some sounds
IMU MPU6050 (accel + gyro) to generate hum. Frequency depends on angle velocity of blade
OR measure angle speed and play some hum sounds from SD
CAPABILITIES:
Smooth turning on/off with lightsaber-like sound effect
Randomly pulsing color (you can turn it off)
Sounds:
MODE 1: generated hum. Frequency depends on angle velocity of blade
MODE 2: hum sound from SD card
Slow swing - long hum sound (randomly from 4 sounds)
Fast swing - short hum sound (randomly from 5 sounds)
Bright white flash when hitting
Play one of 16 hit sounds, when hit
Weak hit - short sound
Hard hit - long "bzzzghghhdh" sound
After power on blade shows current battery level from 0 to 100 percent
CONTROL BUTTON:
HOLD - turn on / turn off GyverSaber
TRIPLE CLICK - change color (red - green - blue - yellow - pink - ice blue)
QUINARY CLICK - change sound mode (hum generation - hum playing)
Selected color and sound mode stored in EEPROM (non-volatile memory)
*/
// ---------------------------- SETTINGS -------------------------------
#define NUM_LEDS 144 // number of microcircuits WS2811 on LED strip (note: one WS2811 controls 3 LEDs!)
#define BTN_TIMEOUT 800 // button hold delay, ms
#define BRIGHTNESS 255 // max LED brightness (0 - 255)
#define SWING_TIMEOUT 500 // timeout between swings
#define SWING_L_THR 150 // swing angle speed threshold
#define SWING_THR 300 // fast swing angle speed threshold
#define STRIKE_THR 150 // hit acceleration threshold
#define STRIKE_S_THR 320 // hard hit acceleration threshold
#define FLASH_DELAY 80 // flash time while hit
#define Blink_ALLOW 1 // blade pulsation (1 - allow, 0 - disallow)
#define Blink_AMPL 20 // Blink amplitude
#define Blink_DELAY 30 // delay between Blinks
#define DEBUG 0 // debug information in Serial (1 - allow, 0 - disallow)
// ---------------------------- SETTINGS -------------------------------
#define LED_PIN 6
#define BTN 3
#define IMU_GND A1
#define SD_GND A0
#define BTN_LED 4
// -------------------------- LIBS ---------------------------
#include <avr/pgmspace.h> // PROGMEM library
#include <SD.h>
#include <TMRpcm.h> // audio from SD library
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
#include <toneAC.h> // hum generation library
#include "FastLED.h" // addressable LED library
#include <EEPROM.h>
CRGB leds[NUM_LEDS];
#define SD_ChipSelectPin 10
TMRpcm tmrpcm;
MPU6050 accelgyro;
// -------------------------- LIBS ---------------------------
// ------------------------------ VARIABLES ---------------------------------
int16_t ax, ay, az;
int16_t gx, gy, gz;
unsigned long ACC, GYR, COMPL;
int gyroX, gyroY, gyroZ, accelX, accelY, accelZ, freq, freq_f = 20;
float k = 0.2;
unsigned long humTimer = -9000, mpuTimer, nowTimer;
int stopTimer;
boolean bzzz_flag, ls_chg_state, ls_state;
boolean btnState, btn_flag, hold_flag;
byte btn_counter;
unsigned long btn_timer, Blink_timer, swing_timer, swing_timeout, bzzTimer;
byte nowNumber;
byte LEDcolor; // 0 - red, 1 - green, 2 - blue, 3 - pink, 4 - yellow, 5 - ice blue
byte nowColor, red, green, blue, redOffset, greenOffset, blueOffset;
boolean eeprom_flag, swing_flag, swing_allow, strike_flag, HUMmode;
int blinkOffset;
// ------------------------------ VARIABLES ---------------------------------
// --------------------------------- SOUNDS ----------------------------------
// Sounds arrays and other sound-related variables
const char strike1[] PROGMEM = "SK1.wav";
const char strike2[] PROGMEM = "SK2.wav";
const char strike3[] PROGMEM = "SK3.wav";
const char strike4[] PROGMEM = "SK4.wav";
const char strike5[] PROGMEM = "SK5.wav";
const char strike6[] PROGMEM = "SK6.wav";
const char strike7[] PROGMEM = "SK7.wav";
const char strike8[] PROGMEM = "SK8.wav";
const char* const strikes[] PROGMEM = {
strike1, strike2, strike3, strike4, strike5, strike6, strike7, strike8
};
int strike_time[8] = {779, 563, 687, 702, 673, 661, 666, 635};
const char strike_s1[] PROGMEM = "SKS1.wav";
const char strike_s2[] PROGMEM = "SKS2.wav";
const char strike_s3[] PROGMEM = "SKS3.wav";
const char strike_s4[] PROGMEM = "SKS4.wav";
const char strike_s5[] PROGMEM = "SKS5.wav";
const char strike_s6[] PROGMEM = "SKS6.wav";
const char strike_s7[] PROGMEM = "SKS7.wav";
const char strike_s8[] PROGMEM = "SKS8.wav";
const char* const strikes_short[] PROGMEM = {
strike_s1, strike_s2, strike_s3, strike_s4,
strike_s5, strike_s6, strike_s7, strike_s8
};
int strike_s_time[8] = {270, 167, 186, 250, 252, 255, 250, 238};
const char swing1[] PROGMEM = "SWS1.wav";
const char swing2[] PROGMEM = "SWS2.wav";
const char swing3[] PROGMEM = "SWS3.wav";
const char swing4[] PROGMEM = "SWS4.wav";
const char swing5[] PROGMEM = "SWS5.wav";
const char* const swings[] PROGMEM = {
swing1, swing2, swing3, swing4, swing5
};
int swing_time[8] = {389, 372, 360, 366, 337};
const char swingL1[] PROGMEM = "SWL1.wav";
const char swingL2[] PROGMEM = "SWL2.wav";
const char swingL3[] PROGMEM = "SWL3.wav";
const char swingL4[] PROGMEM = "SWL4.wav";
const char* const swings_L[] PROGMEM = {
swingL1, swingL2, swingL3, swingL4
};
int swing_time_L[8] = {636, 441, 772, 702};
char BUFFER[10];
// --------------------------------- SOUNDS ---------------------------------
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(100); // set brightness
setAll(0, 0, 0); // turn off all LEDs
Wire.begin();
Serial.begin(9600);
pinMode(BTN, INPUT_PULLUP);
pinMode(IMU_GND, OUTPUT);
pinMode(SD_GND, OUTPUT);
pinMode(BTN_LED, OUTPUT);
digitalWrite(IMU_GND, LOW);
digitalWrite(SD_GND, LOW);
digitalWrite(BTN_LED, HIGH);
randomSeed(analogRead(2)); // random seed for random number generation
accelgyro.initialize(); // IMU initialization
accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_250);
if (DEBUG) {
Serial.begin(115200);
if (accelgyro.testConnection()) {
Serial.println(F("MPU6050 connection successful"));
} else {
Serial.println(F("MPU6050 connection failed"));
}
}
tmrpcm.speakerPin = 9;
tmrpcm.setVolume(5);
tmrpcm.quality(1);
if (DEBUG) {
if (SD.begin(8)) Serial.println(F("SD OK"));
else Serial.println(F("SD fail"));
} else {
SD.begin(8);
}
if ((EEPROM.read(0) >= 0) && (EEPROM.read(0) <= 5)) {
nowColor = EEPROM.read(0);
HUMmode = EEPROM.read(1);
} else {
EEPROM.write(0, 0);
EEPROM.write(1, 0);
nowColor = 0;
}
setColor(nowColor);
FastLED.setBrightness(BRIGHTNESS); // Set initial color based on EEPROM or default
}
void loop() {
randomBlink();
getFreq();
on_off_sound();
btnTick();
strikeTick();
swingTick();
}
void btnTick() {
btnState = !digitalRead(BTN);
if (btnState && !btn_flag) {
btn_flag = true;
btn_counter++;
btn_timer = millis();
}
if (!btnState && btn_flag) {
btn_flag = false;
hold_flag = false;
}
if (btn_flag && btnState && (millis() - btn_timer > BTN_TIMEOUT) && !hold_flag) {
ls_chg_state = true;
hold_flag = true;
btn_counter = 0;
}
if ((millis() - btn_timer > BTN_TIMEOUT) && (btn_counter != 0)) {
if (ls_state) {
if (btn_counter == 3) {
nowColor++;
if (nowColor >= 6) nowColor = 0;
setColor(nowColor);
setAll(red, green, blue);
eeprom_flag = true;
}
if (btn_counter == 5) {
HUMmode = !HUMmode;
if (HUMmode) {
noToneAC(); // вырубить трещалку
tmrpcm.play("HUM.wav"); // грать гудение
} else {
tmrpcm.disable(); // выключаем звук
toneAC(freq_f); // трещать
}
eeprom_flag = true;
}
}
btn_counter = 0;
}
if (eeprom_flag) { //$$$$$$$$$$$$$$$$$$$$$$$$
EEPROM.write(0, nowColor);
EEPROM.write(1, HUMmode);
eeprom_flag = false;
}
}
void on_off_sound() {
if (ls_chg_state) {
if (!ls_state) {
tmrpcm.play("ON.wav");
delay(200);
light_up();
delay(200);
bzzz_flag = true;
ls_state = true;
if (HUMmode) {
noToneAC(); // вырубить трещалку
tmrpcm.play("HUM.wav"); // гудеть
} else {
tmrpcm.disable(); // выключаем звук
toneAC(freq_f); // трещать
}
} else {
noToneAC(); // вырубить трещалку
bzzz_flag = 0; // запретить включение трещалки
tmrpcm.play("OFF.wav"); // воспроизвести звук выключения
delay(300); // ждём воспроизведение
light_down(); // лента выключается
delay(300); // ждём воспроизведение
tmrpcm.disable(); // выключаем звук
if (DEBUG) Serial.println(F("SABER OFF"));
ls_state = false; // запомнить, что меч выключен
if (eeprom_flag) { // если была смена цвета
eeprom_flag = 0;
EEPROM.write(0, nowColor); // записать выбранный цвет в память
EEPROM.write(1, HUMmode);
}
}
ls_chg_state = false;
}
if (((millis() - humTimer) > 9000) && bzzz_flag && HUMmode) { // если настало время трещать и разрешено трещать
tmrpcm.play("HUM.wav");
humTimer = millis(); // сбросить таймер
swing_flag = 1;
strike_flag = 0;
}
long delta = millis() - bzzTimer;
if ((delta > 3) && bzzz_flag && !HUMmode) { // если настало время трещать и разрешено трещать
if (strike_flag) {
tmrpcm.disable(); // выключить звук
strike_flag = 0;
}
toneAC(freq_f); // трещать
bzzTimer = millis();
}
}
void randomBlink() {
if (Blink_ALLOW && ls_state && (millis() - Blink_timer > Blink_DELAY)) {
Blink_timer = millis();
blinkOffset = blinkOffset * k + random(-Blink_AMPL, Blink_AMPL) * (1 - k);
if (nowColor == 0) blinkOffset = constrain(blinkOffset, -15, 5);
redOffset = constrain(red + blinkOffset, 0, 255);
greenOffset = constrain(green + blinkOffset, 0, 255);
blueOffset = constrain(blue + blinkOffset, 0, 255);
setAll(redOffset, greenOffset, blueOffset);
}
}
void strikeTick() {
if ((ACC > STRIKE_THR) && (ACC < STRIKE_S_THR)) { // если ускорение превысило порог
if (!HUMmode) noToneAC(); // выключить трещалку
nowNumber = random(8); // взять случайное число
// читаем название трека из PROGMEM
strcpy_P(BUFFER, (char*)pgm_read_word(&(strikes_short[nowNumber])));
tmrpcm.play(BUFFER); // воспроизвести звук удара
strike_flash();
if (!HUMmode)
bzzTimer = millis() + strike_s_time[nowNumber] - FLASH_DELAY;
else
humTimer = millis() - 9000 + strike_s_time[nowNumber] - FLASH_DELAY;
strike_flag = 1;
}
if (ACC >= STRIKE_S_THR) { // если ускорение превысило порог
if (!HUMmode) noToneAC(); // выключить трещалку
nowNumber = random(8); // взять случайное число
// читаем название трека из PROGMEM
strcpy_P(BUFFER, (char*)pgm_read_word(&(strikes[nowNumber])));
tmrpcm.play(BUFFER); // воспроизвести звук удара
strike_flash();
if (!HUMmode)
bzzTimer = millis() + strike_time[nowNumber] - FLASH_DELAY;
else
humTimer = millis() - 9000 + strike_time[nowNumber] - FLASH_DELAY;
strike_flag = 1;
}
}
void swingTick() {
if (GYR > 80 && (millis() - swing_timeout > 100) && HUMmode) {
swing_timeout = millis();
if (((millis() - swing_timer) > SWING_TIMEOUT) && swing_flag && !strike_flag) {
if (GYR >= SWING_THR) { // если ускорение превысило порог
nowNumber = random(5); // взять случайное число
// читаем название трека из PROGMEM
strcpy_P(BUFFER, (char*)pgm_read_word(&(swings[nowNumber])));
tmrpcm.play(BUFFER); // воспроизвести звук взмаха
humTimer = millis() - 9000 + swing_time[nowNumber];
swing_flag = 0;
swing_timer = millis();
swing_allow = 0;
}
if ((GYR > SWING_L_THR) && (GYR < SWING_THR)) {
nowNumber = random(5); // взять случайное число
// читаем название трека из PROGMEM
strcpy_P(BUFFER, (char*)pgm_read_word(&(swings_L[nowNumber])));
tmrpcm.play(BUFFER); // воспроизвести звук взмаха
humTimer = millis() - 9000 + swing_time_L[nowNumber];
swing_flag = 0;
swing_timer = millis();
swing_allow = 0;
}
}
}
}
void getFreq() {
if (ls_state && (millis() - mpuTimer > 500)) {
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
gyroX = abs(gx / 100);
gyroY = abs(gy / 100);
gyroZ = abs(gz / 100);
accelX = abs(ax / 100);
accelY = abs(ay / 100);
accelZ = abs(az / 100);
ACC = sq((long)accelX) + sq((long)accelY) + sq((long)accelZ);
ACC = sqrt(ACC);
GYR = sq((long)gyroX) + sq((long)gyroY) + sq((long)gyroZ);
GYR = sqrt((long)GYR); //$$$$$$$
COMPL = ACC + GYR;
freq = (long)COMPL * COMPL / 1500;
freq = constrain(freq, 18, 300);
freq_f = freq * k + freq_f * (1 - k);
mpuTimer = micros();
}
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
}
void setAll(byte red, byte green, byte blue) {
for (int i = 0; i < NUM_LEDS; i++) {
setPixel(i, red, green, blue);
}
FastLED.show();
}
void light_up() {
for (char i = 0; i <= (NUM_LEDS / 2 - 1); i++) {
setPixel(i, red, green, blue);
setPixel((NUM_LEDS - 1 - i), red, green, blue);
FastLED.show();
delay(25);
}
}
void light_down() {
for (char i = (NUM_LEDS / 2 - 1); i >= 0; i--) {
setPixel(i, 0, 0, 0);
setPixel((NUM_LEDS - 1 - i), 0, 0, 0);
FastLED.show();
delay(25);
}
}
void strike_flash() {
setAll(255, 255, 255);
delay(FLASH_DELAY);
setAll(red, green, blue);
}
void setColor(byte color) {
switch (color) {
case 0: red = 255; green = 0; blue = 0; break;
case 1: red = 0; green = 255; blue = 0; break;
case 2: red = 0; green = 0; blue = 255; break;
case 3: red = 255; green = 0; blue = 255; break;
case 4: red = 255; green = 255; blue = 0; break;
case 5: red = 0; green = 255; blue = 255; break;
}
}
Kupiłem już moduł DFRobot MAX98357A, i chce go zaadoptować zamiast porzedniego