Derivative?

To extract a derivative of a sensor (or even simply delta), is it best to create a global variable to store previous value and compare with current value? Is there a better method?

For a delta sensor, if you need to do it in ESPHome you can put this on a copy sensor:

filters:
  - lambda: |-
      static float last_value = 0;
      float change = 0;
      change = x - last_value;
      last_value = x;
      return change;

And on ESPHome Discord if you search for “Delta Sensor (Change from previous value). Survive Deep Sleep” there’s also a way using globals that will survive a deep sleep.

1 Like

I didn’t realize that’s how the static keyword works in lambdas. Nice. That solves the issue.

Just out of curiosity; how can I use a copy sensor to get delta? Do I understand correctly that it simply mirrors the state of another?

EDIT: right, I think I get it: instead of creating a separate sensor that fetches the value of the other sensor, it’s easier to create a copy sensor for the delta purpose.

1 Like

Copy sensors are a newer thing. Before that you’d probably use a template sensor to duplicate an existing one.

Most of the solution came from somewhere else on the internet with a few additional improvements then suggested by jesserockz on Discord.

My solution for a time derivative, so far stable for me.

  - platform: copy
    source_id: wasser_boiler
    id: "wasser_boiler_derivative"
    unit_of_measurement: "°C/h"
    name: "Warmwasseränderung Boiler"
 
    filters:
      - lambda: |-
          static float last_value = 0;
          static float last_time = 0;
          float time   = (float) millis();
          if (last_time == 0){
            last_value = x;
            last_time  = time;
            return {};
          }                    
          float change = ( ( x - last_value ) / ( time - last_time ) ) *1000*60*60;
          last_value = x;
          last_time  = time;
          return change;
      - sliding_window_moving_average:
          window_size: 3
          send_every: 2          
      - or: 
        - delta: 0.01  
        - heartbeat: 120minutes            
      - throttle: 1minutes         

Note: the delta is on the derivative, so compared to the source a acceleration filter.

2 Likes

Hi guys, another solution. I wanted to see the mid term temperaturechange of my thermo solar panels on the roof, if temperture was rising or lowering. not within seconds but within the range of 10 minutes.

my solution.
create a sliding average of 10 min range, then subrtract this average from actual value. it looks like this:

  - platform: template
    name: longterm_roof
    id: longterm_roof
    unit_of_measurement: "°C"
    accuracy_decimals: 2
    icon: 'mdi:thermometer'
    lambda: |-
      return id(thsol_roof_adc1_0).state ;
    #
    # original roof-Wert alle 10sec x 2 = 20 sec
    # für 10 min: --> 30x
    # --------------------------------------------
    filters: 
      - sliding_window_moving_average:
          window_size: 30
          send_every: 1      # 20 sec
    #
    #
    #
  - platform: template
    name: derivative_roof
    id: derivative_roof
    unit_of_measurement: "°C"
    accuracy_decimals: 2
    icon: 'mdi:thermometer'
    lambda: |-
      return ( id(thsol_roof_adc1_0).state - id(longterm_roof).state ) ;
      //
    #
    #

works pretty well
good luck