Multisegment pattern

Hi all,

I just got a Pixelblaze, I’m completely new to addressable leds and I must say I’m very impressed with the possibilities.
I’m building a modular light for my girlfriend’s birthday, one where she will be able to connect wooden blocks that will contain a set number of leds(around 15 per block), and make any shape/length she wants-she loves puzzles and light, so I know she will love it:). I have solved all hardware issues, connections etc, but the code is way beyond my abilities.

I’m trying to have a few preset patterns for her to play, without having to touch the edit page as she is equally bad-or possibly worse- at it as I am. Given the modular nature of the light, I want her to have the ability to change colours or patterns along the strip and divide it as she pleases, all done with sliders.

I’ve played around with the multisegment pattern by @zranger1, it is pretty much what I’m looking for, but with one major problem: It won’t keep changes, on every restart it switches to defaults.

I understand that the way to go is to have local-per segment- variables stored, but given that they all share the same sliders, how is that possible?

I have many other questions, but I’d like to start with this one and keep the rest for later, some I might even succeed in answering myself:)

I’m not looking for someone to write the code for me, I’d like to understand how to do it myself, so please try to guide me through it.

By reading example patterns today, I managed to create the following, given my first foray in it I’m quite happy, no matter how simple-and possibly wrong it my look:

    // Colour Picker 1

var hue1 = 0, saturation1 = 0, value1 = 1
export function hsvPickerHue1(_h, _s, _v) {
hue1 = _h
saturation1 = _s
value1 = _v
}

//Colour Picker 2
/*var hue2 = 0, saturation2 = 0, value2 = 1
export function hsvPickerHue2(_h, _s, _v) {
hue2 = _h
saturation2 = _s
value2 = _v
}
*/

export function sliderDepth(v) {
depth = (v * 30);
}

export function render(index) {
if (index < pixelCount / depth) {
hue = hue1
saturation = saturation1
value = value1
hsv(hue1, saturation1, value1)
} else {
hsv(time(.1) + index/-pixelCount, 1, 1)
}

}

/*export function render(index) {
if (index < pixelCount / depth) {
hue = hue1
saturation = saturation1
value = value1
} else {
hue = hue2
saturation = saturation2
value = value2
}
hsv(hue, saturation, value)
} */

The first test was a simple divide of colours with the ability to move the divide across the strip, after that I added a rainbow in the second part, that’s why part of the code is commented. This is of course nowhere near what I’m looking for and know that zranger1’s example is the way to go, but thought I’d post it to show I can at least understand this much:)

btw, how do I add code to a post? Clearly not the way I did it.

1 Like
indent preformatted text by 4 spaces

Is for code.

While variables will remain stored in a pattern, I suspect for this, you’ll have to make each segment it’s own variable space if you want it to be able to recall all of the settings. @zranger1 will likely help here, or maybe @wizard has an idea?

@petros, I’d be glad to help get your lights running, and to answer what questions I can.

Here’s the deal with the multisegment pattern. Right now there’s no way for a pattern to save all its variables between runs. The multisegment pattern is actually made to be used with home automation systems running on larger computers - the home automation platform handles all the saving and restoring of segment configuration and state. Setting up the Web UI version for long term use is a little more involved.

If you know how you want your segments configured on pattern load/startup, it’s actually fairly easy to modify the code to do that.

  • at around line 39, change the __n_segments = 4; to the number of segments you want
  • comment out the default initialization loop (lines 283-290 – the block that starts with
    // Initialize all segments to...)
  • Set startup values for each of your segments, using the following function calls:
    SetSegState(<segment number>,true) ; – turns the segment “on” (false is off)
    SetSegEffect(<segment number>,<effect number>) - sets the animation for the segment. (0 is none)
    SetSegHSB(<segment number>,h,s,v); - sets the initial color for the segment
    SetSegSpeed(<segment number>,1); - sets initial speed for animations
    SetSegSize(<segment number>,<pixels>); - sets the number of pixels in the segment. It will automatically figure out start/end locations. Comments around line 203 explain the rules for that.

Once you’ve done this for each segment,and saved the pattern that’s it. The pattern will come up initialized your way when you load it or restart your Pixelblaze. I do suggest saving with the
“Enable Web UI” slider set to off, because it’s possible that saved slider settings might mess up your first segment on load. To use the web UI, just turn it back on when you load!

You also might want to pick up the latest version at https://github.com/zranger1/PixelblazePatterns/blob/master/multisegmentdemo.js . I’ve probably updated some of the effects since I last uploaded to the library.

2 Likes

Hi all, thanks for your answers.

@zranger1, thanks for the tips, I’m taking your pattern line by line trying to understand what is what and how I can modify it. I’ve removed all effects apart from static colour, brought max segments down to 4 for now. I still want to see how these can be modified and saved individually through the webUI(maybe add hsv pickers for each segment?), but the array is making it difficult. If I can’t figure that out, I’ll see how I can keep only the part of your code that splits the strip to as many segments as defined by the slider and move on from there. I’ll spend the day on this, I expect varying degrees of frustration:)

On a different note, as I’m playing around with simpler methods in order to understand the language, here’s another question:

In the simple code I posted in the beginning, I’m trying to divide a strip in 2 and use a slider to define each segment’s length.

export function sliderDepth(v) {
depth = (v * 100);
}

export function render(index) {
if (index < pixelCount / depth) {

The v * 100 is clearly not the right way to scale properly and I don’t know the math or logic on how to properly do it, that is move the division across the strip regardless of strip size(which I understand is done by using pixelcount).

Re the slider to determine how much of the strip you’ll use… Think of it this way:

Pixelcount is the entire strip. (Say 200 pixels, just to pick a value)

When you make a slider, whatever variable you put in (v is just a placeholder name, and works, it’s a totally local variable), the slider will control it’s value between 0 and 1. So it’s already a percentage.

So depth should be v * pixelcount, rounded down (floor), but the number of pixels is not accurate, as the actual pixels go from 0-199, not 1-200… so you might need to subtract 1. Let’s see…

So if you set the slider to none, it’ll be zero * pixelcount or zero. If you set it to 1 (all), it’ll be 200, which is higher than we have.

Let’s see how we’re going to figure out a segment, for the sake of discussion, let’s say segment 1 is 0 to “boundary”, and segment 2 is boundary+1 to end of pixels (Pixelcount -1)

What value should boundary be? That’s related to depth should be.
If we say None, boundary should be Pixelcount-1, right? (So seg1 is zero to the end)… depth is zero.
If we say All (let’s assume all means all but pixel zero, so seg 1 cannot be empty), boundary should be 1, or Pixelcount - depth (also 200 or maybe 199?)

so boundary should be Pixelcount -1 -depth

I know there are some rounding issues and ensuring you don’t end up with empty segments (which you could do, just would require some special code handling). And adding a 3rd segment, you have to have a start point (when seg 2 starts), and then calculate the depth of what’s left. But basically, you see the approach I’m suggesting.

Sorry this is incomplete, I’m in my phone, but I wanted to point you in the right direction.

1 Like

@Scruffynerf ,

I went for this:

depth = floor(v * 100);

I thought, let’s get round numbers from 0 - 100, then use that as a percentage to get the division to move around in a linear way.

I thought that this would work:

if (index < depth % pixelCount) {

Of course it didn’t. I tried all sorts of alternatives but get either funky results, or the division moves upto a certain bit of the strip.

For the sake of discussion, I got 300 leds connected, but that should make no difference as I want the code to not be led-number specific.

Next question, how do I add a 2nd division(3rd segment)? As you said, I need to calculate my new starting point by subtracting the 1st division from my pixelCount, then adding 1. How’s the math for that?

I’m already using an if → statement to get from segment 1 to segment 2. If I add a 3rd segment, do I do if → if → else?

In regards to turning off segments, my simplistic approach would be to just move the hsv picker all the way down in the gui!

Here’s where I am at:

I discovered the “else if” statement, now I’m able to divide in as many segments as I want, and have gui access to them individually. It’s not a pretty way, as the hue pickers will be in the gui regardless of the segments I want active(I wonder, is it possible to use “if” statements to have the pickers appear depending on active segments?). I applied this method at zranger1’s Oasis pattern, and I’m able to divide it in 2 segments with different colours each, nice:)

The math is still wrong, I could use some help with that, please have a look at the code:

// Colour Picker 1
export function hsvPickerHue1(h, s, v) {
hue1 = h
saturation1 = s
value1 = v
}

//Colour Picker 2
export function hsvPickerHue2(h, s, v) {
hue2 = h
saturation2 = s
value2 = v
}

//Colour Picker 3
export function hsvPickerHue3(h, s, v) {
hue3 = h
saturation3 = s
value3 = v
}

export var depth1
export function sliderDepth1(v) {
depth1 = floor(v * 100 );
}

export var depth2
export function sliderDepth2(v) {
depth2 = floor(v * 100 );
}

export function render(index) {
if (index < depth1 % pixelCount) {
hue = hue1
saturation = saturation1
value = value1
hsv(hue1, saturation1, value1)
}
else if (index < (depth1 % pixelCount) + depth2) {
hue = hue2
saturation = saturation2
value = value2
hsv(hue2, saturation2, value2)

} else {
hue = hue3
saturation = saturation3
value = value3
hsv(hue3, saturation3, value3)
}

}

I still don’t get how to properly paste code in here, sorry:)