#4897873
grogking wrote: Can I make a suggestion? Get a highly reflective red paint, and paint the 3d printed LED cyclotron mounts. Then you can get a piece of 1/8 clear acrylic from lowes for the lenses.

The reason is the folders are cheap and scratch and cloud up easily. The acrylic is tougher and stands up to more abuse.
ah that's an interesting idea and probably better for a 7 year olds pack :). I had not thought of that. I've got to go source some lightweight motherboard material anyway so will go take a look at that too. Thanks
User avatar
By xoff00
#4897874
CountDeMonet wrote:Utilizing the SX1509 proved simpler and more powerful in my mind. As far as I know our setup is the first to utilize it as well as neopixels for the main lighting. Lots of options for LED animations with the neopixels. Now if only they would come out with a 15 or 16 segment neopixel bargraph :)
Yep, loving the SX1509. I'd kill for the bargraph, but the 144pixels/m strips works really nicely for the powercell...
#4898019
That's awesome. I'll have to look into that one some more. Looks like a nice compact package. It would work well in my son's pack I think.

Edit: Took a quick look. This looks really cool and simple. Only uses 2 pins on the arduino. Even though the docs say you need their base shield it looks like it could be directly hooked up. The multi colored graph component would need to be desoldered and an appropriate one put on but other than that it's perfect and cheap if the 10 segment graph is enough. Coding it also looks simple using their lib on github. Could be a really good option. I might order one and check it out since it's pretty cheap. It would simplify the wiring a lot.

http://wiki.seeed.cc/Grove-LED_Bar/
https://github.com/Seeed-Studio/Grove_LED_Bar
xoff00 liked this
#4898028
I've made a wee bit of progress on the code. I've found that referencing the media clips by name is much faster than by index. Apparently even by index it scans thru but not by name. This has reduced the hiccups between clips a smidge. There is still as small hiccup when the beam switches from firing to firing with warning. I don't think there is any way to fix that with the fx chip. That's the only issue I have with it though so that's pretty darn good.

I did a little work on the audio files. Some cleanup and fading to reduce harsh changes. I added in a power charge sound when you flick the activate switch to on. It still clicks to off. I've added 5 more dialog clips and I've added a randomizer for them so hopefully they will never be in the same order and you won't hear the same one twice in a sequence. I'm using almost 12MB of the 16 available on the board. Could still add some more stuff if I want to. For those of you that asked for the sounds I'll PM you the new location.

In other news I have the base of the pack all glued together and I'm cutting out the motherboard today. Then I'll create the mounts for the main body and get those glued on. After that it's just gluing the rest of it together and then finishing it with filler primer, bondo, and tons of sanding. I've procured all of the pvc and fittings I'll need to fabricate a small alice frame for this thing. It's starting to come together.
Code: Select all
#include <QueueArray.h>

// for the sound board
#include <SoftwareSerial.h>
#include "Adafruit_Soundboard.h"

#include <Adafruit_NeoPixel.h>

// for led triggers
#define HIGH 0x1
#define LOW  0x0

// neopixel pins
#define NEO_NOSE 9 // for nose of wand
Adafruit_NeoPixel noseJewel = Adafruit_NeoPixel(7, NEO_NOSE, NEO_GRB + NEO_KHZ800);

#define NEO_POWER 10 // for cyclotron and powercell
Adafruit_NeoPixel powerStick = Adafruit_NeoPixel(16, NEO_POWER, NEO_GRB + NEO_KHZ800);

bool powerBooted = false; // has the pack booted up

// soundboard pins
#define SFX_RST 2
#define SFX_RX 3
#define SFX_TX 4

// setup the board with the pins
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
Adafruit_Soundboard sfx = Adafruit_Soundboard( & ss, NULL, SFX_RST);
const int ACT = 13;// this connects to the act on the board so we can know if the audio is playing

// inputs for switches and buttons
const int THEME_SWITCH = 5;
const int STARTUP_SWITCH = 6;
const int SAFETY_SWITCH = 7;
const int FIRE_BUTTON = 8;

// switch states for tracking
bool theme = false;
bool startup = false;
bool safety = false;
bool fire = false;
bool warning = false;

// audio track locations on soundboard
const String startupTrack =   "T00     WAV";
const String blastTrack =     "T01     WAV";
const String endTrack =       "T02     WAV";
const String idleTrack =      "T03     WAV";
const String shutdownTrack =  "T04     WAV";
const String clickTrack =     "T05     WAV";
const String chargeTrack =    "T06     WAV";
const String warnTrack =      "T07     WAV";
const String ventTrack =      "T08     WAV";
const String texTrack =       "T09     WAV";
const String choreTrack =     "T10     WAV";
const String toolsTrack =     "T11     WAV";
const String listenTrack =    "T12     WAV";
const String goodTrack =      "T13     WAV";
const String thatTrack =      "T14     WAV";
const String neverTrack =     "T15     WAV";
const String hardTrack =      "T16     WAV";
const String neutronizedTrack="T17     WAV";
const String boxTrack =       "T18     WAV";
const String themeTrack =     "T19     OGG";

// dialog trigger times/states
unsigned long startDialogMillis;
int dialogArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // array with an index for each dialog
const int dialogWaitTime = 5000; // how long to hold down fire for a dialog to play
const int warnWaitTime = 10000;  // how long to hold down fire before warning sounds

void setup() {
  // softwareserial at 9600 baud for the audio board
  ss.begin(9600);

  // see if we have the soundboard
  // If we fail to communicate, loop forever for now but it would be nice to warn the user somehow
  if (!sfx.reset()) {
    while (1);
  }

  // set act modes for the fx board
  pinMode(ACT, INPUT);

  // configure nose jewel
  noseJewel.begin();
  noseJewel.show(); // Initialize all pixels to 'off'

  // configure powercell/cyclotron
  powerStick.begin();
  powerStick.setBrightness(10);
  powerStick.show(); // Initialize all pixels to 'off'

  // set the modes for the switches/buttons
  pinMode(THEME_SWITCH, INPUT);
  digitalWrite(THEME_SWITCH, HIGH);
  pinMode(STARTUP_SWITCH, INPUT);
  digitalWrite(STARTUP_SWITCH, HIGH);
  pinMode(SAFETY_SWITCH, INPUT);
  digitalWrite(SAFETY_SWITCH, HIGH);
  pinMode(FIRE_BUTTON, INPUT);
  digitalWrite(FIRE_BUTTON, HIGH);
}

bool isFiring = false; // keeps track of the firing state
bool shouldWarn = false; // track the warning state for alert audio

/* ************* Audio Board Helper Functions ************* */
// helper function to play a track by name on the audio board
void playTrack(String trackname) {
  // stop track if one is going
  int playing = digitalRead(ACT);
  if (playing == 0) {
    sfx.stop();
  }

  char charName[20];
  trackname.toCharArray(charName, 20);
  
  // now go play
  if (sfx.playTrack(charName)) {
    sfx.unpause();
  }
}

void stopTrack() {
  sfx.stop();
}

void resetSoundboard() {
  sfx.reset();
}

/* ************* Main Loop ************* */
int pwr_interval = 60;     // interval at which to cycle lights for the powercell. We update this in the loop to speed up the animation so must be declared here (milliseconds)
int firing_interval = 40;    // interval at which to cycle firing lights on the bargraph. We update this in the loop to speed up the animation so must be declared here (milliseconds).

void loop() {
  // get the current time
  int currentMillis = millis();

  // find out of the audio board is playing audio
  int playing = digitalRead(ACT);

  // find out the theme switch state
  int theme_switch = digitalRead(THEME_SWITCH);

  // if the theme switch has recently changed we should play the full ghostbusters theme song
  if (theme_switch == 1) {
    if (theme == false) {
      playTrack(themeTrack);
      theme = true;
    }
  } else {
    theme = false;
  }

  // now get the other switch/button states so we can handle animations/sounds
  int startup_switch = digitalRead(STARTUP_SWITCH);
  int safety_switch = digitalRead(SAFETY_SWITCH);
  int fire_button = digitalRead(FIRE_BUTTON);

  // while the startup switch is set on
  if (startup_switch == 1) {
    // in general we always try to play the idle sound if started
    if (playing == 1 && startup == true) {
      playTrack(idleTrack);
    }

    // choose the right powercell animation sequence for booted/on
    if ( powerBooted == true ) {
      powerSequenceOne(currentMillis, pwr_interval);
    } else {
      powerSequenceBoot(currentMillis);
    }

    // if we are not started up we should play the startup sound first
    if (startup == false) {
      startup = true;
      playTrack(startupTrack);

      // get the current safety switch state
      if (safety_switch == 1 && safety == false) {
        safety = true;
      }
    }

    // if the safety switch is set off then we can fire when the button is pressed
    if ( safety_switch == 1 && fire_button == 0) {
      // if the button is just pressed we clear all led's to start the firing animations
      if ( isFiring == false ) {
        shutdown_leds();
        isFiring = true;
      }

      // show the firing bargraph sequence
      barGraphSequenceTwo(currentMillis);
    } else { // if we were firing and are no longer reset the leds
      if ( isFiring == true ) {
        shutdown_leds();
        isFiring = false;
      }

      // and do the standard bargraph sequence
      barGraphSequenceOne(currentMillis);
    }

    // if we are started up fire loop
    if (startup == true && safety_switch == 1)
    {
      // if the safety was just changed play the click track
      if (safety == false) {
        safety = true;
        playTrack(chargeTrack);
      }

      // if the fire button is pressed
      if (fire_button == 0) {
        fireStrobe(); // strobe the nose pixels

        // if this is the first time reset some variables and play the blast track
        if (fire == false) {
          shouldWarn = false;
          fire = true;
          startDialogMillis = millis();
          playTrack(blastTrack);
        } else {
          // find out what our timing is
          long diff = millis() - startDialogMillis;
          // if we are in the warn interval
          if ( diff > warnWaitTime) {
            pwr_interval = 20; // speed up the powercell animation
            firing_interval = 20; // speed up the bar graph animation
            if (playing == 1 || shouldWarn == false ) {
              shouldWarn = true;
              playTrack(warnTrack); // play the firing track with the warning
            }
          } else if ( diff > dialogWaitTime) { // if we are in the dialog playing interval
            pwr_interval = 40; // speed up the powercell animation
            firing_interval = 30; // speed up the bar graph animation
            if (playing == 1) {
              playTrack(blastTrack); // play the normal blast track
            }
          }
        }
      } else { // now the button is no longer pressed
        if (fire == true) { // if we were firing let's reset the animations and play the correct final firing track
          clearFireStrobe();
          pwr_interval = 60;
          firing_interval = 40;
          fire = false;

          // see if we've been firing long enough to get the dialog or vent sounds
          long diff = millis() - startDialogMillis;

          if ( diff > warnWaitTime) { // if we are past the warning let's vent the pack
            playTrack(ventTrack);
            clearPowerStrip(); // play the boot animation on the powercell
          } else if ( diff > dialogWaitTime) { // if in the dialog time play the dialog in sequence
            switch (getRandomTrack())
            {
              case (1):
                playTrack(choreTrack);
                break;
              case (2):
                playTrack(toolsTrack);
                break;
              case (3):
                playTrack(texTrack);
                break;
              case (4):
                playTrack(listenTrack);
                break;
              case (5):
                playTrack(goodTrack);
                break;
              case (6):
                playTrack(thatTrack);
                break;
              case (7):
                playTrack(neverTrack);
                break;
              case (8):
                playTrack(hardTrack);
                break;
              case (9):
                playTrack(neutronizedTrack);
                break;
              case (10):
                playTrack(boxTrack);
                break;
            }
          } else {
            // otherwise play the standard power down track
            playTrack(endTrack);
          }
        }
      }
    } else {
      // if the safety is switched off play the click track
      if (safety == true) {
        safety = false;
        playTrack(clickTrack);
      }
    }
  } else { // if we are powering down
    clearPowerStrip(); // clear all led's
    shutdown_leds();

    if (startup == true) { // if started reset the variables
      startup = false;
      safety = false;
      fire = false;

      playTrack(shutdownTrack); // play the pack shutdown track
    }
  }
  delay(1);
}

QueueArray <int> dialogQueue;
int getRandomTrack()
{
  if ( !dialogQueue.isEmpty() )
  {
    // pull the next dialog
    return dialogQueue.dequeue();
  }
  else
  {
    // queue is empty so reset it and pull the first
    // random dialog
    int numDialog = sizeof(dialogArray) / sizeof(int);
    shuffleArray( dialogArray, numDialog );
    
    for (int i = 0; i < numDialog; i++)
    {
      dialogQueue.enqueue(dialogArray[i]);
    }

    return dialogQueue.dequeue();
  }
}

// function for sorting arrays found here. Added random seed
// https://forum.arduino.cc/index.php?topic=345964.0
void shuffleArray(int * array, int size)
{
  randomSeed(analogRead(A0));

  int last = 0;
  int temp = array[last];
  for (int i = 0; i < size; i++)
  {
    int index = random(size);
    array[last] = array[index];
    last = index;
  }
  array[last] = temp;
}

/*************** Powercell Animations *********************/
unsigned long prevPwrBootMillis = 0;    // the last time we changed a light in the boot sequence
const int pwr_boot_interval = 400;      // interval at which to cycle lights (milliseconds).
unsigned long prevPwrMillis = 0;        // last time we changed a light in the idle sequence

int powerSeqTotal = 16;     // total number of led's for power
int powerBootSeqNum = 16;   // boot sequence counts down from 16
int powerSeqNum = 0;

// clears out and resets the power cell neopixel
void clearPowerStrip() {
  powerBooted = false;
  for ( int i = 0; i < powerSeqTotal; i++) {
    powerStick.setPixelColor(i, 0);
  }
  powerStick.show();
  powerSeqNum = 0;
  powerBootSeqNum = 16;
}

// boot animation on the bar graph
void powerSequenceBoot(int currentMillis) {
  if (currentMillis - prevPwrBootMillis > pwr_boot_interval) {
    // save the last time you blinked the LED
    prevPwrBootMillis = currentMillis;

    for ( int i = powerSeqTotal; i > 0; i--) {
      if ( i <= powerBootSeqNum ) {
        powerStick.setPixelColor(i, powerStick.Color(0, 0, 150));
      } else {
        powerStick.setPixelColor(i, 0);
      }
    }
    powerStick.show();
    if ( powerBootSeqNum > 0) {
      powerBootSeqNum--;
    } else {
      powerBooted = true;
      powerBootSeqNum = 16;
    }
  }
}

// normal animation on the bar graph
void powerSequenceOne(int currentMillis, int anispeed) {
  powerBootSeqNum = 16;
  if (currentMillis - prevPwrMillis > anispeed) {
    // save the last time you blinked the LED
    prevPwrMillis = currentMillis;

    for ( int i = 0; i < powerSeqTotal; i++) {
      if ( i <= powerSeqNum ) {
        powerStick.setPixelColor(i, powerStick.Color(0, 0, 150));
      } else {
        powerStick.setPixelColor(i, 0);
      }
    }
    powerStick.show();
    if ( powerSeqNum < powerSeqTotal) {
      powerSeqNum++;
    } else {
      powerSeqNum = 0;
    }
  }
}

/*************** Firing Animations *********************/
unsigned long prevFireMillis = 0;
const int fire_interval = 2;     // interval at which to cycle lights (milliseconds).
int fireSeqNum = 0;
int fireSeqTotal = 5;

void clearFireStrobe() {
  for ( int i = 0; i < 7; i++) {
    noseJewel.setPixelColor(i, 0);
  }
  noseJewel.show();
  fireSeqNum = 0;
}

void fireStrobe() {
  switch ( fireSeqNum ) {
    case 0:
      noseJewel.setPixelColor(0, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(1, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(2, 0);
      noseJewel.setPixelColor(3, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(4, 0);
      noseJewel.setPixelColor(5, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(6, 0);
      break;
    case 1:
      noseJewel.setPixelColor(0, noseJewel.Color(0, 0, 255));
      noseJewel.setPixelColor(1, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(2, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(3, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(4, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(5, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(6, noseJewel.Color(255, 255, 255));
      break;
    case 2:
      noseJewel.setPixelColor(0, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(1, 0);
      noseJewel.setPixelColor(2, noseJewel.Color(0, 0, 255));
      noseJewel.setPixelColor(3, 0);
      noseJewel.setPixelColor(4, noseJewel.Color(0, 0, 255));
      noseJewel.setPixelColor(5, 0);
      noseJewel.setPixelColor(6, noseJewel.Color(255, 0, 0));
      break;
    case 3:
      noseJewel.setPixelColor(0, noseJewel.Color(0, 0, 255));
      noseJewel.setPixelColor(1, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(2, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(3, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(4, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(5, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(6, noseJewel.Color(255, 255, 255));
      break;
    case 4:
      noseJewel.setPixelColor(0, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(1, 0);
      noseJewel.setPixelColor(2, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(3, 0);
      noseJewel.setPixelColor(4, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(5, 0);
      noseJewel.setPixelColor(6, noseJewel.Color(255, 255, 255));
      break;
    case 5:
      noseJewel.setPixelColor(0, noseJewel.Color(255, 0, 255));
      noseJewel.setPixelColor(1, noseJewel.Color(0, 255, 0));
      noseJewel.setPixelColor(2, noseJewel.Color(255, 0, 0));
      noseJewel.setPixelColor(3, noseJewel.Color(0, 0, 255));
      noseJewel.setPixelColor(4, noseJewel.Color(255, 0, 255));
      noseJewel.setPixelColor(5, noseJewel.Color(255, 255, 255));
      noseJewel.setPixelColor(6, noseJewel.Color(0, 0, 255));
      break;
  }

  noseJewel.show();

  fireSeqNum++;
  if ( fireSeqNum > fireSeqTotal ) {
    fireSeqNum = 0;
  }
}

/*************** Bar Graph Animations *********************/
void shutdown_leds() {
  // stubb function for when I re-enable to bargraph
}
void barGraphSequenceOne(int currentMillis) {
  // stubb function for when I re-enable to bargraph
}
void barGraphSequenceTwo(int currentMillis) {
  // stubb function for when I re-enable to bargraph
}
#4898031
I've created the github repo for the project

https://github.com/CountDeMonet/ArduinoProtonPack/

I've posted the models, code, libs, and some of the sounds used. I won't be providing the full song for instance. Users will need to source that themselves. I'll update the thread when changes are made. As I finish putting things together I'll put more information on the github page. Definitely a work in progress.
grogking, xoff00 liked this
#4898086
I just went ahead and updated the thread title to better reflect where we are at with the project. It's no longer just the 3d model :)

I've designed and tested the mounts for the pack to the motherboard. I'll be using m4 lockscrews in these L brackets with the bracket epoxied to shell. Should work well. Probably have 6 to 8 of them around the pack.

Image

I have the motherboard all traced out and ready for cutting. I need to run to the store and get a new blade for my saw before I can do that. Forgot I was cutting thru lattice with it last time and dulled the heck out of it. At least I can mark all of the holes and stuff.

Image
xoff00 liked this
#4898097
For the scaled down version I redesigned the trigger box to have the rear remove instead of the bottom. This allows for easier access. That trigger box can be scaled up for the full version as well. As far as the holes go I've been drilling them out for the size that I need using the existing holes as the template.

I thought I had posted a pic of the redesigned box but looking back I never did. Here it is. The model is up on github. I've not added it to thingiverse yet.

Image
User avatar
By xoff00
#4898174
CountDeMonet wrote:I've made a wee bit of progress on the code. I've found that referencing the media clips by name is much faster than by index. Apparently even by index it scans thru but not by name. This has reduced the hiccups between clips a smidge. There is still as small hiccup when the beam switches from firing to firing with warning. I don't think there is any way to fix that with the fx chip. That's the only issue I have with it though so that's pretty darn good.

I did a little work on the audio files. Some cleanup and fading to reduce harsh changes. I added in a power charge sound when you flick the activate switch to on. It still clicks to off. I've added 5 more dialog clips and I've added a randomizer for them so hopefully they will never be in the same order and you won't hear the same one twice in a sequence. I'm using almost 12MB of the 16 available on the board. Could still add some more stuff if I want to. For those of you that asked for the sounds I'll PM you the new location.
I was working on adding an "ambiance" mode that played several of the less common songs (such as Magic and Cleanin' Up the Town) for "walking around music" since I had the space, for when the pack was on display.
#4898269
My evenings are being split between sanding, modeling connectors, and finishing electronics. I have the main base of the pack filled and sanded. The mounts are glued in and the motherboard is cut out. I just need to drill the holes for the mounts and then I can start gluing on all of the main pieces. I also started work on the first board that will be in the pack. It'll take in the 5v, ground, and the neopixel pin for the powercell/cyclotron lights. I have the board done up in Eagle but I need to get moving so don't have time to order boards. I hand built it and it came out well. Now to get the connectors on all of the neopixels and finish up the cyclotron programming.

Image
Image
#4898273
This post may contain an affiliate link that helps support GBFans.com when you make a purchase at no additional cost to you.

That sucks. I went with these and I'm pretty happy with the set. They were easy to solder in and a good selection.
https://www.amazon.com/gp/product/B0734PS688

Although I just found out my crimper doesn't do this small of a connection so I had to order a new crimping tool. Won't be here until sunday :( I don't have to be using these connectors but it will really make maintenance easier down the road if something breaks. Seeing as how it's in the hands of a near 7 year old I'm guessing there will be some repairs :)
xoff00 liked this
#4898314
Started playing with the PVC to make the alice like frame. For my son I really don't need to do any of the bends. It's about 9x15 in size right now and I might actually make it a little smaller width wise. It sits well on his back though and should work out nicely. Time to figure out how to attach the pack to it.

Image
xoff00 liked this
#4898326
Nice, I like the way you did the standoffs. Looks like something I could do as well as I've been struggling on that. I was going to do the shelf thing for the kidney belt but at this size it proved to be too large with the 90 and 45 degree elbows you can buy at the store. What is the gray tube at the top you are using? That looks really good
#4898353
Crimper came in and after the slight learning curve to it I had the crimping down pat. I managed to finish up the 4 cyclotron lights and rewire the powercell. Hooked it all up, nothing smoked, and it all worked. I have control of all of the leds now. Time to finish up the coding as we are getting close!

Image

Also a LOT of sanding and filling and sanding today. A few more parts to put on it then it's time to hit the pack with the filler primer. I am still contemplating the mount to the backpack frame. I'll probably do something similar to Grogking. As a test I had to connect the wand to the pack to see how it would look. I probably could have gone a little smaller on the wand but it fits my son's hands well right now. I intentionally went with a pack base that was shallow to save on weight for him. It is starting to feel beefy. I've not weighed it yet. I'm excited to get it mounted to the pack and see how it all looks on him.

Image
Image
xoff00 liked this
#4898359
It was a really simple board to chain the neopixels. each neopixel has 4 pads.

* ground
* 5v in
* data in
* data out

The data out is the one that allows you to chain them and control up to 200 and some with 1 pin. So all I did with this board was have a ground and power bus. Then it's data in to the first neopixel which then goes data out to the data in on the next neopixel until we get to the end. I drew it up in eagle so I could get boards made.

Image

From left to right on the 3 pin connectors you have ground * 5v * data in
From left to right on the 4 pin connectors you have ground * 5v * data in * data out
#4898365
Looks great! I ordered (and got today) the same connectors, hopefully my JST crimper works on them!

It's interesting that you did a "home run" for each jewel physically, but that they're logically an array (data in to data out) -- I'm assuming your thought was that each jewel would get power directly instead of having to travel through the entire array?

Mine is a more traditional daisy chain, I tested it directly from an Arduino pin and had no issues, but in the "production" pack I'll be doing similar to yours and running them directly from my 5v source. I do need to swap out the JST SM connector for the ones you're using, since there are female through-hole connectors for those:

Image
Hardest part of the image was finding a clean flat surface to photograph against - I had to use the floor! :)
#4898375
Exactly, I want each neopixel to come straight off the 5v from the buck converter. It should provide a cleaner signal and more consistent brightness between the led's. Plus I had to do it this way due to the design of the mounts I have for the cyclotron.

When I have everything powered thru the usb on the arduino I see some power drain with all of the neopixels running. With the brightness set to 20% on the cyclotron and the nose jewel set to 80% the lights on the powercell/cyclotron visibly fade when the firing animation is running. That doesn't happen when powered thru the buck converters. Something to think about. I'll likely set the brightness on the powercell/cyclotron to 50% and the nose to 100% when I place it in the pack.
#4898385
Ok, I figured as such. I won't be running power for any of the LEDs through the Arduino, just the data pin -- each chain (one for powercell and one for cyclotron) will be off their own line from the 5v rail. A third line (and a separate 3v3 one for the SX1509 and bargraph) will run to the wand for the neopixels there.
  • 1
  • 5
  • 6
  • 7
  • 8
  • 9
  • 25

It appears that some time today someone who […]

Correct, it grants several in fact the Melody's […]

Are they just newspaper clippings or something? […]

If you check the post below from reddit, one of […]