Double Zig Zag Blade Wiring / Config

Moving this topic to the Crucible.

Profezzorn (and everyone) - you mentioned in a previous thread the configurator may not work well for zigzag blades. The K4 config is amazing but I’m having trouble picking out what’s relevant. Wiring is also a bit more challenging.

As opposed to a Maul staff which has alot of blade and a smaller midsection, this staff uses skinny strips, 144 leds per blade, 36 leds per side. (quad zigzag). They are (obviously I suppose) .25 meters in length each. The strips are in series in for the date line and follow a side A up, B down, C up, D down pattern.

Since I am wiring without pogo connectors, how do you recommend wiring the negatives to the board? Normally I bridge pads 2/3 for blade 1 and 4/5 with for blade 2 with a single 470 ohm resistor. Should I stick with this or would it be wiser to have 2 sides of blade one wired to pad 2, the other to pad 3, etc? Other suggestions?

Regarding the config here’s the basic one the configurator produced with a few adjustments and Fett263’s prop file added and the styles trimmed to one example:

#include “proffieboard_v2_config.h”
#define NUM_BLADES 4
#define NUM_BUTTONS 2
#define VOLUME 1000
const unsigned int maxLedsPerStrip = 288;
#define ENABLE_WS2811
#define ENABLE_SD
#define FETT263_SWING_ON
#define FETT263_TWIST_OFF
#define SAVE_STATE


#include “…/props/saber_fett263_buttons.h”

Preset presets[] = {
{ “TeensySF”, “tracks/venus.wav”,
StyleNormalPtr<CYAN, WHITE, 300, 800>(),
StyleNormalPtr<CYAN, WHITE, 300, 800>(),
StyleNormalPtr<CYAN, WHITE, 300, 800>(),
StyleNormalPtr<CYAN, WHITE, 300, 800>(), “cyan”},
BladeConfig blades[] = {
{ 0, SubBlade(0, 143, WS281XBladePtr<288, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3> >()),
SubBladeReverse(143, 287, NULL),
SubBlade(0, 143, WS281XBladePtr<288, blade2Pin, Color8::GRB, PowerPINS<bladePowerPin4, bladePowerPin5> >()),
SubBladeReverse(143, 287, NULL)
, CONFIGARRAY(presets) },

Button PowerButton(BUTTON_POWER, powerButtonPin, “pow”);
Button AuxButton(BUTTON_AUX, auxPin, “aux”);

Still trying to wrap my head around the BladeConfig Section. It looks to me like the numbers are off but I’m really not sure as SubBlades are new to me. Any adjustments I should make before testing?

I recall you (Profezzorn) mentioning that for the K4 design, each style was repeated 4 times for the main blade (you were using a QUADBLADE macro but I think I’ll skip that for now). I see 4 here, but since there are two blades should there be 8?

Thank you so much!

The configurator works well for 2-strip zigzag blades. It does not work for quad-strip zigzag blades.

In general, you want the LED pads to be bridged together to avoid voltage drifting, so i would stick with wiring it the same way you have been doing.

In your case you will want NUM_BLADES to be 8, and the blade config section would look something like this:

BladeConfig blades[] = {
{ 0,
  // first quad-zigzag blade  
  SubBlade(0, 35, WS281XBladePtr<144, bladePin, Color8::GRB, PowerPINS<bladePowerPin2, bladePowerPin3> >()),
  SubBladeReverse(36, 71, NULL),
  SubBlade(72, 107, NULL),
  SubBladeReverse(108, 143, NULL),

  // second quad-zigzag blade
  SubBlade(0, 35, WS281XBladePtr<144, blade2Pin, Color8::GRB, PowerPINS<bladePowerPin4, bladePowerPin5> >()),
  SubBladeReverse(36, 71, NULL),
  SubBlade(72, 107, NULL),
  SubBladeReverse(108, 143, NULL),

  CONFIGARRAY(presets) },
1 Like

Thank you! I can see clearly how the subblade config section is set up.

I was cleaning up my CONFIG_TOP and feel like this might be in error:

‘const unsigned int maxLedsPerStrip = 288;’

I think that once you go from normal to zig zag, the numerical value here would double from 144 to 288 since I’m treating the LEDs as a series instead of 2 parallel strips.

Since my blades are small and only have 140 LEDs total in each, should I adjust that line like:

‘const unsigned int maxLedsPerStrip = 140;’

I noticed the configurator sets that line of code to 144 even if I choose less LEDs in my build length. Is the 144 value a required minimum? Does it matter? That would mean that my line should read:

‘const unsigned int maxLedsPerStrip = 144;’

All 3 choices compile.

Thank you!

maxLedsPerStrip controls the size of a buffer that is used to store the color values for a strip before/while they are fed out to the data line. That color buffer needs to be at least as much as the longest chain of LEDs you have in your saber. It doesn’t need to be longer, because we only do one blade at a time, and the buffer is shared between all the blades.

The thought behind keeping it at 144 by default is that most people won’t have to change it. Making it lower will save a bit of RAM, but unless you are planning to use that RAM for something, it just doesn’t matter. Also, having a little bit of extra space actually can speed things up a bit, because the buffer management code can start filling up the buffer as soon as there is enough room to fit the data for the next blade in there. How much extra space is needed and how much it speeds up depends entirely on your configuration, so it’s hard to predict.


This project is being bench tested and is running great thanks to your help. I went with 8 ohm speakers in parallel in the end, and it sounds fantastic!

There are a few moments when the effects slow down a bit in the blades. Will increasing maxLedsPerStrip help?

I also noticed this define in Cloudfeather’s work:


Is that something I can use as well to improve performance?

The dash of grinding isn’t constant. Thank you!

increasing maxLedsPerStrip and using EXTRA_COLOR_BUFFER_SPACE does the same thing. It is entirely possible that using one of those will improve the performance a bit. The other thing to look at is to enable optimization when compiling.

Further ideas for speeding things up:

I should add a section for EXTRA_COLOR_BUFFER_SPACE.


Never mind, it already mentions increasing maxLedsPerStrip a bit.

Thanks for that primer on buffering. I’ll keep fiddling with it a bit. It still super cool just trying test patterns with 4 sided blades.

Smoothswing sounds spectacular during spins and swings with the speakers split like they are, but there are dead spots during some movement patterns (meaning lots of motion but only the hum plays). The one that stands out is the basic movement for a lot of “jo kata” - thrust (poke straight ahead with with nothing snappy at the end), then rock back and lift the stick over your head while it’s held flat.

Seems like “thrust” and “push” are configurable factors. Would there would also be the reverse of the thrust (maybe a “pull”, but not the super yoink that triggers stab)?

When a thrust is triggered (not a stab), is there a .wav file attached to that?

Any suggestions on how to get these sweepy, rocking motions to trigger some more sound (preferably smoothswing itself but .wav file playback is cool)?

It’s 4 motions: thrust, pull, lift, and drop (or less if thrust plays forward and back and push is omnidirectional) - all horizontal and clashless.

Thank you!

These types of movement all fall into the category of “translation”. Unfortunately, detecting translation well turns out to be somewhat difficult, and my attempts so far have not been successful, so we generally don’t have wav files for that. Some props simply use fusor.mss() (which returns the accelerometer minus the “down” vector.) and uses that as a way to detect movement. The drawback of this approach is that it if you do a thrust motion, you get two movements, one at the start and one at the end, and telling them apart is actually pretty hard.

The proper solution is to integrate the acceleration over time, which becomes “speed”, and then we can trigger on that instead. However, that integration is very unstable and tends to either generate large random spikes or wander off into infinity. I’ve tried to include some dampening in the integration, but my attempts caused just as many problems as it solved.

Maybe if I’m bored over the summer I will have another go at making translation detection work better. It certainly would be a nice feature, it’s just not easy to get it to work right.