Calibrate Linear Filter using a Global Variable?

Hello,
I’m creating a load cell based scale and would like to calibrate the scale to a known weight via the internal web server or from HA without having to upload new code each time.

From what I understand this would require using either a global variable or reading the value from HA and neither is allowed for a calibrate linear filter.
Screen Shot 2022-02-15 at 10.41.32 AM
As you can see in the code below, this global variable is float.

Has anyone been able to use a variable or a sensor as a calibration data point?

Is there a way to call the calibrate_linear function from a lambda that can use global variables?

Thanks!

substitutions:
  name: test-scale
  friendly_name: Test Scale
  entity_name: test_scale
  ip_address: 192.168.6.176

# Map Raw sensor values to Kg
  # Begin initial setup by retrieving the values below by evaluating the raw values with loads of known mass.
  # Measure four weights from 0 Kg to the highest known mass without exceeding the load cell.
  # Note: A bigger difference between mass results in higher scale resolution.
  #
  # Mass in Kg used for calibration
  mass_0_kg: '0'
  mass_1_kg: '5' # heaviest weight without exceeding the load cell
  
  # Raw sensor value for above mass
  mass_0_raw: '172500'
  mass_1_raw: '1247000'


esphome:
  name: $name
  platform: ESP32
  board: wemos_d1_mini32

ethernet:
  type: LAN8720
  mdc_pin: GPIO23
  mdio_pin: GPIO18
  clk_mode: GPIO17_OUT
  phy_addr: 0
  power_pin: GPIO5
  use_address: $ip_address

mdns:
  disabled: true

api:
  password: !secret api_password
  reboot_timeout: 0s

ota:
  password: !secret ota_password

logger:
  baud_rate: 0  # Disable UART logging
  logs:
    hx711: ERROR
  
web_server:
  port: 80

globals:

  - id: tare_value
    type: float
    restore_value: yes
    initial_value: '0'
    
  - id: manual_tare_flag
    type: bool
    restore_value: no
    initial_value: 'false'


switch:

# Switch used to initiate a manual tare
  - platform: template
    id: tare_action_switch
    name: "$friendly_name Manual Tare Action"
    lambda: |-
      return id(manual_tare_flag);
    turn_on_action:
      - lambda: |-
          id(tare_value) = $mass_0_raw - id(cell_raw).state ;
      - switch.turn_off: tare_action_switch
    turn_off_action:
      - lambda: |-
          id(manual_tare_flag) = false;
          
# Switch Virtual Restart
  - platform: restart
    name: "$friendly_name Restart"
    id: restart_switch         


sensor:

# mass map template sensors
  - platform: template
    id: current_mass_0_raw
    name: "$friendly_name Map $mass_0_kg Kg"
    lambda: |-
      return $mass_0_raw;
    update_interval: 1days

  - platform: template
    id: current_mass_1_raw
    name: "$friendly_name Map $mass_1_kg Kg"
    lambda: |-
      return $mass_1_raw;
    update_interval: 1days

# Tare template sensor
  - platform: template
    id: current_tare
    name: "$friendly_name Current Tare"
    lambda: |-
      return id(tare_value);
    update_interval: 1s
    filters:
      - or:
        - throttle: 1min
        - delta: 1
        
# Cell Raw to 0 Kg deviation template sensor
  - platform: template
    id: zero_kg_deviation
    name: "$friendly_name 0 Kg / Raw"
    lambda: |-
      return $mass_0_raw - id(cell_raw).state;
    update_interval: 1s


# Raw ADC Reading
  - platform: hx711
    name: "$friendly_name Raw"
    id: cell_raw
    internal: False
    dout_pin: GPIO14
    clk_pin: GPIO33
    gain: 128
    # unit_of_measurement: kg
    accuracy_decimals: 0
    update_interval: 0.2s
    filters:
    # filter out the top five values and send the nineteenth highest value in the dataset
      - quantile:
          window_size: 25
          send_every: 25
          send_first_at: 25
          quantile: .8
    on_value:
      then:
        - lambda: 'id(cell_kg).publish_state(x);'

    
# Raw ADC Temperature Compensated to Kg
  - platform: template 
    id: cell_kg
    name: "$friendly_name Measured Mass"
    internal: False
    filters:
      # apply tare
      - lambda: 'return x + id(tare_value);'
      # apply rough calibration
      - calibrate_linear:
          - $mass_0_raw -> $mass_0_kg
          - $mass_1_raw -> $mass_1_kg
      # map values below 0.1 to 0 (to decrease value changes due to random fluctuation)
      - lambda: |-
          if (x <= 0.1) {
            return 0.0;
          } else {
            return x;
          }
      - sliding_window_moving_average:
          window_size: 3
          send_every: 1
      - throttle: 5s
    unit_of_measurement: kg
    accuracy_decimals: 3
    update_interval: 0.2s
1 Like

I’ve been doing stuff with load cells recently, and calibrating is a pain.

If you’re calibrating with zero weight and a single known weight only (so 2 readings) then you can probably perform the maths yourself to convert your raw reading into kg, and not use the calibrate_linear function. This would allow you to use variables in a template / lambda

You can also store the variables in globals, and use the restore_from_flash option so the variable survives restarts.

Hope that helps.

Im trying to do the exact same thing… smooth out the hx711 spikes and create a “recalibrate” function that will adjust the reference points for the “calibrate_linear” function.
Did you ever find a way to do it?

1 Like

This has a manual/auto tare function.

Unfortunately not.

Did you find any solution to this?

Haven’t, but also haven’t looked into it. Hard coded it and moved on.

Try this piece of code:

substitutions:
  initial_zero_value: "-59553"

globals:
  - id: initial_zero
    type: float
    restore_value: yes
    initial_value: '${initial_zero_value}'

- calibrate_linear:
    - ${initial_zero_value}.0 -> 0
1 Like

Will the substitutions initial_zero_value variable change and be permanent with the change of the global variable initial_zero?