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?
Lightsaber build questions
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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
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
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Lightsaber build questions
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:
and much easier if you break the innermost loop out as its own function:
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:
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:
every so often.
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 );
}
}
Code: Select all
void doFrameUpdate ( int f ) {
for ( int p=0 ; p < NUMPIXELS ; i++ ) {
strip.setPixelColor( p, colorForPixelInFrame( p, f ) );
}
strip.show();
}
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 ) );
}
Code: Select all
activePattern.frameUpdate();
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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?
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Lightsaber build questions
The simplest way would be to number the arrays and use the button to increment a counter:
If you have three arrays, that would cycle the count through a 0-1-2-0-1-2 pattern.
Code: Select all
if ( button2Pressed() ) {
arrayToUse = ( arrayToUse + 1 ) % NUMBER_OF_ARRAYS;
}
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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)?
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Lightsaber build questions
That's where the Multitasking Arduino tutorials come into play. Those walk through code that will do what you want, step by step.
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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?
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?
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Lightsaber build questions
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:
and a whole animation will be a list of those:
Then you'll probably find it useful to make a list of animations:
From which you'll be able to do:
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[] = { ... };
Code: Select all
uint32_t* animation_0 = { a0_f0, a0_f1, ... };
Code: Select all
uint32_t** animation_list[] = { animation_0, animation_1, ... };
Code: Select all
uint32* active_animation = animation_list[ n ];
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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
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
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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
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)
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
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
}
}
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
}
}
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Lightsaber build questions
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.
https://learn.adafruit.com/firewalker-l ... alker-code
The part that handles the red-yellow-white coloring can be adapted for other colors too.
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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?
- JamesBryan
- Posts: 134
- Joined: Mon Jun 29, 2015 2:39 pm
Re: Lightsaber build questions
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?
Please be positive and constructive with your questions and comments.