Slider Application Questions

Yes, entirely different v’s

Slider can use any variable name, but v (Value /Variable) is the example given It’s a local variable and isn’t global. In your above example, you DID export h but not hue (the value in the function), for example, which makes the ones exported into global I believe. If you tried just using hue in render(), it wouldn’t work. h works as expected

In hsv, it’s a different V, in Hue Saturation and Value… And it’s roughly equal to brightness. (Gamma correction being one example of where it’s not quite identical)

As for Min Max, it was my example and those are arbitrary, up to you in whatever case you have.

Maybe Min is zero and Max is 10

Or Min is -2 and Max is 2, etc.

It’s a formula, you pick the values.

This is really basic (idiotic) stuff I know, but its easy to get stuck in infinite do-loops… not having coded in any fashion for over 35 years it comes slow, and I get stuck on syntax, definitions. My last run programming was using Pascal to run an interface to machine tools running G-Code… a far cry from PB-specific JavaScript. Then there was FORTRAN, but that’s another story.

I am working on my own elementary reference to definitions and syntax examples, concrete examples, that is look-up able.

Local vs global for variables is an awesome point. Something to work with, thanks @Scruffynerf !

Scaling that slider… well that’s easy, just multiply the variable times some factor. Done deal. But not immediately apparent to the new.

So there ya go. Have a great day.

I’ll try to break down the scopes and variable visibility.

//this is the global scope, code here runs once when the pattern loads
//variables created here may be accessed in any scope
var thisIsAGlobal = 1
thisIsAnImplcitGlobal = 2
function thisIsAFunction (thisIsAParameter, anotherParameter) {
  //this is a local scope, code here runs when the function is called
  //variables created here may be accessed only while this function runs
  //parameters are also locally scoped, and work just like local variables
  var thisIsALocal = 3
  //however, you can also implicitly declare globals when the 'var' keyword isn't used
  thisIsAnotherImplicitGlobal = 4
}

Keep an eye out for implicitly declared globals in a function. The default rainbow uses these! I’ll annotate with comments:

export function beforeRender(delta) {
  t1 = time(.1) //this creates an implicit global, which will be used later in another function
}

export function render(index) {
  h = t1 + index/pixelCount // Here the global t1 is accessed. 
  // this also created another implicit global 'h', but it could have been a local 
  s = 1 //another 
  v = 1 //another
  hsv(h, s, v)
}

The other trick to scopes is that it’s possible to create independent variables with the same name. When a function declares a variable or parameter, it will shadow (hide) a global with the same name. Here are 3 different count variables:

var count = 10 //a global

function setCount() {
  count = 30 // the count global may be used or modified. calling this function will set the global count
}

function myFunction() {
  var count = 5 //a local variable, declared with the 'var' keyword and will shadow the global
  //the global count is a different variable, and now cannot be seen/used by this function
  //...
}

function otherFunction(count) {
  //here, a parameter is called count and acts just like a local variable
  //the global count is a different variable, and now cannot be seen/used by this function
  //...
}

I think some of the confusion comes from patterns using variables called h, s, and v as a shorthand, and implicitly declaring them as globals. When a slider function also has a parameter called v it is a completely different variable. These names could be anything, and perhaps using names with more uniqueness and careful attention to locally scope variables would aid in readability.

Here’s a pattern that sets all variables up with proper scope and with unique names. It is a basic moving rainbow with its own brightness slider.

//declare globals
var brightness //used to set the overall brightness through a slider
var t1 //a sawtooth waveform passed between beforeRender() and render()

export function sliderBrightness(sliderValue) {
  //copy the local parameter sliderValue to the brightness global so it can be used later
  brightness = sliderValue 
}

export function beforeRender(delta) {
  //generate a sawtooth waveform and store the current sample in the t1 global
  t1 = time(.1)
}

export function render(index) {
  //declare local variables.
  var h, s, v
  
  h = t1 + index/pixelCount
  s = 1
  v = brightness //here the V of HSV comes from the brightness global
  hsv(h, s, v)
}

Here is the same pattern but using shorthand variable names and lazy variable scoping. It relies on both implicit global declaration for t1, and scope shadowing for v. Tricky!

export function sliderBrightness(v) {
  b = v
}

export function beforeRender(delta) {
  t1 = time(.1)
}

export function render(index) {
  h = t1 + index/pixelCount
  s = 1
  v = 1
  hsv(h, s, v * b)
}
2 Likes

I had no idea there could be local variables inside functions that have the same name as other variables without causing problems. Every time I saw a ‘v’ I assumed it was the same ‘v’. Very confusing. These little things really trip up us noobs when looking at other code.

First, thanks @wizard! Heading toward some clarity here.

These things do add up, can consume lots and lots of time… as in, “how and why does this work or not work?”, and etc.

Terminology and operation and function of types of code is often obscure. Examples include arrays, modes and terms like “flake”. Applied examples really help. Operating examples that one can work with.

That is why I wrote that little piece of code above, to just work with sliders and very simple timing. I wanted to figure out these “nested” variable calls in slider language.
And, I just wanted to turn some lights on and off, and vary the timing. Only that. No refinement.

Perhaps bits of code like this could be made available for noobs as teaching and demo tools. Label them as such. Perhaps there are other plans.

What do you think?

that’s one of the many reasons we started the Academy: to identify the pain points, and improve the tutorials, since once you ‘get it’, it’s harder to see what’s not clear. So fresh eyeballs help all of us.

I see PB as trying to be ‘artist’ friendly, as opposed to just taking a ESP32, adding WLED or FastLED libraries, and doing similar stuff, all of which would require way more technical/programming experience.

1 Like

@JustPete, @SeaLaVie,
Yes, I agree. Thank you for working with this and keep trying! Bit by bit things will fall in to place, and we’re here to help.

I also want to thank you for the perspective that this offers. I’ve put a lot of work in to making Pixelblaze more friendly and easier to learn for new coders (or even non-coders). Sometimes I suffer from being so engrained in this for so long that I blindly walk right past the thorny bits without thinking of how that might snag someone else. I will keep this in mind for sure.

2 Likes

I totally agree with Wizard on this point. I feel like when I started commenting and refactoring the default patterns I could see them with new eyes, but by the 30th pattern I experienced a funny phenomena: “Well. This is all straightforward. I can’t see what someone would be confused by. No need to comment.”

1 Like

I can see all the work and smarts you all put into this so I am glad you are not offended by my observations or suggestions. Sometimes the beginner reveals that which is not so obvious. I am definitely in the noob, barely has a clue category at this point.

So, should I proceed with posting narrow-topic “Teaching Patterns” like for the Flasher above? Would that be welcome? Or do you have other plans/concerns?

Perhaps a category of pattern identified as a Teaching Patterns - e.g.

Teaching Pattern - Sliders, Simple Timing, Variables

I wrote that Flasher pattern above for myself because I needed to isolate two simple issues: Slider config and simple timing.

At this point I would add commentary about local vs global variables.

Cheers.

1 Like

I enjoyed the “Arduino Cookbook” a few years back, so I wonder if we should have a category inside the Academy that’s like “Recipes” or “Cookbook” for posting Q&A about “How to do this one thing X”.

2 Likes

Probably. There are certain types of functions where there are no actual examples of working code and they are totally unintuitive to me. For example how to use arrays as lists of functions, and how to use the new array functions.

Yeah, ideally we can make an well-annotated language reference. PB is JavaScript-y but there are things JS can do that PB can’t. But for the folks who don’t know JavaScript, much of the current language docs assume things they don’t know.
Not Ben’s fault, he’s trying to document what’s he coded, so he doesn’t have fresh eyeballs.

A “PB 101” walkthrough would likely end up covering a lot of JS basics. Anyone have a good JS tutorial page/site/etc ?

Hey @spazzle,

For arrays as lists of functions, check out the “Example:” series that ships with Pixelblaze. There’s a bit more comments on the v3 ones. Example: Modes and Waveforms.

To see something similar where we store different renderer functions in the array instead of just hue or brightness functions, check out zranger1’s Multisegment (admittedly not the shortest possible example), or the shorter Shimmer Crossfade 2D in the Pattern library (page 3, or DL here).

Any other techniques you are wondering about finding examples for? I’d love to start a list as a possible TOC for an intro.

@Scruffynerf In the past, I recommended this subset of Codecademy’s Intro to JS to someone.

1 Like

Might be worth seeing if https://javascript.info
(Which is git repo’d and roughly CCed) is worth trimming down to the bits that do work for PB. A PB centric version might be a bit of work though, and I’m not sure it’d be used enough to justify.

I have found this site to be quite useful for basic JavaScript terms and use - https://www.w3schools.com/js/DEFAULT.asp

per @spazzle’s inquiry, there are what look like good sections on arrays.

1 Like

Ok, I think I see what I was missing there.

edit:
specifically the example on the PB edit page is

modes[0] = () => {/* do mode 0 */};

but it really should be something like

modes[0] = (a,b,c) => {f(a,b,c)};

like in the example you posted.

1 Like
modes[0] = (a,b,c) => {f(a,b,c)};

This creates a function that calls f with 3 arguments, and stores that in mode[0]. It is just a pass-through for a function f. It is mostly equivalent to this:

modes[0] = f

Neither of these show up in the examples though. In the examples, f is the name of the parameter used for the fraction of the strip. The closest is (f) => f which is a function that takes a parameter and returns it unmodified, a bit boring though it conforms to the same contract used for all of the other functions used in the array such that the caller can treat them similarly.

Note that functions can be referenced by value (no parens) in addition to being called (with parens). Likewise a function can be called later after being stored, so that later the function stored in mode[0] can be called with something like this mode[0](1,2,3).

The lambda syntax is used to create “anonymous” functions - which is a function definition that resolves to a value rather than defining a name. In JavaScript, you can make them with either equivalent syntax (note the missing name when using the function keyword):

function (a,b,c) {/*do something*/}

//same as

(a,b,c) => {/*do something*}

You’d normally do this in “functional programming” where you pass functions around (very useful for the new array methods!). In the modes example, it is because we are storing them in an array index and they don’t need a name.

Lambdas have further shortcuts when you want a function that returns a value. These are equivalent:

function (a,b) {
  return a+b
}

// same as
(a,b) => a+b

//or with parens to help visually
(a,b) => (a+b)

//or without return shorthand (curly braces used)
(a,b) => {return a+b}
2 Likes

I keep learning new things, so it’s not just the newbies.

I just (re)noticed this, and I agree, a set of Teaching Patterns is the way to go.
One pattern to flesh out one concept, at a time, building as it goes.
Kudos for voicing it, cause it jelled for me.

That will likely be the replacement I take up in place of Tasks, I think. Tasks was useful in many ways, but after doing them for a while, they weren’t quite scratching the itch people had.

I had to dig to find this after some absence and, well, teaching is always a challenge and I appreciate your doing it and thinking about it.

I still do like the idea of teaching patterns that “flesh out one concept at a time”, the challenge being, I suppose, identifying the concepts to be covered.

I kind of see them as tools, like populating a toolbox…

I do remember at the very outset just wanting to light one pixel, then move it around…

Anyway, bravo and lets keep on!

1 Like