Lua - Calculate watts being used by a light bulb, based on its brightness level?

Viewed 208

I was sent the following code as an example of what I could do to calculate the watts being used by a hue light bulb, based on its model number and brightness level..

if hue_model == "LWB010" and hue_state == true then
   if hue_level <= 0 then watt = 0.4 end
   if (hue_level > 0 and hue_level <= 6) then watt = 1.6 end
   if (hue_level > 6 and hue_level <= 13) then watt = 1.7 end
   if (hue_level > 13 and hue_level <= 20) then watt = 1.8 end
   if (hue_level > 20 and hue_level <= 26) then watt = 1.9 end
   if (hue_level > 26 and hue_level <= 33) then watt = 2.2 end
   if (hue_level > 33 and hue_level <= 40) then watt = 2.4 end
   if (hue_level > 40 and hue_level <= 46) then watt = 2.7 end
   if (hue_level > 46 and hue_level <= 53) then watt = 3.0 end
   if (hue_level > 53 and hue_level <= 60) then watt = 3.5 end
   if (hue_level > 60 and hue_level <= 66) then watt = 3.9 end
   if (hue_level > 66 and hue_level <= 73) then watt = 4.5 end
   if (hue_level > 73 and hue_level <= 80) then watt = 5.1 end
   if (hue_level > 73 and hue_level <= 86) then watt = 5.5 end
   if (hue_level > 86 and hue_level <= 93) then watt = 6.4 end
   if (hue_level > 93) then watt = 6.7 end
   print(watt)
    else
    print("light is off")
    end

As the brightness range returned by the Hue API seems to have changed from 0-100 to 0-255, the above needs to be updated. And as part of that work, I’d like to make it more efficient (less code) and also more precise.

Logic suggests that when the light’s on full (255) it will be using 6.7w, and if it’s at 50% (127), that’ll drop to approx (3.35w)

Sadly after trying various thing, I keep failing badly, and find myself reverting back to something very long like the original look up type table above. Surely there’s a better/cleaner way ?

If so, please could someone share what they would do.

Many thanks..

2 Answers

First of all you should check your data.

According to the datasheet a Phillips Hue White LWB010 has a maximum power of 9W.

Cutting your data at 93%, 6.7W doesn't look clever to me in most scenarios.

I checked another source which given the overall presentation I would trust more than your numbers.

https://www.reddit.com/r/Hue/comments/8kvcsi/power_consumption_hue_white_a60_lwb010/

enter image description here

According to those measurements, you're about 2W off at 93% and as you clamp your values here your 100% wattage is off by almost 4W!

Now to the coding part:

Looking at the plot I'd say an exponential function will give a good approximation.

enter image description here

local wattsFromDim = {
  LWB010 = function (dim) return 0.43981651 * math.exp(0.012712893 * dim) end
}
-- how to use:
local watts = wattsFromDim.LWB010(128)

This makes sense as the brightness perception of the human eye is logarithmic.

So in order to provide linear dimming (you'd expect 50% to be half as bright as 100%) the output power must follow logarithms inverse, an exponential function.

Normally, you should use Lua math operations to perform this task. However, to make it easier, i've just copied the existing table into a new format.

local wattTable = {
        [ 1 ] = 1.6 ,
        [ 2 ] = 1.7 ,
        [ 3 ] = 1.8 ,
        [ 4 ] = 1.9 ,
        [ 5 ] = 2.2 ,
        [ 6 ] = 2.4 ,
        [ 7 ] = 2.7 ,
        [ 8 ] = 3.0 ,
        [ 9 ] = 3.5 ,
        [ 10 ] = 3.9 ,
        [ 11 ] = 4.5 ,
        [ 12 ] = 5.1 ,
        [ 13 ] = 5.5 ,
        [ 14 ] = 6.4 ,
}

Previously, you used jumps of about 6.5, which translates to about 16.5 on the new scale. We can use math.floor(hue/16.5) to get the index for this table.

However, values less than 0 and more than 240 will be out of bounds of the table (the bounds being 1 to 14). So, we can perform some checks:

local index = math.floor(hue / 16.5)
if index <= 0 then
    return 0.4
elseif index >= 15 then
    return 6.7

After that, we can just read from the table:

else
    return wattTable[index]
end

Here is the completed code:

local wattTable = {
        [ 1 ] = 1.6 ,
        [ 2 ] = 1.7 ,
        [ 3 ] = 1.8 ,
        [ 4 ] = 1.9 ,
        [ 5 ] = 2.2 ,
        [ 6 ] = 2.4 ,
        [ 7 ] = 2.7 ,
        [ 8 ] = 3.0 ,
        [ 9 ] = 3.5 ,
        [ 10 ] = 3.9 ,
        [ 11 ] = 4.5 ,
        [ 12 ] = 5.1 ,
        [ 13 ] = 5.5 ,
        [ 14 ] = 6.4 ,
}

function getWattage(hue)
    local index = math.floor(hue / 16.5)
    if index <= 0 then
        return 0.4
    elseif index >= 15 then
        return 6.7
    else
        return wattTable[index]
    end
end

Here is an example of using it:

print(getWattage(150))

Summary: Using a table and some if conditions, we have created a function which accepts all numbers as valid values (bulletproof), and allows us to adjust the range of hue values from 0-100 (6.5) to 0-255 (16.5).

Related