Hey HA Community, i have a massive Drift in my Bed scale over night and have no Idea whats causing this, can you help?
Load cells are sensitive to temperature (they get bigger and smaller even microscopically), and also are sensitive to the material properties of their mounted surfaces, so you must compensate with a temperature sensor.
Source: tried to build a propane scale, mostly failed because of this.
I’m not sure if this will be any use to you but as I’m not interested any weight readings but only how many people are in bed, I use this code.
sensor:
- platform: hx711
name: "HX711 Value"
dout_pin: D0
clk_pin: D1
gain: 128
update_interval: 1s
filters:
- calibrate_linear:
- -994515 -> 0
- -1004000 -> 1
- sliding_window_moving_average:
window_size: 11
send_every: 5
- lambda: |-
if (x <= 15.9) {
return 0.0;
} else {
return x;
}
- lambda: |-
if ((x >= 16.0) && (x <= 46)) {
return 1.0;
} else {
return x;
}
- lambda: |-
if ((x >= 46.1) && (x <= 500)) {
return 2.0;
} else {
return x;
}
unit_of_measurement: kg
accuracy_decimals: 0
The output…
They are mounted on 3D printed holders.
The Temperature dropped at the beginning of the night but stabilized.
I have implemented such a function, but the problem is that the drift is so large that the sensor detects two people when only one is in bed, and in the morning, when no one is in bed anymore, it does not return to zero without being recalibrated.
globals:
- id: initial_zero
type: float
restore_value: yes
# NOTE: make sure to align this value to the one used in "calibrate_linear" below!
initial_value: '1272107'
- id: auto_tare_enabled
type: bool
restore_value: yes
initial_value: 'true'
- id: auto_tare_difference
type: float
restore_value: yes
initial_value: '0'
- id: manual_tare_flag
type: bool
restore_value: no
initial_value: 'false'
binary_sensor:
- platform: template
name: "Bed Occupied"
device_class: occupancy
lambda: |-
if (id(bed_hx711_value).state > 40) {
return true;
} else {
return false;
}
- platform: template
name: "Bed Full"
device_class: occupancy
lambda: |-
if (id(bed_hx711_value).state > 140) {
return true;
} else {
return false;
}
switch:
## Switch to enable/disable the auto tare feature
- platform: template
id: bed_continuous_tare_enabled
name: "Bed Continuous Tare Enabled"
lambda: |-
return id(auto_tare_enabled);
turn_on_action:
- lambda: |-
id(auto_tare_enabled) = true;
turn_off_action:
- lambda: |-
id(auto_tare_enabled) = false;
## Switch used to initiate a manual tare
- platform: template
id: bed_manual_tare_action_switch
name: "Bed Manual Tare Action"
lambda: |-
return id(manual_tare_flag);
turn_on_action:
- lambda: |-
id(auto_tare_difference) = id(initial_zero) - id(bed_hx711_value_raw).state;
- switch.turn_off: bed_manual_tare_action_switch
turn_off_action:
- lambda: |-
id(manual_tare_flag) = false;
sensor:
- platform: wifi_signal
name: "Under Bed WiFi Signal Sensor"
update_interval: 60s
# template sensors from global variables
- platform: template
id: bed_initial_zero
name: "Bed Initial Zero"
lambda: |-
return id(initial_zero);
update_interval: 1s
- platform: template
id: bed_auto_tare_difference
name: "Bed Auto Tare Difference"
lambda: |-
return id(auto_tare_difference);
update_interval: 1s
# sensors imported from home assistant
- platform: homeassistant
id: homeassistant_initial_zero
entity_id: input_number.bed_initial_zero
on_value:
then:
- lambda: |-
id(initial_zero) = x;
- platform: hx711
id: bed_hx711_value_raw
name: "Bed Weight Value"
internal: True
dout_pin: GPIO2
clk_pin: GPIO14
update_interval: 1s
unit_of_measurement: kg
filters:
- sliding_window_moving_average:
window_size: 5
send_every: 1
on_value:
then:
- sensor.template.publish:
id: bed_hx711_value
state: !lambda 'return id(bed_hx711_value_raw).state;'
- if:
condition:
and:
- lambda: 'return id(auto_tare_enabled);'
# current bed value is below approx. 10KG (raw value -275743) aka nobody is standing on the scale
- lambda: 'return id(bed_hx711_value).state < 10.0;'
then:
- if:
condition:
# current raw scale value is below expected zero value
- lambda: 'return id(bed_hx711_value_raw).state < (id(initial_zero) - id(auto_tare_difference));'
then:
# INcrease Auto-Tare offset to slowly align real zero value with expected zero value
- lambda: |-
id(auto_tare_difference) += 10;
else:
# DEcrease Auto-Tare offset to slowly align real zero value with expected zero value
- lambda: |-
id(auto_tare_difference) -= 10;
# Mapped value to KG
- platform: template
id: bed_hx711_value
name: "bed HX711 Value"
internal: False
filters:
# apply auto_tare difference
- lambda: 'return x + id(auto_tare_difference);'
# apply rough calibration
- calibrate_linear:
# retrieve these values by evaluating the raw values with loads of known mass.
# note that a bigger difference between measurements usually results in higher resolution,
# so measure 0 Kg and the highest known mass you have (like f.ex. your own weight, measured by a normal scale with good accuracy)
- 1272107-> 0
- 1514973-> 102
# 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;
}
unit_of_measurement: kg
accuracy_decimals: 2
update_interval: 0.2s
Is it possible that I have overloaded the load cells? I weigh 102 kg, and I don’t know how much my bed weighs. How much can load cells be overloaded before they are permanently damaged?
Cells drift and have hysteresis. Mount them to metal instead of 3-D printed anything to reduce the drift caused by material properties of the mount. Compensate for other type of drift by using a thermometer compensation and a correlation. Some day I will release my experimental Jupyter workbook to do these calculations.
Then I will have to solve the whole thing differently in the long run, because I have no way of making the holders out of metal. I’m just wondering that it seems to work for so many.
Did you ever find a solution? I am trying to build something similar (water dispenser tracking) and have exactly the same drifting issues.
Hi
I had same problem, read this tread to see my strugle and solution