Lightsaber build questions

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Lightsaber build questions

Post by JamesBryan »

i have a few questions that i need answers to so i hope that putting them together here will be forgiven. I'm planning to build a darth maul saber and ive got a few ideas on how to do this. i can either go with purpose built boards which would cost me around 100 or more EACH or i can go with using two pro trinkets paired up with accelerometers for under about 40 total. since i dont care about sound the choice of board makes no difference there.

ojk so onto my list of questions:
1: can the pro trinket support 3 or even 4 buttons (i have a list of functions that i realize can be divided up that can be accomplished with three buttons in addition to a master power switch, but if there is a way to make a momentary switch become a master power switch by use of long press or at least act as a sleep mode for LOW power consumption that would be awesome.
2:a mode switch function. i want to cycle the blade through colours and i know how to use the colour array function to do that. i want to add a mode switch that goes from "normal" blade to a "party mode" where i can choose between three different fire animations and when i press the colour cycle button it will cycle between the blade colours OR the fire animations. basically when the saber is in normal mode button 2 will cycle colours, when i hit button three it changes to party mode and button 2 will cycle the animations and when i hit button 3 again, button 2 will cycle the blade colours again. is this possible to do with the pro trinket and if so, how?
3 if my ideal situation is not possible the way i envision, is there a way to make it where when i hit button 2 it cycles colour but if i hit button three it will switch to party mode and i have to keep hitting button 3 to cycle the fire animations but when i hit button 2 it goes back to normal mode and button 2 cycles the colours?
4: if the pro trinket is not suitable for this project, what board do you have that would work that will fit into a one inch inside diameter cylinder?

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

before "read multitasking the arduino" is said, ive read it and while i get the jist of it, the issue is that it returns to the base animations when you release the buttons. i want to be able to switch between a colorarray and a case switch and it remain on whichever i select until i switch it back.
i have to dedicate button 1 to the colorwipe and reverse colorwipe for ignition and extinguish scroll regardless of what mode i am in. button 2 is to cycle colour during normal mode (a setup i am already familiar with from my tron legacy disc build with the only moification being i need to reverse the direction of the second colorwipe) i want button 3 to change from normal to party mode and button 4 or button two to cycle between the specific fire animation (a red/yellow/orange "standard" fire, a rainbow fire OR scrolling wipe and finally a blue/purple/green fire). it is how to get it to switch between modes and STAY on that mode until i switch it back that has me buggered

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Lightsaber build questions

Post by adafruit_support_mike »

Yes, a Pro Trinket can handle multiple buttons of input. That's fairly simple.

You can't make a Pro Trinket turn itself on and off with a button press, but you can come fairly close. You can tell the microcontroller to go to sleep, and use an interrupt pin to wake it up. The Space Invaders Pendant project does something similar:

https://learn.adafruit.com/trinket-slas ... t/overview

The multitasking series describes an advanced framework for handling concurrent IO, but the same principle exists in the BlinkWithoutDelay sketch:

https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

The fundamental idea is to handle your NeoPixel animations one frame at a time, and let the microcontroller do other things between updates. It's very hard to make that work when code is written line this:

Code: Select all

    for ( int i=ANIMATION_CYCLES ; i ; i-- ) {
        for ( int f=0 ; f < FRAMES_IN_PATTERN ; f++ ) {
            for ( int p=0 ; p < NUMPIXELS ; i++ ) {
                strip.setPixelColor( p, colorForPixelInFrame( p, f ) );
            }
            strip.show();
            delay( WAIT_TIME );
        }
    }
and much easier if you break the innermost loop out as its own function:

Code: Select all

void doFrameUpdate ( int f ) {
    for ( int p=0 ; p < NUMPIXELS ; i++ ) {
        strip.setPixelColor( p, colorForPixelInFrame( p, f ) );
    }
    strip.show();
}
and handle the timing between frames outside that loop.

If you want to switch between animation patterns, just make that another parameter for the update function:

Code: Select all

int doFrameUpdate ( int pattern, int frame ) {
    for ( int p=0 ; p < NUMPIXELS ; i++ ) {
        strip.setPixelColor( p, colorForPixelInFrame( p, pattern, frame ) );
    }
    strip.show();

    return( nextFrameAfter( pattern, frame ) );
}
You can also encapsulate that kind of logic in objects, which is what the multitasking series of tutorials do. It's even easier to shift between animations when all the pattern and frame logic is associated with an object and you can just call:

Code: Select all

    activePattern.frameUpdate();
every so often.

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

awesome, so now i at least know it CAN do everything i want to. i know i can make a basic stunt (no sound) saber with what i know so far by simply modifying my tron legacy disc sketch. its getting button three to switch between cycling through the normal blade colour to getting it to cycle through the display animations (beside using this at raves, i do want to have a fire blade option for dueling simply because it looks cool). the multitasking arduino article helps a great deal in showing how to do multiple button inputs and ive set up a two button sketch with one button cycling animations (ignition/extinguish) and the second cycling colours. now its getting the third button to select WHICH array to use and reliably switch between the two arrays. how would i get it to have button 2 be the cycle button for whichever array is active so i can use button 4 as a master power switch?

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Lightsaber build questions

Post by adafruit_support_mike »

The simplest way would be to number the arrays and use the button to increment a counter:

Code: Select all

    if ( button2Pressed() ) {
        arrayToUse = ( arrayToUse + 1 ) % NUMBER_OF_ARRAYS;
    }
If you have three arrays, that would cycle the count through a 0-1-2-0-1-2 pattern.

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

AWESOME, my problem is that i simply dont know the programming language but THIS is exactly what it was i was thinking would be needed, i just didnt know how to code for it. i can see that this will make button2 cycle through the active array, how do i code for button three to cycle which array is active? as for the animations, since im doing two or three fire animations, do i simply list them as i did with my colours like (rainbowfire, redfire, purplefire)?

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Lightsaber build questions

Post by adafruit_support_mike »

That's where the Multitasking Arduino tutorials come into play. Those walk through code that will do what you want, step by step.

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

i know the coding im about to type is wrong but should convey what im thinking.
define activearray= button3
if button3 pushed then activearray+1
"something, something (0,1)"
if active array=2 then 0
list the active arrays like:
array0 (0, 0, 255 0,25,0 255,0,0)
array1 (fire, rainbow fire, really impressive animation)
? am i at least somewhere in the ballpark for what im trying to tell the code regardless of how abysmal my attempt at it is?

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Lightsaber build questions

Post by adafruit_support_mike »

You're heading the right direction. There will be a few more steps though.

One frame of animation will probably be a list of colors for all the pixels in the strip:

Code: Select all

uint32_t a0_f0[] = { ... };
and a whole animation will be a list of those:

Code: Select all

uint32_t* animation_0 = { a0_f0, a0_f1, ... };
Then you'll probably find it useful to make a list of animations:

Code: Select all

uint32_t** animation_list[] = { animation_0, animation_1, ... };
From which you'll be able to do:

Code: Select all

uint32* active_animation = animation_list[ n ];

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

you can see sort of what my problem is, im great at concept, but because i dont code often enough to retain the info, i find it EXTREMELY hard to learn how to code. im a high function autistic so my learning curve is a cliff but so is the dropoff if i dont use a skill often enough to maintain it.
i know i can prety much copy and paste any of my previous working sketches from line 1 down to void and modify that as needed like adding buttons and i keep my sketches set up where i only have to comment/uncomment certain lines if im going with dotstar vs neopixels. the multitasking articles are great for showing me that the pro trinket is capable of the things that i need, but its lacking some of the very vital components of the code like the "mode change" and the selectable arrays. i get frustrated because i see so many projects where people were able to find sketches that showed the exact "proto-code" they needed where all they had to do was modify a vew things to make it work, but ive read a metric {deleted} ton of articles where people talk about doing the very things im trying to acomplish yet dont publish a single line of code OR i find articles where they publish not only every line of code but get into really detailed explanations of the code line by line and how they conect, but they are for projects that have nothing to do with what im trying to do

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

the problem with this that im encountering is when i try to google "how to select between two arrays" i either get a bunch of articles on random number generators or i get a bunch of stuff on how to make multiple strips of LEDs do things, but nothing on how to make a strip display a single active animation chosen from two different arrays based on which array is selected as the active array to choose from

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

ok ive gotten at least SOME progress. i think ive at least gotten it to extend and retract like a lightsaber should and im pretty sure that the colour change will be reliable. i STARTED out using my TRON legacy disc sketch

Code: Select all

//This is to allow a NeoPixel or DotStar strip to be cycled through a preset list of animations
//as well as to all the user to change the colours of the enimations while the animations are playing
//the start animation will send a pulse of blue, red and green down the strip to indicate the device is
//booted up and ready to go as well as allow a check for dead pixels or individualk colour elements
//TRON Legacy Identity disc Mk2 (replace with the name of the project being built)

//#include <Adafruit_DotStar.h> //Comment out if using NeoPixels
#include <Adafruit_NeoPixel.h> //commnt out if using DotStar


#ifdef _AVR_
#include <avr/power.h>
#endif


#define ANIMATION_BUTTON_PIN   5    // Digital IO pin connected to the button.  This will cycle through the animations.
#define COLOR_BUTTON_PIN   6    // Digital IO pin connected to the button.  This cycle through the colors.
#define PIXEL_PIN    4    // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 37
#define NUMPIXELS 37
// set both of the above to the number of pixels in your strip
// Parameter 1 = number of pixels in strip,  neopixel stick has 8
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream, correct for neopixel stick
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
// Here's how to control the LEDs from any two pins:
#define DATAPIN    4
//#define CLOCKPIN   3 //comment out if using neopixel as clockpin is not required
//Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BRG); //comment out if using neopixels
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800); //comment out if using dotstar

int      head  = 0, tail = -10; // Index of first 'on' and 'off' pixels
uint32_t color = 0xFF0000;      // 'On' color (starts red)



void setup() {
#if defined (_AVR_ATtiny85_)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  pinMode(ANIMATION_BUTTON_PIN, INPUT_PULLUP);
  pinMode(COLOR_BUTTON_PIN, INPUT_PULLUP);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  startAnimation();     //we use () because we are not passing any parameters
}
int mode = 0;  // Start in the "Off" mode

int colorindex = 0; //Starts in Red
int areLEDsBlank = 0;  //We did this so that the "Off" Mode isn't constantly writing to the LED Strip

//Adjust the colors here
uint32_t COLOR_ARRAY[] = {strip.Color(127, 0, 0), strip.Color(0, 255, 0), strip.Color(0, 0, 255)};


void loop() {

  // check for a button press
  if (digitalRead(ANIMATION_BUTTON_PIN) == LOW)  // button pressed
  {
    mode++;  // advance to the next mode
    if (mode == 4)
    {
      mode = 0; // go back to Off
    }
  }

  // check for a button press
  if (digitalRead(COLOR_BUTTON_PIN) == LOW)  // button pressed
  {
    colorindex++;  // advance to the next mode
    if (colorindex == sizeof(COLOR_ARRAY)/sizeof(COLOR_ARRAY[0]))
    {
      colorindex = 0; // go back to Red
    }
  }

  switch (mode) // execute code for one of the 3 modes:
  {
    case 0:
      if (areLEDsBlank != 0)
      {
        colorWipe(strip.Color(0, 0, 0), 10);
        areLEDsBlank = 0;
      }
      break; // mode == OFF

    case 1:          // add code for the "Ignition" mode here
      areLEDsBlank = 1;
      colorWipe(COLOR_ARRAY[colorindex], 5);
      break;

    case 2:          // add code for the "Spinning" mode here
      areLEDsBlank = 1;
      theaterChase(COLOR_ARRAY[colorindex], 25);
      break;
      
    case 3:          // add code for the "Ignition" mode here
      areLEDsBlank = 1;
      colorWipe(COLOR_ARRAY[colorindex], 10);
      break;
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, c);  //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}


void startAnimation() {

for (int i = 0; i< 4*NUMPIXELS; i++)
{ 
  strip.setPixelColor(head, color); // 'On' pixel at head
  strip.setPixelColor(tail, 0);     // 'Off' pixel at tail
  strip.show();                     // Refresh strip
  delay(20);                        // Pause 20 milliseconds (~50 FPS)

  if (++head >= NUMPIXELS) {        // Increment head index.  Off end of strip?
    head = 0;                       //  Yes, reset head index to start
    if ((color >>= 8) == 0)         //  Next color (R->G->B) ... past blue now?
      color = 0x000000;             //   Yes, reset to red
  }
  if (++tail >= NUMPIXELS) tail = 0; // Increment, reset tail index
}
}
and did some research to find out how to reverse the colorWipe and so far it compiles and looks like THIS: (the variables such as number of LED and such will be changed to th proper values later, im just plugging in values as placeholders for now)

Code: Select all

//This is to allow a NeoPixel or DotStar strip to be employed in a lightsaber replica
// the user will be able to cycle the blade through a selection of colours while in "saber" mode
//and through a selection of animation during "party mode"
//"party mode" is intended for purely impressive visual displays when at a rave or other setting to impress an audience
//as well as to enable a "fire blade" mode for use in dueling



//#include <Adafruit_DotStar.h> //Comment out if using NeoPixels
#include <Adafruit_NeoPixel.h> //commnt out if using DotStar


#ifdef _AVR_
#include <avr/power.h>
#endif

#define BLADE_BUTTON_PIN  7  // This will trigger the blade scroll for ignition and extinguish animation
#define ANIMATION_BUTTON_PIN   5    // This will select whether solid blade or aminations are active
#define COLOR_BUTTON_PIN   6    // This cycle through the colors in "saber" mode" or the animations in "party mode"
#define PIXEL_PIN    4    // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 37
#define NUMPIXELS 37
// set both of the above to the number of pixels in your strip
// Parameter 1 = number of pixels in strip,  neopixel stick has 8
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream, correct for neopixel stick
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
// Here's how to control the LEDs from any two pins:
#define DATAPIN    4
//#define CLOCKPIN   3 //comment out if using neopixel as clockpin is not required
//Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BRG); //comment out if using neopixels
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800); //comment out if using dotstar

int      head  = 0, tail = -10; // Index of first 'on' and 'off' pixels
uint32_t color = 0xFF0000;      // 'On' color (starts red)


void setup() {
  // put your setup code here, to run once:
#if defined (_AVR_ATtiny85_)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  pinMode(ANIMATION_BUTTON_PIN, INPUT_PULLUP);
  pinMode(COLOR_BUTTON_PIN, INPUT_PULLUP);
  pinMode(BLADE_BUTTON_PIN, INPUT_PULLUP);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  startAnimation();     //we use () because we are not passing any parameters
}
int mode = 0;  // Start in the "Off" mode

int colorindex = 0; //Starts in Red
int areLEDsBlank = 0;  //We did this so that the "Off" Mode isn't constantly writing to the LED Strip

//Adjust the colors here
uint32_t COLOR_ARRAY[] = {strip.Color(127, 0, 0), strip.Color(0, 255, 0), strip.Color(127, 0, 255)};
//adjust the animations here


void loop() {
  
  // check for a button press
  if (digitalRead(BLADE_BUTTON_PIN) == LOW)  // button pressed
  {
    mode++;  // advance to the next mode
    if (mode == 2)
    {
      mode = 0; // go back to Off
    }
  }
  switch (mode) // execute code for one of the 3 modes:
  {
    case 0:          // add code for the "Ignition" mode here
      areLEDsBlank = 1;
      colorWipe(COLOR_ARRAY[colorindex], 5);
      break;
      
    case 1:          // add code for the "extinguish" mode here
      areLEDsBlank = 1;
      reversecolorWipe(strip.Color(0, 0, 0), 10);
      break;
  }
}



// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

// turns off the LED one after the other 
void reversecolorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i--) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void startAnimation() {

  for (int i = 0; i < 4 * NUMPIXELS; i++)
  {
    strip.setPixelColor(head, color); // 'On' pixel at head
    strip.setPixelColor(tail, 0);     // 'Off' pixel at tail
    strip.show();                     // Refresh strip
    delay(20);                        // Pause 20 milliseconds (~50 FPS)

    if (++head >= NUMPIXELS) {        // Increment head index.  Off end of strip?
      head = 0;                       //  Yes, reset head index to start
      if ((color >>= 8) == 0)         //  Next color (R->G->B) ... past blue now?
        color = 0x000000;             //   Yes, reset to red
    }
    if (++tail >= NUMPIXELS) tail = 0; // Increment, reset tail index
  }
}
now im kind of stuck, im having trouble finding a fire animation code that i can plug in or how to change the colour values for that so that i can have a normal red/yellow/orange fire blade and a blue/green/purple "ice fire" blade

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Lightsaber build questions

Post by adafruit_support_mike »

The Firewalker Shoe project has code that might be useful for you:

https://learn.adafruit.com/firewalker-l ... alker-code

The part that handles the red-yellow-white coloring can be adapted for other colors too.

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

i actually read that one a couple hours before i posted my code. i couldnt quite suss out what the specific code for the fire animation was to figure out what to copy into my code or how to modify it. i am curious about whether the reverscolorWipe i have will accomplish the goal of "retracting" the blade no matter which animation is going?

User avatar
JamesBryan
 
Posts: 134
Joined: Mon Jun 29, 2015 2:39 pm

Re: Lightsaber build questions

Post by JamesBryan »

i realize i may have been too ambitious with my original plan. ive been looking at how i understand the code to function and what im guessing is that if i make animationbutton cycle through animations instead of trying to make it switch between saber and animation mode, that if i have the blade lit with a solid colour and then hit animationbutton, it will change to the animation and if i hit colorbutton it will switch BACK to solid colour. if this is true then i can probably just copy and paste from the HALO energy sword upgrade sketch i saw in the learn section, or perhaps jut copy the animtion code and then modify the colorarray code to be animationarray with having animationbutton in place of colorbutton. am i on the right track?

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”