So now I have to ask: how to incorporate brightness/dimming/gamma,

So now I have to ask: how to incorporate brightness/dimming/gamma, whatever you want to call it. For example: I’d like to run my strings at full power during the day so that they can be seen, however in the dark of night, they don’t need to be, so I’d like to dim them. Now I can hard code it of course, either set a channel to full 255 or lower to say 50. But there has to be a way to incorporate a calculation that can do this (based off of an RTC for example.) Furthermore, the channels won’t always be at 255. Let’s say you’re running a scrolling rainbow pattern, they won’t be 255 the whole time. One channel will fade down while the other fades up.

So, I’m sure there’s a way to do this so I won’t ask that dumb question. But I will ask, does anyone know of a mathematical way to apply a brightness value to the channel’s output? So that rather than saying array[px].r = xxx, you’d say array[px].r = . ‘brightness’ could be a value between 0 to 255, or also an arbitrary level of say 1 through 10.

Pointers to code are welcome. Oh, and I’m working with FastSPI2 by the way …

Patience :). The next preview release will incorporate an extra parameter to show which is a 0-255 scaling factor for that mind of brightness control :).

There’s some things I’m still shaking out and parts of the interface are in flux - but email me (danielgarcia at gmail) of you are impatient.

Also, this scaling comes at almost no CPU cost to you (except for bitbang’d spi, where there is about a 5% hit to max bandwidth.

When running multiple strings with one of them on SPI and the rest bit-banged, it makes for a very confused AVR. :slight_smile: And I’m waiting for the next test release to fix the analog pins bug as well as the ‘same port’ bug.

By the way, my goal here is quite literally what I said. I’m using a DS3231 to turn on/off a power supply that drives my LED strings. They come up while it’s still light out and stay on all throughout the night then shut off late morning. I’m hoping to incorporate a light sensor to detect ambient light and adjust the LED brightness accordingly. :slight_smile:

You’d basically be able to do, say, an analog read off the light sensor - map that back to 0-255 and feed that right into the scaling argument for show - all the rest of your code can still do its patterns/brightnesses from 0-255 as it wishes. My plan is to use this functionality for a global brightness dimmer :slight_smile: I know someone else who uses the brightness value to do bpm-based pulsing of light effects.

I’m really happy about being able to squeeze the brightness scaling in for free. It will save me a bunch of random code all over the place in the future, and more importantly, cpu time!

I’m also starting to see how things can get a bit unwieldy when having multiple strings on the same AVR. When addressing each LED as array1[px].r, array1[px].g, and array1[px].b, repeat for array2, and array-nth, it gets a bit tedious. Time to rethink this code and figure out a better way of doing this.

Take for example the following routine:
// snow flakes
void snowFlake() {
if (flakePause > 0) {
if (millis() - lastRun > ((flakeCnt > 0) ? flakeSpeed : flakePause)) {
pushString(0); // falling
leds1[NUM_LEDS - 1].r = flakeColor;
leds1[NUM_LEDS - 1].g = flakeColor;
leds1[NUM_LEDS - 1].b = flakeColor;
LED1.showRGB((byte*)leds1, NUM_LEDS);
lastRun = millis();
flakeColor >>= 1;
// make sure the last of the trail reached the bottom
// on a flake value of 255, that’s an 8 pixels long tail
flakeCnt++;
if (flakeCnt > ((NUM_LEDS - 1) + 8)) {
// flake reached bottom
flakeCnt = 0;
flakeColor = random(20, 256);
flakePause = random(250, 1000);
flakeSpeed = random(15, 51);
}
}
} else {
flakePause = random(500, 3000);
flakeSpeed = random(15, 51);
flakeColor = random(20, 256);
}
}

That runs great one a single string. The flakes fall at random intervals, random speed, and random brightness. However, expanding that to run across say four strings, each one separate from each other, things get hairy.

There’s a couple ways you can do this. One is that you can use one led array for all the arrays - and work with that in this code, then when you call show you can pass in an offset to the led array (e.g. leds + 25 or some such) which will shift where things get started (offset will eventually be an actual parameter to the function - also I’m working on a global controller where you map segments of an array of leds to controller(s) and then just call show with no arguments (other than maybe brightness) and it does the mapping for you - keep things simpler if possible (you will still, of course, have direct control).

Another possibility would be to have snowFlake take the array and the number of leds to work with in as parameters. Of course, if you want flakeCnt, flakeSpeed/Pause to be different for each of the strips, then you should start thinking about making a class - where you can have multiple instances, one for each strip of leds that you’re working with.

Once the library settles down and I get a chance to get some movement on some projects of my own, I have a higher level led and animation library that I use to organize things that I want to clean up and publish. (It defines generic things like patterns which can be given arbitrary segments of led arrays to work with, and handles making sure all the patterns get called and rendered, etc…)

What about something like, leds[x][px].r, leds[x][px].g, and leds[x][px].b, where ‘x’ is 0-nth representing each individual string (being leds[0] would refer to the first string, leds[1] the second, leds[nth] the nth +1 string? And while I’m at it, rather than having a separate line for each of .r, .g, and .b, is there a different, or perhaps better way of setting the three values in the array?

You could also do an array of arrays easily enough. As for accessing r, g, and b separately - honestly it’s not something I do often, but that’s mostly because I work in HSV and then translate to rgb at the last minute. That said, we’re going to be putting a definition for both RGB and HSV data types in the library and this is what the rgb def currently looks like:

struct CRGB {
union {
struct { uint8_t r; uint8_t g; uint8_t b; };
uint8_t raw[3];
};
inline uint8_t& operator[] (uint8_t x) attribute((always_inline)) {
return raw[x];
}
};

So you can say (assuming you have CRGB leds[NUM_LEDS] defined):

leds[i].r = 128;

or

leds[i].raw[0] = 128;

or leds[i][0] = 128;

to set r to half brightness. There’s some other operations that we’re going to be adding to the structure with an eye towards providing high speed versions of various operations that you might want to do on pixels.

No, what i mean is, if I want to set a color right now, I do that by addressing each pixel’s r, g, and b values:

leds[px].r = 255;
leds[px].g = 255;
leds[px].b = 255;
LED1.show((byte*)leds1, NUM_LEDS);

I’m just wondering if there’s a better way of doing that.

Not really, certainly not more efficient (the libraries that use “setPixel” functions incur a bunch of extra overhead when you use those functions if the compiler doesn’t end up optimizing/inlining the set functions, which it often doesn’t).

If what you’re asking for is a way to set all the values to the same color at once - right now there isn’t a single line of code way to do it, unless you want to set all the r, g, and b values to the same value, as memset only sets bytes, not larger structures.

I’m looking into some ways of doing this very very efficiently on the teensy 3/arm platform, and want to look into whether or not there are ways to do it quickly on AVR as well.

If you’re asking if RGB is the best way to represent color - personally, I don’t think it is - but it’s how the leds want to be addressed. I tend to prefer using HSV for color representation, it’s still 3 values, but it’s brightness, hue, and saturation - and you can cycle through colors by just cycling the value of hue. It does mean that you have to translate from HSV to RGB before writing data out - which we have a fairly high performance library that will be going into FastSPI_LED2 for handling that, as well as support code to make it so you don’t have to explicitly do this.

What about something like having an array for r, g, and b? So that one could do something like: leds[px] = {r, g, b}; ? (or even if it’s leds[px] = {h, s, v} that would work too)

You’re basically asking for the equivalent of a setPixel function :slight_smile: - unfortunately the syntax you’re describing is not really doable in C/C++ - that notation that you describe up there is only usable for initialization of new objects. e.g. int numbers[3] = { 1, 2, 3}; I can abuse overloading of operators in C++ to let you say ledspx - it’d still be a function but i’ve gotten pretty good at convincing gcc to inline what I want and when i want it :slight_smile:

That said - for the way I do work - always having to assign all three values is frequently wasteful. For example, if I’m calling a 3 value set pixel, that’s 3 sets of stores into memory at 2 clock cycles apiece (assuming, for the moment, that the function fully inlines and gcc isn’t doing anything stupid behind the scenes). But often, what I will do is use memset to rapidly zero out the entire array of leds, then only set the specific colors that I want values set for. If i’m doing something with primarily colors - r, g, o b - that’s 1 assignment/store vs. 3. Relatedly, with HSV, there are times where I’m setting those values separately under differing circumstances. E.g. a loop/function for mapping pixel to hue, then saturation, then brightness.

So, there is a slight bias towards the things i’ve done in projects in the past and need to do in the future.

Also, the explicit callout of foo.r, foo.g, foo.b means that it’s always clear looking at your code what’s red/blue/green. vs. just tossing 3 numbers in - quick: leds[fx](128, 128, 128); - is that HSV or RGB? Even if the ordering was consistent :slight_smile: Long term readability and re-readability of code has a lot of weight with me - but mainly because I spend a lot of time writing some really complex pattern code - the extra typing short term saves me a lot of time re-understanding what the hell i was doing when I go back in 3 months to adapt it to something new.

Note that right now at this point we’re mostly talking about various syntactic sugars for setting values - where explicit assignments for the values r, g, and b, or a setPixel function call, or abusing overloading operators. Under the hood - there are still 3 bytes that need to get written into memory if you are setting all 3 of r, g, and b.

This is part of why, though, I’m pulling the definitions of RGB and HSV classes into the library itself - it’s so we can put functions on the classes directly to address things like this.

(Or, even better, be able to do things like add or subtract two CRGB values and have it know to constrain the values of the resulting ranges to 0-255, and with far far fewer clock cycles than it would take if you were to try to do the add/bounding yourself - arduino’s map function is wasteful! - honestly high performance pixel level manipulations were the first set of functions that Mark and I are throwing together to put into these defs).

Yeah, I was wondering about what the overhead would be after I submitted the comment. I don’t mind the foo.r, foo.g, and foo.b syntax, other than needing to write them out on separate lines, or do something I am so much against, which is:
foo.r = x, foo.g = x, foo.b = x;
I cringe every time I see someone write that, instead of separate lines for each.

Actually, I think I thought of a way to do it - maybe, I think I can make led[px] = (r, g, b); work - may the C++ gods forgive me for what I’m about to do :slight_smile:

Nope - can’t do that - back to either led[px](r, g, b); or led[px] = CRGB(r, g, b);

Hey, first work on what you already have on your plate … :slight_smile: (like that wonderful byte casting)

Actually, taking a slight diversion from teensy 3 DMA games to double the number of LEDs most of the HSV based programs I work on can handle when using SPI based led chipsets :slight_smile: