#4969900
Hello.

Late last year I hijacked a thread about the Afterlife Sound Effects, and have been asked for some updates regarding my own build. Rather than continue to hijack that thread, I'll continue over here, on my own, probably quite disorganized thread.

After getting excited about Afterlife, and seeing [urlhttps://www.youtube.com/c/LostWaxOz/search?query=proton]Lost Wax's EVA Proton Pack build videos[/url], I decided to fulfill a life-long desire to build my own Proton Pack. It was originally going to be EVA, but after doing some research, I learned about the 3D Printed Q-Pack. I had previously purchased a 3D printer to make some leather molding tools, and it had been sitting unused after printing the molds. After seeing the Q-Pack, and the various builds here and on Facebook, the course was set, and lots of printing commenced.

Right now most of the parts are in various states of assembly and in boxes, because I got distracted with also printing a 50% scale pack, and more recently, a Workbench Pack. I'll touch on progress and everything later, but the question in the other thread that spawned this one was -
Do you have a video showing off the afterlife spinning lights and possible the code and instructions to setting it up for myself?


Here's the video:


The code is from Cfunseth's github, and the code itself looks like:

/*
* Example sketch for afterlife_cyclotron class
* Written By: Cole Funseth
*/

#include "afterlife_cyclotron.h"

#define PIN 13 // Which pin on the Arduino is connected to the NeoPixels?
#define HEAT_PIN 9 // Which pin on the Arduino is connected to the "overheat" signal?
#define NUMPIXELS 40 // How many NeoPixels are attached to the Arduino?
#define BRIGHTNESS 255 // How bright should the pixels be? (min = 0, max = 255)
#define GROUP 3 // How big of a group of pixels do you want to rotate?
#define INIT_SPD 255 // How slow do you want the animation to rotate at the beginning of the boot? (higher = slower, 255 max)
#define IDLE_SPD 0 // How fast do you want the animation to rotate during "normal" operation (lower = faster, 0 min)
#define HEAT_SPD 5 // How fast do you want the animation to rotate at overheat? (lower = faster, 0 min)
#define BOOT_DLY 10000 // How long do you want the boot animation to last?
#define HEAT_DLY 5000 // How long should the "overheat" ramp up last?

// Create a new cyclotron object
Cyclotron cyclotron(PIN, NUMPIXELS, GROUP, INIT_SPD);

void setup() {
//Setup and start the cyclotron
cyclotron.setBrightness(0, 0);
cyclotron.start();
cyclotron.setSpeed(IDLE_SPD, BOOT_DLY);
cyclotron.setBrightness(BRIGHTNESS, BOOT_DLY);

//Set "overheat" signal pin as an input
pinMode(HEAT_PIN, INPUT_PULLUP);
}

void loop() {
//Update the cyclotron (should be called as frequently as possible)
cyclotron.update();

//Delete the "!" below if you want to invert the overheat signal for your board
//This signal isn't debounced, so it may be wonky with noisy signals
if(!digitalRead(HEAT_PIN)) cyclotron.setSpeed(IDLE_SPD, BOOT_DLY);
else cyclotron.setSpeed(HEAT_SPD, HEAT_DLY);
}

The Neopixel ring is the 40 pixel ring from this set, and it's controlled by an Arduino Nano clone. The ring is in the Tacobelli Spinning Cyclotron Set in the q-Pack MK3 files.
jonogunn, Jimsy33 liked this
#4969912
Thanks so much for sharing dude! Glad to see it in action. I don’t understand the coding much but I notice “overheat” in it. I’m guessing it’s meant to be attached to some wand code?
Did you also get it working with sound or is that still a WIP?

I’m most likely gonna keep it simple and use a Hasbro wand so it’ll just be all pack related lights and sound for me.
#4969914
I notice “overheat” in it. I’m guessing it’s meant to be attached to some wand code
That's exactly correct. If the arduino detects a "high" signal on Pin 9, it will trigger an overheat sequence. Since it's not being used, it can be ignored.

Eventually I might trim it up to make the sketch focused solely on the cyclotron, but for now, if ain't broke there's no need to fix it. :-)
jonogunn liked this
#4970117
And another distraction...

As part of buying the "emitter" 3d files from LeBazarDuQ on Etsy, aka Quentin Machiels, he provided files for the other interior parts as well - colloquially known as the "Cake", the "Cooler", and the "Plate". These files are all available as part of a revised listing.

Here's the almost completed cake, waiting on wires, clamps, and weathering:
Image

The window was created by Rich, @ lasergarage.net, from the STL I had. I highly recommend them.



Don't make the same mistake I did when assembling your cake. The center column part has holes that need to align with the outer holes of the separate body. If you don't align them before glue-up, when you go to assembly your window and top grid, you'll need to drill out new center holes:
Image

Next up, the plate...
#4971120
Hi Roland,

I'm trying to understand the code now and I would like to add the start up and hum sound effect to the cyclotron arduino set up as well the powercell light. Did you by any chance figured that out yet?

I have an idea to replace the intensify button with a DPDT button on my Spengler wand and initiate the overhead sequence on the cyclotron (sound effects not needed since it'll come from the wand via aux to speakers in pack). Ideally it'll speed up to max speed and then the entire ring blinks in sync with the warning sounds at the overheat sequence.

I've looked at Gucabe's code, CFunseth as well as Mikes11 but it's beyond me how to add all these together.
#4971132
I had a very detailed and thorough reply, with links etc to everything referenced below, but the site timed out, made me reload the page, and it was all gone... If you need links or anything, let me know and I'll add them.
I would like to add the start up and hum sound effect to the cyclotron arduino set up as well the powercell light. Did you by any chance figured that out yet?
Hi. I did, but it's not a very elegant solution.

I have 2 Arduinos, one each each controlling the Cyclotron and Powercell. Cfunseth's code works for the Cyclotron; CountDiMonet's "Spirit Minimal"for the Powercell . For the sounds, I am using an Adafruit soundboard. I remixed my startup sound & hum to 1 file that kicks on at power-up, and cycles every 12 min or so. I had an hour and 5 hour options, but had to trim it because of the file sizes.

I have an idea to replace the intensify button with a DPDT button on my Spengler wand and initiate the overhead sequence on the cyclotron
This thread might help. They are using CountDiMonet's code and wanted to trigger an overheat with a button, without having to wait for the whole sequence.

I've looked at Gucabe's code, CFunseth as well as Mikes11 but it's beyond me how to add all these together.
Each person's code is using a different approach to handling lights/sounds/etc, and that's why it is difficult to remix them, without knowing a lot about Arduino & coding.

Gucabe is using 2 controllers, similar to my approach.

Cfunseth's is solely for the Cyclotron. His code includes listening on Pin 9 for an overheat signal to play a different light sequence - that's where you'd put your switch to set the Pin from Low to High to trigger that sequence in the code.

MikeS11 and CountDiMonet both use an "all-in-one" approach, using one controller to handle Pack & Wand lights & sounds. The biggest difference I can see so far is that CountdiMonet's has an Afterlife option. They both handle the lights/sounds using the internal clock, rather than strict loops to handle everything - it's also called a "State Machine". It's a way to have independent lights/sounds/events and is beyond my current skill set.

Hope that helps!
jonogunn liked this
#4971141
Thanks for the reply!

Are you open to sharing your code, files and setup? If not that’s cool too.

I was playing around with Gucabe’s code on tinkercad last night (I’m still waiting on some parts to arrive to try IRL) and I understood how some of it works a bit more. Unfortunately, if I understood it correctly it looks like there are 5 pins that connect to the adafruit sound board which would imply there are 5 sound files?? Since he never shared what files he used im not sure on this part.

In my mind to keep it simple I would put the powercell and sound effects on one arduino and cfunseth’s cyclotron on another with a dpdt connection to the wand for the overheat.

But yah if you’re willing to share your design for me to look let me know!
#4971144
Are you open to sharing your code, files and setup?
You bet:

Cyclotron code -
Code: Select all
/*
 * Example sketch for afterlife_cyclotron class
 * Written By: Cole Funseth
 */

#include "afterlife_cyclotron.h"

#define PIN 13           // Which pin on the Arduino is connected to the NeoPixels?
#define HEAT_PIN  9     // Which pin on the Arduino is connected to the "overheat" signal?
#define NUMPIXELS 40    // How many NeoPixels are attached to the Arduino?
#define BRIGHTNESS 255  // How bright should the pixels be? (min = 0, max = 255)
#define GROUP 3          // How big of a group of pixels do you want to rotate?
#define INIT_SPD  255   // How slow do you want the animation to rotate at the beginning of the boot? (higher = slower, 255 max)
#define IDLE_SPD  0    // How fast do you want the animation to rotate during "normal" operation (lower = faster, 0 min)
#define HEAT_SPD 5      // How fast do you want the animation to rotate at overheat? (lower = faster, 0 min)
#define BOOT_DLY  10000  // How long do you want the boot animation to last?
#define HEAT_DLY  5000  // How long should the "overheat" ramp up last?

// Create a new cyclotron object
Cyclotron cyclotron(PIN, NUMPIXELS, GROUP, INIT_SPD);

void setup() {
  //Setup and start the cyclotron
  cyclotron.setBrightness(0, 0);
  cyclotron.start();
  cyclotron.setSpeed(IDLE_SPD, BOOT_DLY);
  cyclotron.setBrightness(BRIGHTNESS, BOOT_DLY);

  //Set "overheat" signal pin as an input
  pinMode(HEAT_PIN, INPUT_PULLUP);
}

void loop() {
  //Update the cyclotron (should be called as frequently as possible)
  cyclotron.update();

  //Delete the "!" below if you want to invert the overheat signal for your board
  //This signal isn't debounced, so it may be wonky with noisy signals
  if(!digitalRead(HEAT_PIN)) cyclotron.setSpeed(IDLE_SPD, BOOT_DLY);
  else cyclotron.setSpeed(HEAT_SPD, HEAT_DLY);
}

Powercell -
Code: Select all
#include <Adafruit_NeoPixel.h>

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

#define NEO_CYCLO 3 // for cyclotron
Adafruit_NeoPixel cyclotron = Adafruit_NeoPixel(4, NEO_CYCLO, NEO_GRB + NEO_KHZ800);

// Possible Pack states
bool powerBooted = false;   // has the pack booted up

// ##############################
// available options
// ##############################
const bool useGameCyclotronEffect = true;     // set this to true to get the fading previous cyclotron light in the idle sequence
const bool useCyclotronFadeInEffect = true;   // Instead of the yellow alternate flashing on boot this fades the cyclotron in from off to red

// ##############################
// bootup animation speeds
// ##############################
const unsigned long pwr_boot_interval = 40;       // How fast to do the powercell drop animation on bootup 
const unsigned long cyc_boot_interval = 400;      // If useCyclotronFadeInEffect is false this alternates the cycltron lights yellow 
const unsigned long cyc_boot_alt_interval = 150;  // How fast to fade in the cyclotron lights from black to red on bootup

// ##############################
// idle animation speeds
// ##############################
const unsigned long pwr_interval = 35;            // how fast the powercell cycles: One 14 led cycle per 756 ms
const unsigned long cyc_interval = 770;           // how fast the cycltron cycles from one cell to the next: One full rotation every 3024 ms
const unsigned long cyc_fade_interval = 1;        // if useGameCyclotronEffect is true this is how fast to fade the previous cyclotron to light to nothing

void setup() {
  // configure powercell/cyclotron
  powerStick.begin();
  powerStick.setBrightness(80);
  powerStick.show(); // Initialize all pixels to 'off'

  cyclotron.begin();
  cyclotron.setBrightness(80);
  cyclotron.show(); // Initialize all pixels to 'off'
}

void loop() {
  // get the current time
  unsigned long currentMillis = millis();
  if( powerBooted == false ){
    powerSequenceBoot(currentMillis);
  } else {
    powerSequenceOne(currentMillis, pwr_interval, cyc_interval, cyc_fade_interval);
  }
  delay(1);
}

int cyclotronRunningFadeOut = 255;  // we reset this variable every time we change the cyclotron index so the fade effect works
int cyclotronRunningFadeIn = 0;     // we reset this to 0 to fade the cyclotron in from nothing
void setCyclotronLightState(int startLed, int endLed, int state ){
  switch ( state ) {
    case 0: // set all leds to red
      for(int i=startLed; i <= endLed; i++) {
        cyclotron.setPixelColor(i, powerStick.Color(255, 0, 0));
      }
      break;
    case 1: // set all leds to orange
      for(int i=startLed; i <= endLed; i++) {
        cyclotron.setPixelColor(i, powerStick.Color(255, 106, 0));
      }
      break;
    case 2: // set all leds off
      for(int i=startLed; i <= endLed; i++) {
        cyclotron.setPixelColor(i, 0);
      }
      break;
    case 3: // fade all leds from red
      for(int i=startLed; i <= endLed; i++) {
        if( cyclotronRunningFadeOut >= 0 ){
          cyclotron.setPixelColor(i, 255 * cyclotronRunningFadeOut/255, 0, 0);
          cyclotronRunningFadeOut--;
        }else{
          cyclotron.setPixelColor(i, 0);
        }
      }
      break;
  case 4: // fade all leds to red
      for(int i=startLed; i <= endLed; i++) {
        if( cyclotronRunningFadeIn < 255 ){
          cyclotron.setPixelColor(i, 255 * cyclotronRunningFadeIn/255, 0, 0);
          cyclotronRunningFadeIn++;
        }else{
          cyclotron.setPixelColor(i, cyclotron.Color(255, 0, 0));
        }
      }
      break;
  }
}

/*************** Powercell/Cyclotron Animations *********************/
/* These allow you to use more than one neopixel per cyclotron if you
 * want it brighter. If using only one set start and end to the same
 * number */
int c1Start = 0;
int c1End = 0;
int c2Start = 1;
int c2End = 1;
int c3Start = 2;
int c3End = 2;
int c4Start = 3;
int c4End = 3;

unsigned long prevPwrBootMillis = 0;    // the last time we changed a powercell light in the boot sequence
unsigned long prevCycBootMillis = 0;    // the last time we changed a cyclotron light in the boot sequence
unsigned long prevPwrMillis = 0;        // last time we changed a powercell light in the idle sequence
unsigned long prevCycMillis = 0;        // last time we changed a cyclotron light in the idle sequence
unsigned long prevFadeCycMillis = 0;    // last time we changed a fading cyclotron light in the idle sequence

// LED indexes into the neopixel powerstick chain for the cyclotron
const int powercellLedCount = 15;   // total number of led's in the animation
int powerSeqNum = 0;                // current running powercell sequence leds

// animation level trackers for the boot and shutdown
int currentBootLevel = 0;                          // current powercell boot level sequence led
int currentLightLevel = powercellLedCount;         // current powercell boot light sequence led

// boot animation on the powercell/cyclotron
bool reverseBootCyclotron = false;
void powerSequenceBoot(unsigned long currentMillis) {
  bool doPowercellUpdate = false;

  if ((unsigned long)(currentMillis - prevPwrBootMillis) >= pwr_boot_interval) {
    // save the last time you blinked the LED
    prevPwrBootMillis = currentMillis;

    // START POWERCELL
    if( currentBootLevel != powercellLedCount ){
      if( currentBootLevel == currentLightLevel){
        if(currentLightLevel+1 <= powercellLedCount){
          powerStick.setPixelColor(currentLightLevel+1, 0);
        }
        powerStick.setPixelColor(currentBootLevel, powerStick.Color(0, 0, 255));
        currentLightLevel = powercellLedCount;
        currentBootLevel++;
      }else{
        if(currentLightLevel+1 <= powercellLedCount){
          powerStick.setPixelColor(currentLightLevel+1, 0);
        }
        powerStick.setPixelColor(currentLightLevel, powerStick.Color(0, 0, 255));
        currentLightLevel--;
      }
      doPowercellUpdate = true;
    }else{
      powerBooted = true;
      currentBootLevel = 0;
      currentLightLevel = powercellLedCount;
    }
    // END POWERCELL
  }

  // if we have changed an led
  if( doPowercellUpdate == true ){
    powerStick.show(); // commit all of the changes
  }
  
  // START CYCLOTRON
  bool doCycUpdate = false;
  if( useCyclotronFadeInEffect == false ){
    if ((unsigned long)(currentMillis - prevCycBootMillis) >= cyc_boot_interval) {
      prevCycBootMillis = currentMillis;

      if( reverseBootCyclotron == false ){
        setCyclotronLightState(c1Start, c1End, 1);
        setCyclotronLightState(c2Start, c2End, 2);
        setCyclotronLightState(c3Start, c3End, 1);
        setCyclotronLightState(c4Start, c4End, 2);
        
        doCycUpdate = true;
        reverseBootCyclotron = true;
      }else{
        setCyclotronLightState(c1Start, c1End, 2);
        setCyclotronLightState(c2Start, c2End, 1);
        setCyclotronLightState(c3Start, c3End, 2);
        setCyclotronLightState(c4Start, c4End, 1);
        
        doCycUpdate = true;
        reverseBootCyclotron = false;
      }
    }
  }else{
    if ((unsigned long)(currentMillis - prevCycBootMillis) >= cyc_boot_alt_interval) {
      prevCycBootMillis = currentMillis;
      setCyclotronLightState(c1Start, c4End, 4);
      doCycUpdate = true;
    }
  }

  if( doCycUpdate == true ){
    cyclotron.show(); // send to the neopixels
  }
  // END CYCLOTRON
}

int cycOrder = 0;
int cycFading = -1;

// normal animation on the bar graph
void powerSequenceOne(unsigned long currentMillis, unsigned long anispeed, unsigned long cycspeed, unsigned long cycfadespeed) {
  // START POWERCELL
  bool doPowercellUpdate = false;
  if ((unsigned long)(currentMillis - prevPwrMillis) >= anispeed) {
    // save the last time you blinked the LED
    prevPwrMillis = currentMillis;

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

    // Update the leds
    powerStick.show();
  }
  
  // END POWERCELL
  
  // START CYCLOTRON 
  bool doCycUpdate = false;
  if( useGameCyclotronEffect == true ){
    // figure out main light
    if ((unsigned long)(currentMillis - prevCycMillis) >= cycspeed) {
      prevCycMillis = currentMillis;
      
      switch ( cycOrder ) {
        case 0:
          setCyclotronLightState(c1Start, c1End, 0);
          setCyclotronLightState(c2Start, c2End, 2);
          setCyclotronLightState(c3Start, c3End, 2);
          setCyclotronLightState(c4Start, c4End, 2);
          cycFading = 1;
          cyclotronRunningFadeOut = 255;
          cycOrder = 1;
          break;
        case 1:
          setCyclotronLightState(c1Start, c1End, 2);
          setCyclotronLightState(c2Start, c2End, 2);
          setCyclotronLightState(c3Start, c3End, 2);
          setCyclotronLightState(c4Start, c4End, 0);
          cycFading = 0;
          cyclotronRunningFadeOut = 255;
          cycOrder = 2;
          break;
        case 2:
          setCyclotronLightState(c1Start, c1End, 2);
          setCyclotronLightState(c2Start, c2End, 2);
          setCyclotronLightState(c3Start, c3End, 0);
          setCyclotronLightState(c4Start, c4End, 2);
          cycFading = 3;
          cyclotronRunningFadeOut = 255;
          cycOrder = 3;
          break;
        case 3:
          setCyclotronLightState(c1Start, c1End, 2);
          setCyclotronLightState(c2Start, c2End, 0);
          setCyclotronLightState(c3Start, c3End, 2);
          setCyclotronLightState(c4Start, c4End, 2);
          cycFading = 2;
          cyclotronRunningFadeOut = 255;
          cycOrder = 0;
          break;
      }
  
      doCycUpdate = true;
    }
  
    // now figure out the fading light
    if( (unsigned long)(currentMillis - prevFadeCycMillis) >= cycfadespeed ){
      prevFadeCycMillis = currentMillis;
      if( cycFading != -1 ){
        switch ( cycFading ) {
          case 0:
            setCyclotronLightState(c1Start, c1End, 3);
            break;
          case 1:
            setCyclotronLightState(c2Start, c2End, 3);
            break;
          case 2:
            setCyclotronLightState(c3Start, c3End, 3);
            break;
          case 3:
            setCyclotronLightState(c4Start, c4End, 3);
            break;
        }
        doCycUpdate = true;
      }
    }
  }else{
    // figure out main light
    if ((unsigned long)(currentMillis - prevCycMillis) >= cycspeed) {
      prevCycMillis = currentMillis;
      
      switch ( cycOrder ) {
        case 0:
          setCyclotronLightState(c1Start, c1End, 0);
          setCyclotronLightState(c2Start, c2End, 2);
          setCyclotronLightState(c3Start, c3End, 2);
          setCyclotronLightState(c4Start, c4End, 2);
          cycOrder = 1;
          break;
        case 1:
          setCyclotronLightState(c1Start, c1End, 2);
          setCyclotronLightState(c2Start, c2End, 2);
          setCyclotronLightState(c3Start, c3End, 2);
          setCyclotronLightState(c4Start, c4End, 0);
          cycOrder = 2;
          break;
        case 2:
          setCyclotronLightState(c1Start, c1End, 2);
          setCyclotronLightState(c2Start, c2End, 2);
          setCyclotronLightState(c3Start, c3End, 0);
          setCyclotronLightState(c4Start, c4End, 2);
          cycOrder = 3;
          break;
        case 3:
          setCyclotronLightState(c1Start, c1End, 2);
          setCyclotronLightState(c2Start, c2End, 0);
          setCyclotronLightState(c3Start, c3End, 2);
          setCyclotronLightState(c4Start, c4End, 2);
          cycOrder = 0;
          break;
      }
  
      doCycUpdate = true;
    }
  }
  
  if( doCycUpdate == true ){
    cyclotron.show(); // send to the neopixels
  }
  // END CYCLOTRON
}
to keep it simple I would put the powercell and sound effects on one arduino
The sound board does the hard work for you, there's no need to drive it with an Arduino unless you want it to trigger certain sounds. If you just want it to play a sound, all you need is power.

I have the Adafruit Sound board set with pin 0 grounded. That's the trigger pin. The startup & hum sound is [urlhttps://drive.google.com/drive/folders/1ksSNp483eWyteVQqRcolSgfY_wjdkVSS?usp=sharing]here [/url]- it's t00.ogg - t00 tells the soundboard to play it when trigger pin 1 goes to ground. In the future, it'll be named "", which will tell the soundboard to "t00lhold.ogg" - which will tell the board to play the sound and loop as long as trigger 0 is grounded.

There's no diagrams, because honestly, they're not needed at this point. The Powercell & Cyclotrons leds are set up with their respective Nanos, and the soundboard outputs to an amp (currently powered by a DC wall-wart), which is then hooked up to speakers. Power is run off a common bus, supplied by a powerbank, which eventually be a TalentCell, to drive the amp and the arduinos (It has 5v *and* 12v out).



Here's Gucabe's code running on Tinkercad. I haven't implemented the switch yet.
Last edited by rolandblais on July 7th, 2022, 9:16 am, edited 1 time in total.
jonogunn liked this
#4971215
jonogunn wrote: July 6th, 2022, 6:46 pm Hi I finally got the neopixel sticks in so i was testing it out on the arduino with the code you provided. however it seems to only do the boot up animation and then remain with static lights. happened in IRL and tinkercad. am i missing something?
Looks like the animation sequence is never getting called from the main loop. Maybe that's a bad version of the code. Let me check in a bit. *Edit* Yep, that was is. What I posted was test code after a "cleanup" that didn't work. I've fixed the code in your link, and in my post. It works now. It needs to be cleaned up; I'll address that later when I have some spare time. Apologies!
jonogunn liked this
#4971227
rolandblais wrote: July 7th, 2022, 6:45 am
jonogunn wrote: July 6th, 2022, 6:46 pm Hi I finally got the neopixel sticks in so i was testing it out on the arduino with the code you provided. however it seems to only do the boot up animation and then remain with static lights. happened in IRL and tinkercad. am i missing something?
Looks like the animation sequence is never getting called from the main loop. Maybe that's a bad version of the code. Let me check in a bit. *Edit* Yep, that was is. What I posted was test code after a "cleanup" that didn't work. I've fixed the code in your link, and in my post. It works now. It needs to be cleaned up; I'll address that later when I have some spare time. Apologies!
Thanks dude. I took a deeper look at the code and I managed to clean it up and deleted all the cyclotron code. It's now 100% a powercell only code. I updated my file if you want to copy from that for yourself. I saw the code that was missing that you mentioned and how that function works and did a lot of trial and error until I got it to work.

Btw are you planning to do a full 3D print build with the wand or are you going with the Hasbro wand route? I ask since it seems liek you are keeping the pack lights and sounds simple.
#4971234
I updated my file if you want to copy from that for yourself.
Perfect! I was going to try and do that today but haven't had the chance yet. I'll back it up for myself asap. I appreciate it!

are you planning to do a full 3D print build with the wand
Probably. I currently have 1 Hasbro Wand, and 3 more on order (to go with the Haslab packs - yeah I kinda went a little crazy). I'll likely do an EVA and/or 3d printed wands as well. The current goal is to finish 1 3d printed pack, for myself and my Hasbro Wand, then 2 more EVA packs & wands for my wife and grandson. Gonna be a busy summer lol. :-)
#4971236
for Venkler stantzmore:

"So if I pick all this up and add your code to my spirit Halloween pack. It’s golden?"

Yep. You can do everything with 2 Arduinos and neopixels - code is in the post above. Or....

You can even do it with 1 Arduino, and GuCabe's revised code - see this Tinkercad circuit. It's pretty cool - he added a flag so that you can choose between GB1 and Afterlife cyclotron effects with a switch.

I would do some measuring etc of the pack though - they are not scaled 100% - I think they are around 83% - for example 2 8 neopixel sticks from Adafruit fit in the Q-Pack Powercell; I don't know how that would scale for a Spirit pack. This is the 2 sticks in the Powercell:
Image
#4971241
rolandblais wrote: July 7th, 2022, 5:41 pm
I updated my file if you want to copy from that for yourself.
Perfect! I was going to try and do that today but haven't had the chance yet. I'll back it up for myself asap. I appreciate it!

are you planning to do a full 3D print build with the wand
Probably. I currently have 1 Hasbro Wand, and 3 more on order (to go with the Haslab packs - yeah I kinda went a little crazy). I'll likely do an EVA and/or 3d printed wands as well. The current goal is to finish 1 3d printed pack, for myself and my Hasbro Wand, then 2 more EVA packs & wands for my wife and grandson. Gonna be a busy summer lol. :-)
That sounds awesome! you guys gonna look awesome.

Are you sticking with the current layout where there is no "overheat" segment to the pack? Or are you looking to add more dynamic features. As in doing my idea of replacing the intensify button in the wand with a DPDT button and triggering a firing and then overheat/reboot animation in the pack?

basically like this at 0:22 in this video:
https://youtu.be/UI1YEHUnraw

And for your 12min sound effect since the start up and hum are in the same file does that mean that when it loops it'll have to randomly start from the boot up sound again?


Also I dunno if this helps or works okay on 1 Arduino nano but but I combined the powercell and cfunseth's cyclotron code into one (still waiting on my neopixel ring to arrive):
/*
* Example sketch for afterlife_cyclotron class
* Written By: Cole Funseth
*/

#include "afterlife_cyclotron.h"

#define PIN 3 // Which pin on the Arduino is connected to the NeoPixels?
#define HEAT_PIN 9 // Which pin on the Arduino is connected to the "overheat" signal?
#define NUMPIXELS 40 // How many NeoPixels are attached to the Arduino?
#define BRIGHTNESS 255 // How bright should the pixels be? (min = 0, max = 255)
#define GROUP 2 // How big of a group of pixels do you want to rotate?
#define INIT_SPD 255 // How slow do you want the animation to rotate at the beginning of the boot? (higher = slower, 255 max)
#define IDLE_SPD 10 // How fast do you want the animation to rotate during "normal" operation (lower = faster, 0 min)
#define HEAT_SPD 5 // How fast do you want the animation to rotate at overheat? (lower = faster, 0 min)
#define BOOT_DLY 5000 // How long do you want the boot animation to last?
#define HEAT_DLY 5000 // How long should the "overheat" ramp up last?
#define NEO_POWER 13 // for powercell
Adafruit_NeoPixel powerStick = Adafruit_NeoPixel(16, NEO_POWER, NEO_GRB + NEO_KHZ800);

// Possible Pack states
bool powerBooted = false; // has the pack booted up


// bootup animation speed for powercell
const unsigned long pwr_boot_interval = 40; // How fast to do the powercell drop animation on bootup
// idle animation speeds
const unsigned long pwr_interval = 55; // how fast the powercell cycles: One 14 led cycle per 756 ms

// Create a new cyclotron object
Cyclotron cyclotron(PIN, NUMPIXELS, GROUP, INIT_SPD);

void setup() {
// configure powercell
powerStick.begin();
powerStick.setBrightness(80);
powerStick.show(); // Initialize all pixels to 'off'

//Setup and start the cyclotron
cyclotron.setBrightness(0, 0);
cyclotron.start();
cyclotron.setSpeed(IDLE_SPD, BOOT_DLY);
cyclotron.setBrightness(BRIGHTNESS, BOOT_DLY);

//Set "overheat" signal pin as an input
pinMode(HEAT_PIN, INPUT_PULLUP);
}

void loop() {
// get the current time for powercell
unsigned long currentMillis = millis();
if( powerBooted == false ){
powerSequenceBoot(currentMillis);
} else {
powerSequenceOne(currentMillis, pwr_interval, pwr_interval, pwr_interval);
}
delay(1);

//Update the cyclotron (should be called as frequently as possible)
cyclotron.update();

//Delete the "!" below if you want to invert the overheat signal for your board
//This signal isn't debounced, so it may be wonky with noisy signals
if(!digitalRead(HEAT_PIN)) cyclotron.setSpeed(IDLE_SPD, BOOT_DLY);
else cyclotron.setSpeed(HEAT_SPD, HEAT_DLY);
}


/*************** Powercell Animations *********************/

unsigned long prevPwrBootMillis = 0; // the last time we changed a powercell light in the boot sequence
unsigned long prevPwrMillis = 0; // last time we changed a powercell light in the idle sequence


// LED indexes into the neopixel powerstick chain for the powercell
const int powercellLedCount = 14; // total number of led's in the animation
int powerSeqNum = 0; // current running powercell sequence leds

// animation level trackers for the boot and shutdown
int currentBootLevel = 0; // current powercell boot level sequence led
int currentLightLevel = powercellLedCount; // current powercell boot light sequence led

// boot animation on the powercell

void powerSequenceBoot(unsigned long currentMillis) {
bool doPowercellUpdate = false;

if ((unsigned long)(currentMillis - prevPwrBootMillis) >= pwr_boot_interval) {
// save the last time you blinked the LED
prevPwrBootMillis = currentMillis;

// START POWERCELL
if( currentBootLevel != powercellLedCount ){
if( currentBootLevel == currentLightLevel){
if(currentLightLevel+1 <= powercellLedCount){
powerStick.setPixelColor(currentLightLevel+1, 0);
}
powerStick.setPixelColor(currentBootLevel, powerStick.Color(0, 0, 255));
currentLightLevel = powercellLedCount;
currentBootLevel++;
}else{
if(currentLightLevel+1 <= powercellLedCount){
powerStick.setPixelColor(currentLightLevel+1, 0);
}
powerStick.setPixelColor(currentLightLevel, powerStick.Color(0, 0, 255));
currentLightLevel--;
}
doPowercellUpdate = true;
}else{
powerBooted = true;
currentBootLevel = 0;
currentLightLevel = powercellLedCount;
}
// END POWERCELL
}

// if we have changed an led
if( doPowercellUpdate == true ){
powerStick.show(); // commit all of the changes
}

}


// normal animation on the bar graph
void powerSequenceOne(unsigned long currentMillis, unsigned long anispeed, unsigned long cycspeed, unsigned long cycfadespeed) {
// START POWERCELL
bool doPowercellUpdate = false;
if ((unsigned long)(currentMillis - prevPwrMillis) >= anispeed) {
// save the last time you blinked the LED
prevPwrMillis = currentMillis;

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

if ( powerSeqNum <= powercellLedCount) {
powerSeqNum++;
} else {
powerSeqNum = 0;
}

// Update the leds
powerStick.show();
}

// END POWERCELL

}
#4971246
you guys gonna look awesome.
Thanks! I'm hoping so! Lots of work ahead...

Are you sticking with the current layout where there is no "overheat" segment to the pack?
Yep, for now. But who knows? Vape pens aren't too expensive :-)

when it loops it'll have to randomly start from the boot up sound again?
Not randomly. Every 12 minutes. :-) It was the longest I could get within the file constraints of the board. Maybe with a DFPlayer, it could be different, but I'm working with what I've got :-) If I can change up the way I can trigger the startup vs the hum sounds, perhaps I could change the way it works, but for now, it is what it is.

combined the powercell and cfunseth's cyclotron code into one
I can't get it to compile. Lots of "undefined reference" errors. Probably because of the way variables are defined within the functions, but that's just a guess. Multitasking on Arduino is still out of my wheelhouse. But GuCabe's code is definitely something to explore. He's got both going at once.
    GB1 Pedal Build

    Walmart Ghost trap upgrade I bought the pedal to […]

    Looks like television broadcast announcements are […]

    This is the corresponding frame in the finished fi[…]

    I got an email to say my order was cancelled so […]