I've found other posts on this topic before but none have solved my particular problem.
This is my first project so please keep that in mind....
This particular YouTuber did not supply a complete parts list (resister visible in his video but none listed in his parts list). So much of this project is guess-work. So far, when I press the "on" button the saber hum starts and that's it. There is no "Saber on" sound at the beginning and the swing sounds don't play when the teensy is moved. The hum stops when the button is pressed again. I did not intend to use the LED portion of things as I am attempting to put this in an Ultrasaber stunt saber I got from a mystery box.
Here is the code:
No wiring diagram was provided but I found this website and read the comments. In them I discovered this photo
From it I made this schematic:
View attachment ILTMS_LIGHTSABER SCHEMATIC.pdf
I built my circuit from my schematic.
For the .RAW files needed in the code, they weren't provided either but I found some appropriate .WAV files and converted them using Audacity. I then copied them to the on-board memory using TeensyTransfer.
...that was a lot... any ideas?
This is my first project so please keep that in mind....
This particular YouTuber did not supply a complete parts list (resister visible in his video but none listed in his parts list). So much of this project is guess-work. So far, when I press the "on" button the saber hum starts and that's it. There is no "Saber on" sound at the beginning and the swing sounds don't play when the teensy is moved. The hum stops when the button is pressed again. I did not intend to use the LED portion of things as I am attempting to put this in an Ultrasaber stunt saber I got from a mystery box.
Here is the code:
Code:
/* Presented without warranty, guarantee and support.
* By Bob Clagett - I Like To Make Stuff
*
* This is the code to accompany the lightsaber project at http://www.iliketomakestuff.com/make-lightsaber/
* Expected hardware is listed in post (Teensy 3.2, Prop Shield, DotStar LEDs)
*
* This is functional v1 of this code. Lots more I want to add to it including crash detection/sounds.
* This code is dirty, bulky, poorly documented and ugly but I finally got it all functional.
* Cleanup to come later in v2.
*/
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioPlaySerialflashRaw playFlashRaw1; //xy=149,388
AudioPlaySerialflashRaw playHUMraw; //xy=149,388
AudioPlaySerialflashRaw playSwingRaw; //xy=149,388
AudioMixer4 mixer1; //xy=445,386
AudioOutputAnalog dac1; //xy=591,379
AudioConnection patchCord4(playSwingRaw, 0, mixer1, 2);
AudioConnection patchCord1(playFlashRaw1, 0, mixer1, 1);
AudioConnection patchCord3(playHUMraw, 0, mixer1, 0);
AudioConnection patchCord2(mixer1, dac1);
// GUItool: end automatically generated code
#include <Adafruit_DotStar.h>
#include <NXPMotionSense.h>
NXPMotionSense imu;
NXPSensorFusion filter;
int motionThreshold = 2;
float lastPitch = 0, lastRoll = 0, lastHeading = 0;
int buttonState = HIGH;
int bladeState = 0; //0 off, 1, fading up, 2 on, 3 fading down
int fadeStep = 0;
int fadeStepSize = 6;
int selectedColor = 0;
int lastSelectedColor = 0;
bool isAnimating = 0;
bool bladeOn = 0;
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50;
int lastButtonState = HIGH;
int pendingPress = 0;
//BC = Blade Color
int BCbuttonState = HIGH;
long BClastDebounceTime = 0; // the last time the output pin was toggled
long BCdebounceDelay = 50;
int BClastButtonState = HIGH;
int BCpendingPress = 0;
int pendingColorPress = 0;
#define COLOR_BUTTON_PIN 1
#define POWER_BUTTON_PIN 0
#define COLOR_ORDER BGR
#define CHIPSET APA102
#define NUMPIXELS 252
#define BRIGHTNESS 100
#define FRAMES_PER_SECOND 70
#define PROP_AMP_ENABLE 5
#define FLASH_CHIP_SELECT 6
#define LED_BUFFER_SELECT 7
#define VOLUME_POT 15
#define LED_PIN 7
Adafruit_DotStar strip = Adafruit_DotStar(
NUMPIXELS, DOTSTAR_BRG);
int outputValue = 0;
int presetColors[] = {0x0000FF,0x00FF00,0xFF0000,0xFFFFFF};
int totalPresetColors = (sizeof(presetColors)/sizeof(int));
int selectedColorIndex = 0;
int swingSounds = 4;
int lastSwingSound = swingSounds;
int clashSounds = 0;
void setup() {
delay(500); // sanity delay
imu.begin();
filter.begin(100);
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
clock_prescale_set(clock_div_1); // Enable 16 MHz on Trinket
#endif
strip.begin(); // Initialize pins for output
strip.show(); // Turn all LEDs off ASAP
pinMode(POWER_BUTTON_PIN, INPUT);
pinMode(COLOR_BUTTON_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(POWER_BUTTON_PIN, HIGH);
digitalWrite(COLOR_BUTTON_PIN, HIGH);
digitalWrite(LED_PIN, LOW);
Serial.begin(9600);
// wait up to 3 seconds for the Serial device to become available
long unsigned debug_start = millis ();
while (!Serial && ((millis () - debug_start) <= 3000))
;
Serial.println ("Start prop shield RAW player");
SPI.begin();
// Enable the amplifier on the prop shield
pinMode(PROP_AMP_ENABLE, OUTPUT);
digitalWrite(PROP_AMP_ENABLE, HIGH);
pinMode(LED_BUFFER_SELECT, OUTPUT);
digitalWrite(LED_BUFFER_SELECT, HIGH);
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(8);
// Set initial volume
mixer1.gain(1, 1.5f); //other sounds
mixer1.gain(0, 0.8f); //hum
// Start SerialFlash
if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
while (1)
{
Serial.println ("Cannot access SPI Flash chip");
delay (3000);
}
}
triggerSound("saberswing1.raw");
}
void powerUpBlade(){
isAnimating = 1;
bladeState = 1;
Serial.println("Turn on blade");
bladeOn = 1;
triggerSound("saberon.raw");
}
void powerDownBlade(){
//animate DOWN
triggerSound("saberoff.raw");
bladeState = 3;
fadeStep = NUMPIXELS;
isAnimating = 1;
Serial.println("Turn off blade");
stopHum();
bladeOn = 0;
}
void bladeIsOn(){
if(!playHUMraw.isPlaying()){
startHum();
}
//nothing needed here unless adding animation
}
void bladeIsAnimatingUp(){
//Serial.println("bladeIsAnimatingUp");
int midpoint = NUMPIXELS/2;
int newSection = fadeStep+fadeStepSize;
for( int j = fadeStep; j < newSection; j++) {
strip.setPixelColor(j, selectedColor);
strip.setPixelColor(NUMPIXELS-j, selectedColor);
}
Serial.println(newSection);
fadeStep = newSection;
if (fadeStep >= midpoint+fadeStepSize){
fadeStep = NUMPIXELS;
isAnimating=0;
bladeState = 2;
// delay(200);
Serial.println("blade up complete");
startHum();
}
}
void bladeIsAnimatingDown(){
//Serial.println("bladeIsAnimatingDown");
int midpoint = NUMPIXELS/2;
int newSection = fadeStep-fadeStepSize;
for( int j = fadeStep; j > newSection; j--) {
strip.setPixelColor(j-midpoint, 0x000000);
strip.setPixelColor(midpoint+NUMPIXELS-j, 0x000000);
}
//Serial.println(fadeStep);
fadeStep = newSection;
if (fadeStep <=midpoint-fadeStepSize){
fadeStep = 0;
isAnimating=0;
bladeState = 0;
}
}
void detectMotion() {
float ax, ay, az;
float gx, gy, gz;
float mx, my, mz;
float roll, pitch, heading;
if (imu.available()) {
// Read the motion sensors
imu.readMotionSensor(ax, ay, az, gx, gy, gz, mx, my, mz);
// Update the SensorFusion filter
filter.update(gx, gy, gz, ax, ay, az, mx, my, mz);
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
// does it need a time threshold too?
float headingDiff = abs(lastHeading - heading);
float pitchDiff = abs(lastPitch - pitch);
if(lastHeading != 0){
if(pitchDiff > motionThreshold || headingDiff > motionThreshold){
//cyle through swing sounds
lastSwingSound++;
if(lastSwingSound>swingSounds){
lastSwingSound=1;
}
String swingFile = "saberswingX.raw";
swingFile.replace("X",lastSwingSound);
char charBuf[50];
swingFile.toCharArray(charBuf, 50);
triggerSwing(charBuf); // needs sequence to iterate through
}
}
lastHeading = heading;
lastPitch = pitch;
}
}
void loop(){
// Add entropy to random number generator; we use a lot of it.
// random16_add_entropy( random() );
//handle color selector button
int BCreading = digitalRead(COLOR_BUTTON_PIN);
if (BCreading != BClastButtonState) {
// reset the debouncing timer
BClastDebounceTime = millis();
}
if ((millis() - BClastDebounceTime) > BCdebounceDelay) {
if (BCreading != BCbuttonState) {
BCbuttonState = BCreading;
if(BCbuttonState == HIGH){
nextColor();
}
}
}
BClastButtonState = BCreading;
selectedColor = presetColors[selectedColorIndex];
if(selectedColor != lastSelectedColor && bladeState != 0){
Serial.print("COLOR CHANGE");
Serial.println(selectedColorIndex);
for( int j = 0; j < NUMPIXELS; j++) {
strip.setPixelColor(j,selectedColor);
}
}
lastSelectedColor = selectedColor;
//handle blade on/off
int reading = digitalRead(POWER_BUTTON_PIN);
//debounce
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
}
}
lastButtonState = reading;
if( pendingPress == 1 && buttonState != LOW){
buttonState = HIGH;
pendingPress = 0;
Serial.print("execute pending blade press");
if(bladeOn){
powerDownBlade();
} else {
powerUpBlade();
}
}
if (buttonState == LOW && !isAnimating) {
Serial.println("BLADE BUTTON IS PRESSED");
pendingPress = 1;
}
switch(bladeState){
case 0:
//blade is off
break;
case 1:
//blade is animating up
bladeIsAnimatingUp();
break;
case 2:
//blade is on
bladeIsOn();
break;
case 3:
//blade is animating down
bladeIsAnimatingDown();
break;
}
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite(LED_PIN, HIGH); // enable access to LEDs
strip.show(); // Refresh strip
digitalWrite(LED_PIN, LOW);
SPI.endTransaction(); // allow other libs to use SPI again
delay(10);
if(bladeState == 2){
detectMotion();
}
}
void nextColor(){
selectedColorIndex++;
if(selectedColorIndex >= totalPresetColors){
selectedColorIndex = 0;
}
}
void triggerSound(const char *filename){
playFlashRaw1.play(filename);
}
void triggerSwing(const char *filename){
if(playSwingRaw.isPlaying()==0){
playSwingRaw.play(filename);
} else {
Serial.println("already swinging");
}
}
void startHum(){
//Serial.println("startHum");
playHUMraw.play("HUM2.RAW");
Serial.println(playHUMraw.isPlaying());
}
void stopHum(){
playHUMraw.stop();
}
No wiring diagram was provided but I found this website and read the comments. In them I discovered this photo
From it I made this schematic:
View attachment ILTMS_LIGHTSABER SCHEMATIC.pdf
I built my circuit from my schematic.
For the .RAW files needed in the code, they weren't provided either but I found some appropriate .WAV files and converted them using Audacity. I then copied them to the on-board memory using TeensyTransfer.
...that was a lot... any ideas?