Closed jcsouthworth closed 3 weeks ago
I'm also experiencing this issue, and I can confirm that it started at 2024.4.0, and continues in 2024.4.1. I went back to 2024.3.2 for now.
There was a recent commit that added a temperature sensor to the QMC5883L module that is the likely culprit: https://github.com/esphome/esphome/pull/6456/
I am also experiencing this issue. I worked around by also querying the y and z axis.
Calling @tronikos! Hoping they can provide some insight.
I'm sorry for causing this. It's strange that other registers don't work unless you request Z. I'm reverting my changes in https://github.com/esphome/esphome/pull/6650
I'm curious what are you using the QMC5883L for? I'm using it to read my water meter see https://github.com/tronikos/esphome-magnetometer-water-gas-meter I have a spare QMC5883L so I'm interested to hear any other cool projects.
I like the idea of the commit! I looked through and couldn't identify a reason for the failure mode so I agree roll back is probably best for now.
I use it for the same purpose you describe - reading water meter (7ms refresh - fastest it will go. Functions below this, but the output is still at 7ms intervals) and gas meter (38ms refresh). It has been incredibly reliable and accurate.
I also have an application monitoring when a motor is operating - use a filter to output std.dev of the one of the axes. Alerts me and allows me to immediately de-energize in case of no rotation.
I'm curious what are you using the QMC5883L for? I'm using it to read my water meter see https://github.com/tronikos/esphome-magnetometer-water-gas-meter I have a spare QMC5883L so I'm interested to hear any other cool projects.
I am also using it to monitor my water and gas meters, and sending the results to Home Assistant. It's been working great, and is incredibly accurate. It would be nice to have the temperature available, too, if you feel like taking another stab at this!
I'm curious what are you using the QMC5883L for? I'm using it to read my water meter see https://github.com/tronikos/esphome-magnetometer-water-gas-meter I have a spare QMC5883L so I'm interested to hear any other cool projects.
I am also using it to monitor my gas meter.
@jcsouthworth How did you achieve 7ms refresh? Using my code I get ~5ms on ESP32 but only after setting the loop interval to 0 see https://github.com/tronikos/esphome-magnetometer-water-gas-meter/blob/1d78792730be45240fb8de0e90087faad970ef34/esphome-magnetometer.yaml#L32
https://github.com/esphome/esphome/pull/6647 will make that unnecessary
It would be nice to have the temperature available, too, if you feel like taking another stab at this
I didn't revert the temperature changes.
Since you are all using it to monitor water and gas meters it would be good to start using https://github.com/tronikos/esphome-magnetometer-water-gas-meter and report any feedback there or even send PRs with improvements.
How did you achieve 7ms refresh? Using my code I get ~5ms on ESP32 but only after setting the loop interval to 0 see https://github.com/tronikos/esphome-magnetometer-water-gas-meter/blob/1d78792730be45240fb8de0e90087faad970ef34/esphome-magnetometer.yaml#L32
this is all on an 8266:
sensor:
- platform: qmc5883l
address: 0x0D
oversampling: 64x ## chose lowest oversampling for speed.
range: 200uT
update_interval: 7ms
field_strength_z: ## added internal z to mitigate issues with #6458
id: qmc5883lz
field_strength_x: ## 15x increase in stddev during flow - best SNR for my installation
id: qmc5883lx
filters:
- sliding_window_moving_average: ## oversampling isn't good enough - average 4 readings to reduce noise
window_size: 4
send_every: 4
on_value:
then:
- lambda: |- ## if field is > 14uT and it was previously low
if (x > 14 && !id(water_high)) {
id(water_counter_int) += 1; ## increment internal counter
id(water_high) = true; ## indicate magnetic field is now high
if (id(water_counter_int) % id(increment_multiplier) == 0) { ## i opted not to perform this work on every rotation, but instead to do it every x rotations. I currently have increment_multiplier set to 4
id(water_counter_total) += id(water_increment) * id(increment_multiplier); ## increment water meter by calibrated water_increment times increment_multiplier
id(water_counter_timestamp) = millis(); ## record the timestamp for water flowrate calculation
id(water_flow).update(); ## run component to update flowrate
id(water_total).update(); ## run component to update the total water flow
for (int i = 0; i < 35; i++) ## I have lead pipes between city main and my water meter I use this counter to shift elements of an array that represents the length of stagnation of the water in each segment
id(water_main_elements)[i] = id(water_main_elements)[i+1];
}
id(water_main_elements)[35] = 0; ## last element in the array (newest water in the pipe) has an age of zero
id(water_age).update(); ## update component that indicates the water age at the tap
id(water_dist).update(); ## update component that indicates the distance from the tap to "fresh" water
}
} else if (x < 2 && id(water_high)) { ## if field is < 2uT and it was previously high
id(water_high) = false; ## indicate magnetic field is now low
}
#ESP_LOGD("custom", "High X %f %i", id(qmc5883lx).state, millis()); ##useful for troubleshooting
#ESP_LOGD("custom", "Low X %f %i", id(qmc5883lx).state, millis()); ##useful for troubleshooting
I use the esp_logd command with millis() to figure out what the refresh limits are (typically in a loop with a counter of >1000 to not overwhelm the log).
I added the water_main_elements array in order to track where the "fresh" water was in my pipes. I have the age of the element closest to my tap and the distance until the water is <10 minutes old piped to another ESP8266 in my kitchen that has a light that changes brightness and pulse rate in an way that is understandable by my family so while running the tap, they know when it is safer to drink vs use for other purposes.
The problem
After this merge: https://github.com/esphome/esphome/pull/6458
qmc5883l requires z-axis register to be queried, otherwise x- and y-axes remain constant with what appears to be the first value returned. If only x- or y-axis is queried, issue exists. If only z-axis is queried, works as expected. If ( x- and/or y- ) and z-axis is queried, all work as expected. z-axis must be queried.
Since all axes were queried automatically prior to the merge, the band-aid fix is to just query z-axis in addition to the x- or y-axis you are querying and it works, but this is not intuitive and not how the documentation nor referenced merge advertise the behavior.
The same behavior is happening on two nodemcu 8266 boards and one ESP32 dev each with their own qmc5883l.
Which version of ESPHome has the issue?
2024.4.1
What type of installation are you using?
Home Assistant Add-on
Which version of Home Assistant has the issue?
2024.4.3
What platform are you using?
ESP8266/ESP32
Board
nodemcu
Component causing the issue
i2c/qmc5883l
Example YAML snippet
Anything in the logs that might be useful for us?
Additional information
No response