Rolling Average LUX Sensor


#1

1) Give a description of the problem
I’ve created this piston that essentially sets a virtual devices dimmer to different level’s based on different lux ranges. Using run automations based on the virtual devices dimmer level.

The problem is I have it running once every 10 minutes to avoid the drastic up and downs all the time, but sometimes I just get an unlucky 10 seconds where a cloud covers the sun.

2) What is the expected behaviour?
Ideally If I can create a rolling average this would stabalize things. Ideally it would be the rolling average for the last 20 minutes or so, but it could be the rolling average for the last 10 readings as well.

This gave me some ideas, but I wasn’t able to pull it off.

Does anyone have any ideas?


#2

There might be a better way but he is what I’ve done in the past

Set up three varaibles
One that captures a string of lux values
Second that is the average of those variables
Third is a counter variable

Then compare your ranges to the avgLux variable

Below is a 10 reading example:


#3

I tried this to see what I can come up with… You can use the piston as is and save the average lux to a global variable or modify your piston to integrate the snippets in this one.


#4

In this case, I like the simplicity of arrays:

Every 10 minutes
    Set integer variable lux(2) to lux(1)
    Set integer variable lux(1) to lux(0)
    Set integer variable lux(0) to Device's illuminance
    Set integer variable avg to {avg(lux[0], lux[1], lux[2])}
    Set Virtual Device Dimmer's level to avg
END EVERY
  • The first 2 commands just shifts the data over…
  • The 3rd sets the latest dataPoint…
  • The 4th sets the average.

Basically, this creates a 20 minute rolling average.
(using 3 numbers: Now, 10m ago, and 20m ago)


Worth mentioning:

I usually want an average written in decimal, but if that number is getting pushed to a Dimmer’s level, then we want to use an integer for an average.

Also, if “Device’s illuminance” ever goes above 100, you may need to use math (or extra code) to keep the avg variable at 100 or less. (because most Virtual Dimmers can’t go above)


Pro Tip:

I often will monitor the illuminance levels for a week or so, to find the real life maximum for that device. Afterwards, I can scale the max lux to level 100, to basically give me a “percentage of brightness”, which converts to “Dimmer’s level” quite nicely.

Yes, there is a calibration period, but the final results are always more optimized (and helpful) to the SmartHome.

For example, if 5,000 is the maximum illuminance for your location / device, then we can take luminance divided by 50 equals Dimmer level. (which should always fall between 0 and 100)


#5

Thank you very much, I didn’t try your method, as the code didn’t work for me and I wasn’t sure how to get set the variables.

It seems like a very simple method though which could work.

P.S. Sorry, I didn’t realize people were trying to help


#6

Thank you very much. This worked!!
I made a couple of tweeks. I realized that it should be time based rolling average not event based.
My solar sensor records like crazy when there is changes.

I ended up adding event triggers as well to my previous script so that whenever I turn my virtual switch on again, it will get the current state. (personally the way i wrote the code is very sloppy but at least it works)


#7

Thanks, I really like this recommendation.
I tried to get it setup but I’m not well versed in webcore, so it was difficult to find the statements needed.

If I started from scratch I would use this method.

Personally I think this would be an extremely useful script that people could download that are new.