Level adjustment curves for dimmers

I have multiple combinations of dimmers and LED light bulbs. With LED’s, especially, “25%” on the dimmer is already almost 100% in perceived brightness. Because of this, when using my voice assistant, I have to hunt around in a narrow range for the brightness I want:
“Alexa, set kitchen overheads to 16 percent…”
“Alexa, set kitchen overheads to 12 percent…”
“Alexa, set kitchen overheads to 14 percent…”

What would solve this is if we could have some translation curves, defined by just a handful of points, like:

transfer_curves:
  - name: wemo_led
    points:
      - for: 0
        send: 0
      - for: 50
        send: 14
      - for: 90
        send: 20
      - for: 100
        send: 100

So, if I ask for 50% brightness, HA would really send 14% to the device. If I ask for 90% brightness, HA would send 20%. Other levels would be interpolated (so, asking for 95%, half way between 90 and 100, would result in HA sending 60%, half way between 20 and 100). Also, the for 0/send 0 and for 100/send 100 could be the defaults, so those wouldn’t even be needed to be provided. For many devices, you could probably satisfactorily approximate a logarithmic taper with just one point (probably what to send for the 50% brightness).

This way, we could assign different curves to different lights and just ask for a certain level which would be consistent across all of our lights (or any variable-level device, like a motor or powered speaker).

Typically these adjustments are made on the hardware itself via it’s config. Zigbee and Zwave devices typically offer this. Outside that, you can make template lights that do exactly what you’re asking here.

Wemo also has a setting for this, and you can do it on the hardware itself.

Adjust Wemo Brightness

  1. The Wemo example uses six steps to adjust min/max brightness (pressing/holding buttons, waiting for LEDs to flash certain colors, adjusting brightnesses, etc). Furthermore, this is to set the minimum and maximum brightness levels of a dimmer. I’m not suggesting limiting the range of brightnesses (I still want it to go from super dim to 100%). I’m suggesting changing the way it progresses through those brightnesses. Sending a 1 to the dimmer gives me very dim (good). Sending a 255 to the dimmer gives me very bright (good). Sending a 127 (about 50%, numerically) gives me about 97% of perceived brightness (bad).
  2. I’ve got a pretty feature-laden dimmer (Homeseer WD100/200/300 series), and it just allows setting minimum dim levels. Even if all dimmers offered that feature, they would all have different parameter values for different dim levels… and Zwave and Zigbee devices have different ways of getting to their parameters (with Zigbee’s “cluster” system being particularly unintuitive)… not to mention the various Wifi-based interfaces.
    A unified translation function (from what the user wants to what HA needs to request) would make this: 1) more intuitive for the user, 2) uniform across devices of all systems (Zigbeen, Zwave, Hue,…), and 3) even make it available to dimmers which don’t have this built-in.

The brightness adjustment you’re proposing must be bi-directional.

If you set the light wntity to 50 and it transmits 40 to the physical device, the device will reply with an acknowledgement that it was set to 40. The received value of 40 must be translated to 50 to correspond with what was requested.

Until a volunteer developer finds the time and interest to implement this feature (and the development team accepts it), you can use the Template Light integration to create a ‘virtual light’ (for each one of your existing lights) that controls brightness according to whatever algorithm you choose (employing a template).

  • Use the set_level option to convert brightness values transmitted to the light entity representing the device.

  • Use the level_template option to convert brightness values received from the light entity representing the device.

Not a problem. You can use the interpolation in reverse, as well. But I realized it could be made even easier. You can pretty much use exponents to get a curve that rises early or late, and it’s easy to convert it back (i.e. taking the square root in one direction and squaring in the other direction).

Because we really don’t need exact values, it could just offer varying degrees of aggressiveness (in the same way that electric vehicles can offer lighter or heavier regenerative braking), and the user could then just experiment with, say, “skew darker - medium” (would send lower actual values than requested by user) or “skew darker - heavy” (would send yet lower actual values than requested by user), “skew lighter - medium” (would send higher actual values than requested). Meanwhile, asking for 0 would always send 0 and asking for 100% would always send 100%.

Here’s an example of how just taking different powers of the requested value (once you normalize it to between 0.0 and 1.0) skews how those values progress from 0.0 to 1.0:

Screenshot 2023-08-11 at 12.29.41

That’s good news because it means you’ll have no difficulty using it in a Template Light. Whatever challenges you may encounter and overcome, those tips can be passed on to whoever ultimately implements this FR.

Did you ever implement this as I also want to be able to set up level curves for dimmers so that I can use a dimmer to morph between scenes for a number secondary lights by interpolating from a set of known values which I provide? In my case I want to go even further, such that the input brightness will be used to control hue and saturation also, so that there are a number of output curves which vary as the input brightness changes.