Is there a way, to reset sensor filter cache?

Hello, is there a way to reset the last saved sensor values ​​used for a filter? The reason I would like to use something like this would be to smooth out smaller sensor fluctuations using a “sliding moving average” filter, but I would like to see larger value changes displayed immediately.

example:
- sliding_window_moving_average:
window_size: 5
send_every: 1
(decimals: 1)

current:

raw value - sliding average:
* 2 - 2
* 4 - 3
* 6 - 4
* 3 - 3,8
* 7 - 4,4
* 2 - 4,4
* 4 - 4,4
* 2 - 3,6
* 5 - 4,0
* 1000 - 202,6
* 1050 - 412,2
* 998 - 611
* 1020 - 814,6
* 990 - 1011,6
* 970 - 1005,6

I would like this behavior: if the raw value changes by a certain amount, I reset the filter’s buffer to get an accurate value straight away and not after the 5th update

so for example:

raw value - sliding average:
* 2 - 2
* 4 - 3
* 6 - 4
* 3 - 3,8
* 7 - 4,4
* 2 - 4,4
* 4 - 4,4
* 2 - 3,6
* 5 - 4,0
* 1000 - 1000
* 1050 - 1025
* 998 - 1016
* 1020 - 1017
* 990 - 1011,6
* 970 - 1005,6

Is there a way to handle this, or maybe a workaround? Maybe someone has an idea for my problem

Hmm interesting.

You kind of want to convert to a square wave.

A few ideas…

You can identify the boundaries of the stepped change by using a delta filter.

Then maybe you can figure out how to send the raw data to say another template sensor or a global as it comes in and aggregate it. And when a delta value is passed, clear it.

So you have some on_value and on_raw_value triggers/actions on your sensor with a delta filter on it. Maybe use a copy sensor for this while you’re developing.

This will likely involve a fair amount of lambda’s.

Just some high level ideas, maybe there are better ways.

This delta sensor may also give you some starting point for expansion (for tracking values, and then include some publish actions)

1 Like

This sounds like a perfect use for the Copy platform. It allows you to “copy” a sensor for situations where you might want to do different equations, filters, or similar things.

thx for your input

I got another Inspiration here:

but at the moment I am trying an lambda-filter, what chatGPT wrote for me :laughing:

      - lambda: |-
          static float values[15];
          static uint8_t index = 0;
          float filtered_value = 0;
          float raw_diff = x - values[index];
          if (fabs(raw_diff) >= 1000) {
            // If the absolute difference is greater than or equal to 1000, reset the index
            index = 0; // Reset the index
          }
          values[index] = x;
          index = (index + 1) % 15;
          for (int i = 0; i < 15; i++) {
            filtered_value += values[i];
          }
          return filtered_value / 15;

finally i got it:

    filters:
      - lambda: |-
          static float previous_values[15]; // Array to store previous values
          static uint8_t index = 0; // Index to track the number of values used for average calculation
          float current_value = x; // Current value
          float average_value; // Variable to store the calculated average value
          
          // Shift previous values
          for (int i = 14; i > 0; i--) {
            previous_values[i] = previous_values[i - 1];
            ESP_LOGD("power_meter", "Previous value at index %d: %.2f", i, previous_values[i]);
          }
          previous_values[0] = current_value; // Store current value as the most recent one
          
          // Check if the absolute difference between the current value and the previous value is greater than or equal to 1000
          if ((fabs(current_value - previous_values[1]) >= 1000) {
            // If any of the conditions are met, reset the index
            index = 1; // Reset the index to consider only the current value for average calculation
          } 
          
          // Calculate average value
          float sum = 0;
          for (int i = 0; i < index; i++) {
            sum += previous_values[i];
          }
          average_value = sum / index;
          


          // Log relevant variables
          ESP_LOGD("power_meter", "Current value: %.2f, Previous value: %.2f, Average value: %.2f, Index: %d", current_value, previous_values[1], average_value, index);

          // Increment the index only if it's less than 15
          if (index <15) {
          index++;
          }


          return average_value;

this resets the sliding moving average of 15 values when the input value changes at least 1000 or exceeds 5800 - see comments
ESP_LOGD just for debugging…

1 Like