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

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 Lost Wax's EVA Proton Pack build videos, 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.
Last edited by rolandblais on November 1st, 2022, 9:01 pm, edited 1 time in total.
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 here - 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 February 20th, 2023, 9:39 pm, edited 2 times 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.
#4972477
Hi Roland

lol ok so for the life of me I am trying to take your 30min ogg file and separate the start up part of it (i notice there's a gap where it fades down after the start up so i figured I'd use that point to split it). The issue is whenever i export from the audio program on my pc I can't get it to export using the exact same source as the original file and thus end up with bigger files! ugh. sorry to ask but would you be able to do it for me if you have time?

btw I have some exciting stuff from the electronics set up that we have been discussing that invovles overheat! I'll share it with you when it's all finished.
#4972480
btw I have some exciting stuff from the electronics set up that we have been discussing that invovles overheat! I'll share it with you when it's all finished.
Nice! I'm looking forward to it. I haven't had time to do anything - life kind of took up all my time. But with Halloween around the corner, I'm going to be ramping things up...

regarding
I am trying to take your 30min ogg file
All mine are WAVs:

Image

But, the file "GBAL_Pack_Startup.wav" is a 20 second startup sound.

I got the original sounds from here, courtesy of the "Die Geisterjäger „Ghostbusters Fans from Germany“" Facebook Group. This was the original post.

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

Wow, an update...

So because I'm a [professional procrastinator, I hadn't really done much in the last few months, then decided a couple of weeks out that I wanted to be ready for Halloween..., because why not, right? After a 2 week-ish marathon, I present the "jank pack v1.0" - it's about 80% complete, I'd guess.

I don't have a lot of in-progress pics, but here's a couple after priming:
Image

Image

And obligatory "in action" video:


Motherboard mounting to the pack and subsequent mounting of the brackets and shell took place Sunday evening. Because of some setbacks and workarounds, it took a lot longer than anticipated. The center mount required a longer bolt than I had - I needed at least a 2" bolt and mine were 1.5" and the hardware store had closed, so I had to cut a block of wood and use it behind the motherboard, along with a 2" (or 2.5"?) wood screw. It worked fine, however because of the placement of the printed parts of the shell I had to trim the block down a couple of times, but eventually got the shell to seat on the motherboard. It was around 12a when that was completed...

After mounting each different component into the shell, I would test the system and make sure everything worked as expected before moving on to mounting the next component. Time consuming, yes, but I didn't want to get everything assembled, and then see that it didn't work, and have to take it all apart again. Around 2a, everything was installed, and shell and motherboard screwed together. Everything worked. I stood the pack up in the guitar stand I'd purchased for it, and tried it one more time, just to be sure.

Nothing happened.

I tried it again.

Still nothing.

I checked the seating of the usb cable into the Talentcell battery velcroed to the back of the mother board. Yep, it's seated well; still nothing. I tried switching the talentcell on and off; still no-go. I removed the shell and looked at the wiring - everything looked connected and seated, no issues there; still not firing up. I tried a different battery; no dice. I'd given myself a deadline of 2:30a for fixing it, because I have to wake up at 5:30a to get ready for work, and it was now 5 minutes past that deadline. I'd resigned myself to not wearing the pack at work or trick or treating. Ah well.

After feeding the pets at 6a, I was looking at the pack and figured, "Ah what the hell. Try it one more time." Boom! It fired up. I reassembled the pack to the motherboard and tried it again. Still working! I attached the speaker to the pack and tried it again. Yep, still works! I donned the pack, turned it on again, and walked and jumped around to test durability. Still blinking and humming, Excellent! I still have no idea what happened, but who cares, I now have a "working" Unlicensed Nuclear Accelerator.

Still made it to work on time, and folks really liked it. What was especially fun was I'd have it off, and people would look at it and say "wow that's really cool" or similar, and I'd look at them and say "Well, let's get ready. Switch me on... red switch, upper left." And let them flip the switch to turn on the pack. That always elicited a smile.

One unexpected effect of switching from the on-board amp & speaker I was going to use to an auxiliary speaker and audio cable, was that because of the bass, the pack had a tangible "rumble" feeling. No need to install an additional motor to simulate that effect. I had the speaker zip tied and velcroed to the motherboard and pack, but because I had it in a bad position, the audio cable pointed straight back and hit me in the belt-line, causing it to fail. I don't know if the cable went bad or the plug in the speaker is now damaged, but that's troubleshooting for another day. The speaker also has a fiddly startup sequence, but because it delivers good bass, I don't know if I want to switch back to the internal amp and speaker.

Another thing I may revisit is how I wired up power. The way it works now is via a usb cable plugged into the battery, then the other end is stripped and +/- plugged into a a small breadboard. Each Vin and GND for the Arduino Nanos and the SFX board are plugged in to the same +/- rows on the breadboard. I think a simpler approach would be to still use usb-out from the battery to a usb hub, then use usb cables to each board, since they already have the usb-in soldered on. I could easily wire in the main switch to the usb hub cable, to turn everything on & off.

Things I learned -

Filler primer dries pretty quickly. Paint sprayed onto polyethylene tubing does not.
No matter how sure you've spray painted every surface, you haven't. When you mount the shell on the motherboard, you'll find a spot you missed. A couple days after that, you'll find another.
Speaking of motherboards, don't forget to paint both sides.
Don't mount your external speaker in such a way that the aux cable for sound is poking directly into your back. It will fail.
People don't care if there's audio, or even if there's blinky lights. The fact you're wearing a Proton Pack will still elicit a smile.
Don't stress every missed detail, cracking paint, or drip run. It's a Proton Pack, not a Piano.
Put padding on your pack frame from the beginning.
If you think you have enough nuts and bolts, you don't. Don't start anything you can't finish before the local hardware store closes.
Sew or epoxy the pack strap quick release buttons. They'll inevitably fail, potentially swinging the back off your back.
Sometimes crazy glue takes forever to dry, even when adding additional moisture. Make sure nuts are firmly glued to their brackets, or else you're going to have a bad time when trying to screw in the bolt blind.
Either really sand and seat your v-bracket for your Thrower really well, or use a metal bracket system.
The S-hook on the Spengler Wand is not quite enough for hanging on a belt; I added a carabiner on the belt to hang it from, and it was still iffy. I kept my hand on the handle most of the time after almost losing it once. I'm thinking of getting a metal bracket for the "V" mount on the thrower.


But for now, I'm taking a short break and reorganizing my work area :-)




Here's a couple more pics of Halloween.

I'm terrified beyond the capacity for rational thought.
Image

I need somebody to photoshop a Proton Stream in there :-) (edit - I did. Thanks to a great tutorial and trial PS subscription.)
Image

Hard to see but I've got my modified Disguise Ghost Trap and Attenuator both on
Image

My Wife and Grandson also suited up for separate events; I'm hoping to get a group picture soon.
Image
Image
Jimsy33, jonogunn liked this
#4976938
Paco wrote: January 14th, 2023, 11:47 pm i meant for firing. i eventually realized where to put the main switch but for the firing trigger that causes the sound to cue and the LEDs to spin rapidly.
Ah, ok - I don't have my wand connected electronically to the pack. It's a Spengler and I don't want to mod it :-)

The circuit this build is based on doesn't have provisions for adding a wand.

    The yellow parts are raw 3D prints, unsanded and u[…]

    Sorry, I hadn't seen any of these replies. Either […]

    Uniform Tips

    Sorry for the triple post (you guys have gotten […]

    Proton Props???

    Ugly Little Spud, Did you actually get the pack?[…]