Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Alan Wang
Published © CC BY-NC-SA

So I Fixed a Broken Hasbro Lightsaber

Refit a 2004 Hasbro lightsaber toy with Arduino Nano, NeoPixel, ADXL335 and a DFPlayer Mini.

IntermediateShowcase (no instructions)7,054
So I Fixed a Broken Hasbro Lightsaber

Things used in this project

Story

Read more

Code

Refitted Hasbro lightsaber

C/C++
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h" // https://github.com/DFRobot/DFRobotDFPlayerMini
#include <Adafruit_NeoPixel.h> // https://github.com/adafruit/Adafruit_NeoPixel
#include "ADXL335.h" // https://github.com/Seeed-Studio/Accelerometer_ADXL335

#define BUTTON_PIN 2
#define NEOPIXEL_PIN 3
#define MP3_BUSY_PIN 4
#define MP3_RX_PIN 5
#define MP3_TX_PIN 6

#define ACCEL_TRIGGER_RATIO 0.06

#define NEOPIXEL_NUM 9
#define BUTTON_LONGPRESS_1 750
#define BUTTON_LONGPRESS_2 1500

#define SABER_ON 1
#define SABER_HUM 2
#define SABER_MOVE 3
#define SABER_OFF 4
#define SABER_QUOTE 5
#define SABER_MUSIC 6

#define SABER_ON_START 1
#define SABER_ON_END 15
#define SABER_HUM_START 16
#define SABER_HUM_END 25
#define SABER_MOVE_START 26
#define SABER_MOVE_END 50
#define SABER_OFF_START 51
#define SABER_OFF_END 58
#define SABER_QUOTE_START 59
#define SABER_QUOTE_END 72
#define SABER_MUSIC_START 73
#define SABER_MUSIC_END 81

#define SABER_ON_VOLUME 25
#define SABER_HUM_VOLUME 20
#define SABER_MOVE_VOLUME 22
#define SABER_OFF_VOLUME 25
#define SABER_QUOTE_VOLUME 20
#define SABER_MUSIC_VOLUME 22

SoftwareSerial softSerial(MP3_RX_PIN, MP3_TX_PIN);
DFRobotDFPlayerMini mp3;

ADXL335 accel;
int x, y, z, button_start, button_end, hum_index;
float last_accel_data, current_accel_data, accel_diff;
bool r, g, b, musicMode;

Adafruit_NeoPixel leds(NEOPIXEL_NUM, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup() {

  Serial.begin(9600);
  softSerial.begin(9600);

  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(MP3_BUSY_PIN, INPUT_PULLUP);

  leds.begin();
  accel.begin();

  mp3.begin(softSerial);
  delay(50);
  mp3.EQ(DFPLAYER_EQ_ROCK);
  musicMode = false;
  delay(200);

  clearLEDs();

}

void loop() {

  randomSeed(analogRead(A5) + analogRead(A6) + analogRead(A7));

  while (!buttonPressed());
  clearLEDs();
  chooseRGB();
  playMp3(SABER_ON);
  delay(50);
  for (int i = 0; i < 255; i++) {
    setLEDs(r * i, g * i, b * i);
    delay(1);
  }
  while (mp3IsBusy());
  while (buttonPressed());
  delay(200);
  chooseHum();
  getAccel();

  while (true) {

    last_accel_data = current_accel_data;
    getAccel();
    accel_diff = (current_accel_data - last_accel_data) / last_accel_data;

    if (!mp3IsBusy()) {
      musicMode = false;
      loopHum();
    }

    if (!musicMode && accel_diff >= ACCEL_TRIGGER_RATIO) {
      playMp3(SABER_MOVE);
      while (!mp3IsBusy());
      while (mp3IsBusy());
      delay(200);
    }

    if (buttonPressed()) {
      button_start = millis();
      while (buttonPressed());
      button_end = millis();
      if (button_end - button_start >= BUTTON_LONGPRESS_2) {
        musicMode = true;
        playMp3(SABER_MUSIC);
      } else if (button_end - button_start >= BUTTON_LONGPRESS_1) {
        musicMode = true;
        playMp3(SABER_QUOTE);
      } else {
        if (musicMode) {
          musicMode = false;
          mp3.pause();
          delay(200);
        } else {
          break;
        }
      }
    }
    delay(50);
  }

  delay(50);
  playMp3(SABER_OFF);
  delay(150);
  for (int i = 255; i >= 0; i--) {
    setLEDs(r * i, g * i, b * i);
    delay(2);
  }
  while (mp3IsBusy());
  while (!buttonPressed());
  delay(200);

}

bool buttonPressed() {
  return !digitalRead(BUTTON_PIN);
}

bool mp3IsBusy() {
  return !digitalRead(MP3_BUSY_PIN);
}

void playMp3(int soundType) {
  int startIndex, endIndex, selectedVolume;
  switch (soundType) {
    case SABER_ON:
      startIndex = SABER_ON_START;
      endIndex = SABER_ON_END;
      selectedVolume = SABER_ON_VOLUME;
      break;
    case SABER_HUM:
      startIndex = SABER_HUM_START;
      endIndex = SABER_HUM_END;
      selectedVolume = SABER_HUM_VOLUME;
      break;
    case SABER_MOVE:
      startIndex = SABER_MOVE_START;
      endIndex = SABER_MOVE_END;
      selectedVolume = SABER_MOVE_VOLUME;
      break;
    case SABER_OFF:
      startIndex = SABER_OFF_START;
      endIndex = SABER_OFF_END;
      selectedVolume = SABER_OFF_VOLUME;
      break;
    case SABER_QUOTE:
      startIndex = SABER_QUOTE_START;
      endIndex = SABER_QUOTE_END;
      selectedVolume = SABER_QUOTE_VOLUME;
      break;
    case SABER_MUSIC:
      startIndex = SABER_MUSIC_START;
      endIndex = SABER_MUSIC_END;
      selectedVolume = SABER_MUSIC_VOLUME;
      break;
    default:
      startIndex = 0;
      endIndex = 0;
      selectedVolume = SABER_HUM_VOLUME;
  }
  mp3.volume(selectedVolume);
  delay(50);
  mp3.play(random(startIndex, endIndex + 1));
  delay(200);
}

void chooseHum() {
  hum_index = random(SABER_HUM_START, SABER_HUM_END + 1);
}

void loopHum() {
  mp3.volume(SABER_HUM_VOLUME);
  delay(50);
  mp3.play(hum_index);
  delay(200);
}

void chooseRGB() {
  r = random(0, 2);
  g = random(0, 2);
  b = (r || g) ? random(0, 2) : true;
}

void clearLEDs() {
  leds.clear();
  leds.show();
}

void setLEDs(int rc, int gc, int bc) {
  for (int i = 0; i < NEOPIXEL_NUM; i++) {
    leds.setPixelColor(i, leds.Color(rc, gc, bc));
  }
  leds.show();
}

void getAccel() {
  accel.getXYZ(&x, &y, &z);
  current_accel_data = x + y + z;
}

Credits

Alan Wang
32 projects • 103 followers
Please do not ask me for free help for school or company projects. My time is not open sourced and you cannot buy it with free compliments.
Contact

Comments

Please log in or sign up to comment.