Perfect. Got it.
Is there some reason for scattering the { }s about in that particular way?
Only for readability. The only thing required is ensuring you have matching pairs.
Curly braces are used in many computer languages (specifically those with syntax derived from the âCâ language.) to define blocks of code. Theyâre analagous to BEGINâŚEND pairs in older languages. People argue endlessly about the proper way to format them.
My take is this: do it in whatever way makes it easiest for you to understand when you come back after not having looked at that code for a while. (Itâs a general programming principle â be nice to the next guy. Itâs likely to be you!)
I usually follow these rules:
- Curly braces are optional for one line
if
statments. - The opening brace goes on the same line as the statement that opens it
- Code below a brace is indented two spaces. (Or more, to your taste.) Everything within a block is indented to the same level.
- If you open an new block within a block, indent two more spaces. The indentation will always tell
you clearly which block youâre currently looking at. - Closing braces go on a line by themselves, I sometimes break this rule for
else
statements because it doesnât impact clarity, and it makes the code shorter. (Itâs a good rule of thumb to to keep functional blocks to 1 screenful or less - makes it easier to see what theyâre doing.) - Never ever freaking ever under any circumstances use tabs to indent, unless you know for certain that your editor replaces them with spaces. Tabs will definitely bork the next guy, who is invariably using a different editor with different tab settings.
Hereâs a working example, from the multisegment pattern. (Ignore the code. Itâs looking at every pixel to see what segment itâs in, and calling an appropriate rendering function, but it took a lot of setup to get there, and itâs pretty meaningless in isolation. This one is just for the formatting!)
export function render(index) {
if (index >= segStart[segNumber+1]) segNumber++;
if (segEnabled[segNumber]) {
segRender[segTable[segNumber][__effect]](segNumber,segTable[segNumber],index)
}
else {
hsv(0,0,0);
}
}
Well, hereâs what I got so far.
export var hue
export var sat
export var v
export var theLitPixel
export var cycleTime
export var offdwell
export var timeFactor
export var delta // Just throwing out a bunch of variables to look at
export function sliderSpeed(v) {
timeFactor = random(1) * v * 10 // Some kinda slider
}
export function beforeRender(delta) { theLitPixel=floor(random(pixelCount))
cycleTime=delta*random(100) // Goes negative if >= 10,000. Not sure if affects anything, timewise. My attempt at
// imparting randomness to cycleTime/delta
}
export function render(index) {
delta = cycleTime
hue = random(1)
sat = random(1)
v = random(1)
if (index==theLitPixel) {
hsv(hue, sat, v)
}
else
{hsv(hue,sat,0)}}
The random pixel lit, color, brightness and hue was pretty easy. And the results quite nice, especially on a 16 x 16 matrix.
But, It seemed like there had to be a way to introduce a simple time function/duration (then randomize) to values like on-time and off-time, without the wave stuff, but I guess not. This is far as Iâve got at present what with the rest of life, taking care of Mom, fixing cars and houses, and an old brain. Comments welcome!
Couple of comments my code and stuff above -
-
I played with introducing a random factor to overall delta but it doesnât work the way I had hoped. Values for delta go negative somehow and the desired âslowdown the cycle effectâ is not achieved.
-
I am still not sure how best to introduce time delays in PB language. Seems like folks ~ typically use a wave, right?
-
Sliders - I did not know how a slider manifest in this arena until I cobbled one together nd voilà there it is in the user interface. I had wondered, why not just define a variable and adjust it in the code⌠Stupid, huh?
-
Twinkle - Iâm figuring the simplest manifestation is to modulate brightness according to some wave function, right?
-
Patience - Your patience appreciated. I do not expect to have all answered by you. Working with the language and interface is clearly most helpful. I do find myself trying to puzzle it out on âfirst principlesâ rather than copying otherâs code, which probably gets in the way.
-
My handle and background - Why Gandalf? Because I like the character, he has magic but is flawed, he is humane, and he is humble. Whatâs not to like?. He is an aspirational character in my book.
My background is in chemistry (lots and lots of spectroscopy) followed by physical product engineering, then energy efficiency consulting, outreach, and lots of quasi-business oriented reports, presentations and such⌠not so much coding thereâŚ
Re coding - I started with punch cards/Fortran, so Iâm getting up there, then Pascal, then lots of pretty much canned code, so thatâs my schtick, please bear with. Per the chemistry background Iâm pretty much here to model atmosphere, but thatâs another story. Cheers.
@Gandalf, I havenât had a chance to run your code yet.
Thatâs not quite how to use âdeltaâ. Think of it as a automatically set value, not one you should ever set. Delta is the time it takes to render one round of setting pixels. We discussed this recently. @devoh explored it. Thatâs part of the time delay solutions.
Yes, sliders are super easy. Kudos to @Wizard for the simple implementation.
There are many ways to âtwinkleâ, from random to smooth, all manner of ways to do it. Weâll come back to this in a few months likely.
Cool background and welcome⌠Good to know background of folks so we find a good level of interaction.
Hey, please donât worry about it. I may give it a try anywho.
Yeah, I figured delta was something I would try to manipulate with a random variable call, scaled, but it blew up and didnât have a discernable effect on the pattern. The apparent value of delta did go all over the place, tho. !
Check out this thread for an overview of common approaches!
I will walk thru a basic technique in the next few days. Sorry, Iâm a bit behind.
Thanks @ Scruffynerf!
Went to edit the post and hit âwithdrawâ⌠here it is again -
Believe it or not I am still STUCK in the weeds on this. Between all else (the Rest of Life) I cannot seem to connect these ideas to affecting LED on and off time. Yeah Iâve looked at the stuff⌠I donât want to copy otherâs code. So, hereâs mine and if someone can fill me in on how connect this to actually controlling on/off time that would be GREAT -
export var hue, sat, v, theLitPixel, onDwell, offDwell, plusDelta, twinkletoes
export function beforeRender(delta) {
plusDelta += (delta)
onDwell = 100 + random(2000)
offDwell = 100 + random(1000)
plusDelta = onDwell + offDwell
if (plusDelta > 3200) plusDelta = 0 // Max total cycle is 3,200 Ms, randomized
theLitPixel=floor(random(pixelCount))
hue = random(1)
sat = random(1)
v = random(1)
v=pow(v,2.5)
}
export function render(index) {
if (index==theLitPixel) {
hsv(hue, sat, v)
//twinkle
// hold this for some random time - HOW?
}
else
{hsv(0,0,0)}
// Hold this for some other time - HOW?
}
// hey
@JustPete, if @scruffynerf or @jeff donât beat me to it, I can help you with this code a bit tomorrow. Donât let it frustrate you - the language has a ton in common with Pascal, and absolutely nothing is going on in there that computers havenât been doing since the dawn of time.
Iâve been thinking for a while that it would be helpful to give everybody a better understanding of what the Pixelblaze is actually doing when it runs your patterns.
A good mental model gives you an orderly place to store all the details as you learn so youâre not just trying to memorize heaps of random unconnected facts, which is actually a nearly impossible task.
So hereâs my first shot at describing whatâs happening when a Pixelblaze loads and runs a pattern. Anybody whoâs better at making this sort of diagram, or has more complete information, please revise, expand and improve this!
(Of course,the flow is more complicated for the v3, which has two processors, but the same basic idea applies:
The Pixelblaze loads, compiles and initializes your pattern, then it loops forever calling beforeRender() to set up a frame, then render() for each LED, then it performs other behind-the-scenes system tasks.
Just wanting to say you guys are great. At this point my notes are scattered about and all I seem to get is static/sparks for that pattern. Whatever you may do, and whenever⌠fantastic!
I keep looking for do-is and do-while stuff⌠and I know thatâs a possibility
The timing thing is eluding me for now.
At least its not assembler⌠we used that for a few simple things, back in the day.
For now, Iâm collating some simplified definitions and terms, as follows, in a spreadsheet -
" % "
*=
**
â=â
â==â
â===â
â+=â
â-=â
â++â
â!â
â!=â
abs
array
break
CamelCase
channel
colorPicker
continue
delta
export var
export var
floor
for
h
hsv
index
âindex / pixelCountâ
LOGICAL OPERATORS and COMPARISONS
Lookup Table
mode
next
pow
random
render(index)
render
rgb
slider
snake_case
time(interval)
xor
I think I know the point Iâd like to hint you about.
Using @zranger1âs helpful diagram, notice that this code is inside beforeRender(delta)
â which means it will run once between frames. And keep in mind that a typical frame rate is 60FPS, or in other words, youâre running this 60 times per second:
Do you want to check if something is bigger than 3.2 seconds sixty times per second? Probably! But what about those on/offDwells
? And arenât you overwriting the plusDelta
you just accumualted delta into right above?
See how that goes for ya.
Iâll echo what @zranger1 and @jeff said, and add this:
Donât think of do while âŚ
Thatâs a different sort of programming
Keep in mind the two stroke engine. You donât want it to stall on one of the two operations it does, it should run smoothly 1,2,1,2,1,2âŚ
Trying to make it wait on 2, will only make the engine falter and sputter.
The on/off/twinkle is really all one thing:
The brightness of the light. So think of the problem like this:
Stroke one (BeforeRender):. How bright is the light? All of your timing happens here⌠Just keep track of the time, and vary the light brightness variable.
Stroke two (Render):. NO calculation here needed except for deciding what pixel is on or off. If itâs the pixel weâre lighting, then itâs brightness is that variable (which could still be 0), or itâs not that pixel, so itâs always 0 (off)
Repeat, repeat, repeat.
In your beforeRender() function: @jeffâs suggestions are good ones.
Near the line theLitPixel=floor(random(pixelCount))
, you have is the right idea. Youâre selecting the pixel you want to light at frame time. Thing is, unless itâs controlled by your timer, ( if (plusDelta > 3200)...
), it will select a new pixel on every frame.
This is what curly braces are all about - theyâre just a general purpose mechanism for marking off functional blocks of code. So if you set that piece of code up like this:
if (plusDelta > 3200) {
plusDelta = 0 // Max total cycle is 3,200 Ms, randomized
theLitPixel=floor(random(pixelCount))
hue = random(1)
sat = random(1)
v = random(1)
v=pow(v,2.5)
}
all the code between {
and }
will only be executed every 3.2 seconds, which will give you the timing control youâre looking for.
Thanks all⌠@Scruffynerf, @jeff, @zranger1. I really appreciate the input. Will be back @ it in coming days I anticipate an epiphany soon!
Per my above note, not to forget the Wizardly assistance of @wizard himselfâŚ! Thanks all!
I have now generated some random code. Seems to do the thing. I limited colors to the blue spectrum to make it more âstarlikeâ. I think I even did the curly-brace thing fairly right. Kudos to @devoh for slider idea and for getting it done wayyyy quicker than me. All things considered, a great exercise.
Here it is -
// Looks like stars, kinda. Limied to blue range. Hue and sat vary within a range. Intensity varies per double-sine-wave function.
// Harmonics, non-randomness or time-outs seem to be observed at low speedranger values.
// Looks nice at high Scintillation Settings
// 480 FPS at 16 Px; 35 FPS at 256 Px
export var SpeedRanger
export var ScintillationRanger
export var timer
export var dwell
export var theOneLitPixel
export var v
export function sliderSpeedRanger(v) {
SpeedRanger = 100 * v + 0.15}
export function sliderScintillationRanger(t) {
ScintillationRanger = t}
var dwell = random(90)
export function beforeRender(delta) {
timer += delta
v = random(wave(wave(time(0.1 * ScintillationRanger))))
if (timer >= SpeedRanger * dwell) {
timer = 0
hue = clamp(random(1),0.45,0.66)
sat = clamp(random(1), 0.4,1.0)
theOneLitPixel = floor(random(pixelCount))
dwell = random(90)
}
}
export function render (index) {
if (index == theOneLitPixel) {
hsv(hue,sat,v*v)
}
else {
hsv(0,0,0)
}
}
Excellent. I like the limiting to blue approach. Initially I thought to myself, you could do something like that with RGB value instead of HSV, but the variation of brightness intensity would be harder to simulate, so nice choice there.
Nice, @JustPete! And thanks, @Scruffynerf - this really was an excellent task with miles of room for creativity.
Thanks. Itâs a tough balancing act, out of the 5 tasks so far, given the constraints of a single strand, I tried to vary enough, and also keep it flexible.
I need to start a feedback thread.