DRAFT: I’m still working on this post.
I’ll cover the primary capabilities of the Web Inspired LED (wiLED) controller and include JSON examples. There are 4 primary JSON objects:
- Script
- Element
- Container (a type of Element)
- Value (number, string, boolean, and very powerful patterns & ranges)
Most of the snippets below are not fully functional. Additional attributes and/or JSON is necessary to achieve the results described.
Script
Every JSON definition is a script. Most scripts look something like this
{ "name": "Moving Rainbow", "frequency": 100, "duration": "60s", "elements": [...] }
None of the attributes are required, but it won’t do anything without elements.
name – the name is displayed on the WebAdmin app and does not matter
frequency – number of milliseconds between updates.
duration – the number of milliseconds the script will run.
elements – the JSON element definitions that update LED colors
Note that frequency and duration are milliseconds but one is a JSON number and the other is a string in this example. See Value definitions below for different ways to specify millisends.
LED Element
The most important elements are the ones that set LED colors. There are 2 (or 3) types
"elements": [ { "type": "hsl", "hue":50, "saturation":100,"lightness":50}, { "type": "rgb", "red":50, "green":100,"blue":255}, { "type": "rhsl", "hue":50, "saturation":100,"lightness":50} ]
“hsl” type elements can set the hue, saturation, and lightness. Only one of the 3 values (H, S, or L) need to be set in an hsl element. This allows the values to be animated independently.
“rhsl” is the same as hsl but uses “rainbow hue” rather than “spectrum hue” values. Hue values are in the range 0-359 (degrees in the color wheel). The spectrum color wheel has fewer “reds” than other colors – so in animations, the reds are shorter in length or faster than other colors. Rainbow hue values result in each hue using the same number of values in the range. (red, yellow, cyan, etc). The FastLED library explains it’s method here. wiLED doesn’t use FastLED and has a different conversion from rainbow to spectrum values (this needs to be improved but has better results in most cases).
“rgb” type elements allow specifying colors using red, green, and blue values, each in the range 0-255. Unlike “hsl”, “rgb” elements must define all components in the same element. If only one component is defined, the other two are set to 0. I will write a post about how scripts are drawn, but the simple reason for this is that draw operations use hue, saturation, and lightness, so the RGB color needs to be converted to HSL when the element is processed, and that requires all 3 RGB components.
There are many websites explaining HSL and HSV (some wrong). HSV has some advantages, but I chose HSL since it is supported in CSS and will be easier to create a web-based design app. For wiLED, the values are
hue – a value in the range 0-359. Selects that value from the color wheel.
saturation – a value the range 0-100. This is a mixture of “white” and the specified hue. 0 is white (no hue component) and 100 is the hue (no white added).
lightness – a value in the range 0-100. 0 results in black, and 100 is white. 50 is “normal”
You can experiment with different HSL values.
Position
Scripts would be long and difficult to write if each LED needed a color element. Much of the power comes from position attributes which can be added to any element (both LED and container elements). The most common are offset and length
{ "type": "rgb", "red": 255, "offset": 0, "length":10} , { "type": "hsl", "hue": 230, "length":10}, { "type": "hsl", "lightness": 10, "offset": 5, "length": 8}
The elements above draw 10 red pixels, followed by 20 blue pixels. Lightness is decreased to 10 for the last 5 red LEDs and first 3 blue ones (8 total) since the 3rd element spans parts of both of the first 2 elements. LED elements have a number of attributes in addition to offset and length:
- unit – Every numeric LED value (e.g. offset or length) can have a unit. The default for unit is “inherit”, or “%” if no ancestor elements define a unit.
- offset – position of the starting LED of this element. Can be a JSON number (e.g. 5), or a JSON string with a value and unit (e.g. “5px”).
- length – length of this element. This has units like offset. If length is not set, it is set to the end of the parent container.
- reverse – if true, pixels are drawn from the end toward offset. Only useful when a LED value (e.g. hue) is not a constant.
- op – This is the blend operation that is used if elements overlap.
- absolute – if true, offset is relative to the beginning of the parent element. If false, offset is from the end of the previous element.
- cover – if true, offset and length are set to the beginning and length of the parent.
- center – if true, the element is centered on the parent. Both parent and this element must specify a length
Container elements can have all of these attributes and additionally
- clip – LED positions outside of the container’s position are discarded.
- wrap – LED positions outside of the container’s position wrap – connecting the start and end
- gap – Child elements flow so that each one begins at the LED after the previous element ends. If the container has a gap, that number of positions is added between the elements.
If neighter clip nor wrap are true, LEDs may be drawn beyond the ends of the element. In that case, the parent clip or wrap will be used. The physical strip wraps if LEDs are drawn outside it’s length.
Every offset and lengthvalue can have a unit. If the unit attribute is set in a container, it is used for any values missing a unit in it’s children. The supported values are
- “px” (or “pixel”) – a count of LED pixels being drawn
- “%” (or “percent”) – the number of pixels as a percent of the parent (e.g. the entire strip, or a container that covers part of the strip)
- “in” (or “inch”) – the number of pixels that cover an inch of the strip
- “cm” (or “centimeter) – the number of pixels in a centimeter
- “m” (or “meter”) – the number of pixels in a meter
- “inherit” – use the unit of the parent. This is the default.
Using “%”, “in”, or “cm” units allows the same script to be used on multiple controllers that have strips of different lengths and acheive similar looks. Distance units (“in”,”cm”,”m”) use the pixels/inch in the config.json definition and work with strips of different densities.
op is the blend operation to use when elements overlap. “replace” is the default and the last element of the script that draw on an LED replaces previous values. RGB values are converted to HSL before blending. These values are implemented
- “replace” – the previous value is replaced with the new one. In the case of an HSL element that only the specified component(s) are replaced.
- “add” – the new value is added to the previous value.
- “subtract” (or “sub”) – the new value is subtracted from the previous.
- “average” (or “avg”) – the new value is averaged from the previous. If more than 2 values are blended, the average is done with each new element. For example, if 3 elements overlap, the first 2 are averaged, and then that average is averaged with the 3d.
- “min” – the minimum of the previous and new value is used
- “max” – the maximum of the previous and new value is used
Containers
todo
Value
todo
Shorthands
todo:
{ “hue”:50}
{“green”: [100,200]}
Multiple Physical Strips
todo
- stripNumber – when multiple physical strips are controlled as a single strip, and element can choose
Future
- I plan to add “next” attribute to scripts. When duration expires, it will load the next script.
- Implement a better “rainbow hue” method. Currently uses a bezier curve.
- Improve blend operations. Add alpha values to LED elements or some other way to combine values by percent/weight.
todo
todo