Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: ILTMS_TEENSY_LIGHTSABER_V1 help needed

  1. #1
    Junior Member
    Join Date
    Jul 2019
    Posts
    4

    ILTMS_TEENSY_LIGHTSABER_V1 help needed

    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:

    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

    Click image for larger version. 

Name:	ILTMS_LIGHTSABER WIRING PIC.jpg 
Views:	4 
Size:	72.8 KB 
ID:	16935

    From it I made this schematic:

    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?

  2. #2
    Junior Member
    Join Date
    Jul 2019
    Posts
    4
    .RAW SOUND FILES ARE CASE SENSITIVE!!!!

    Again... I'm a noob and didn't know that.

    I matched the case of the .RAW files named in the code to those that are actually on the chip. I had the right names, but I had lower case in the code and upper on the chip. That worked. It doesn't sound that great (the sounds coming out of my little Adafruit speaker don't sound as good as when they are played on the computer.

    Is there something I'm missing when converting my .WAV files to .RAW files for this propshield?

    I could still use help on that part.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •