I have a magnometer that every time my ESP looses power it’s readings change slightly. It’s a minor annoyance to have to go in and find out it’s min/max readings so I can get it to accurately measure my gas usage.
So I’ve setup some code that on boot sets it to an “uncalibrated” state and waits until it measures enough of a change in the reading to set itself into a “calibrated” state.
I put a couple of debug statements and found that even though the calibrated variable is never set to true, in the template area it treats it as if it was true. Am I missing something in how I should set up my lambda in the platform: template area? Here is my code:
substitutions:
name: "gas-meter"
esphome:
name: "${name}"
friendly_name: Gas Meter
#on_boot:
#- priority: 800.0
# then:
# - lambda: |-
# id(gas_max_mid) = (id(gas_max)-id(gas_min))*0.75+id(gas_min);
# id(gas_min_mid) = (id(gas_max)-id(gas_min))*0.25+id(gas_min);
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: ""
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: ""
password: ""
captive_portal:
globals:
- id: gas_counter_total
type: long
restore_value: no
initial_value: '0'
- id: gas_counter
type: long
restore_value: no
initial_value: '0'
- id: gas_high
type: bool
restore_value: no
initial_value: 'false'
- id: gas_max
type: float
restore_value: no
initial_value: '-1000.0'
- id: gas_min
type: float
restore_value: no
initial_value: '1000.0'
- id: gas_max_mid
type: float
restore_value: no
initial_value: '-2000.0'
- id: gas_min_mid
type: float
restore_value: no
initial_value: '2000.0'
- id: calibrated
type: bool
restore_value: no
initial_value: 'false'
interval:
- interval: 0.1s
then:
- lambda: |-
# If the current reading is greater than the current max/min, set max to current reading and if device is "calibrated" update the max and min mid values
if (id(gasx).state > id(gas_max)) {
id(gas_max) = id(gasx).state;
if (id(calibrated)) {
id(gas_max_mid) = (id(gas_max)-id(gas_min))*0.75+id(gas_min);
id(gas_min_mid) = (id(gas_max)-id(gas_min))*0.25+id(gas_min);
}
} else if (id(gasx).state < id(gas_min)) {
id(gas_min) = id(gasx).state;
if (id(calibrated)) {
id(gas_max_mid) = (id(gas_max)-id(gas_min))*0.75+id(gas_min);
id(gas_min_mid) = (id(gas_max)-id(gas_min))*0.25+id(gas_min);
}
}
# If the absolute value of the max-min is greater than 10, but less than 1000 set calibrated to true and update min/max mid values
if ((fabs(id(gas_max)-id(gas_min)) > 10) && (fabs(id(gas_max)-id(gas_min)) < 1000.0) && (!id(calibrated))) {
ESP_LOGD("custom", "Just set to true");
id(calibrated) = true;
id(gas_max_mid) = (id(gas_max)-id(gas_min))*0.75+id(gas_min);
id(gas_min_mid) = (id(gas_max)-id(gas_min))*0.25+id(gas_min);
}
# If calibrated, evaluate current state to see if gas is being used
if (id(calibrated)) {
if (id(gasx).state > id(gas_max_mid) && !id(gas_high)) {
id(gas_counter_total) += 1;
id(gas_counter) += 1;
id(gas_high) = true;
} else if (id(gasx).state < id(gas_min_mid) && id(gas_high)) {
id(gas_high) = false;
}
}
i2c:
sda: GPIO21
scl: GPIO22
#scan: true
frequency: 10kHz
sensor:
- platform: qmc5883l
address: 0x0D
field_strength_x:
name: "Gas Meter Field Strength X"
id: gasx
internal: true
field_strength_y:
name: "Gas Meter Field Strength Y"
id: gasy
internal: true
field_strength_z:
name: "Gas Meter Field Strength Z"
id: gasz
internal: true
heading:
name: "Gas Meter Heading"
internal: true
range: 200uT
oversampling: 512x
update_interval: 0.1s
#8 counts per cubic foot, multiplied by 2 to get per minute based on update interval, only evaluate if device is "calibrated"
- platform: template
name: "Gas Rate"
lambda: |-
if (id(calibrated)) {
int temp = id(gas_counter);
id(gas_counter) -= temp;
float temp2 = temp;
float temp3 = (temp2/8)*2;
return temp3;
} else {
return 0;
}
update_interval: 30s
unit_of_measurement: ft³/min
device_class: 'gas'
- platform: template
name: "Gas Total"
lambda: |-
if (id(calibrated)) {
float temp = id(gas_counter_total);
return temp/8;
} else {
return 0;
}
update_interval: 1s
unit_of_measurement: 'ft³'
state_class: 'total_increasing'
device_class: 'gas'
# Reset calibration state
button:
- platform: template
name: "${name} Calibrate"
id: Calibrate
icon: "mdi:chart-histogram"
on_press:
then:
lambda: |-
id(gas_max) = -1000.0;
id(gas_min) = 1000.0;
id(gas_max_mid) = 500.0;
id(gas_min_mid) = -500.0;
id(calibrated) = false;