Can this gas meter be made smart in any way?

It’s definitely a diaphragm meter. What I did prior to purchasing the magnetometer was to use the one built into my phone to confirm it would work (just downloaded an app that gave me access to the actual sensors in my phone, the one I used was literally called ‘Sensors’). I just ran the furnace and placed it in different spots to test it out. You’ll want to put your phone (or magnetometer sensor) on either the front or back of the meter where that large flat plate is.

are these the sort of fluctuations that we can read with the QMC5883L and convert to something meaningful?

(this was with the heater on, basically a flat line before)

and in terms of magnetic strength, is this weak or normal? would a 3D-printed enclosure hinder the sensor? or does it have to be pushed right up against the meter in the best spot?

Have you seen this one? GitHub - jomjol/AI-on-the-edge-device: Easy to use device for connecting "old" measuring units (water, power, gas, ...) to the digital world

A camera is not an optimal solution for outdoors, the meter is owned by the council, the front meter read cant be obstructed otherwise they’ll get upset when they try read it

The first part of the z-axis looks pretty similar to what I was getting on my phone (kind of looks like you maybe moved your phone to a less optimal spot afterwards). I found it tricky since I had no idea where in my phone the actual sensor was located. I do seem to remember that with my phone, one side of the meter gave much better results than the other (but for whatever reason, this didn’t seem to be the case with the QMC5883L).

You don’t need a massive difference between the peaks and valleys, the key is just that they’re consistent and that there isn’t a bunch of noise in the data.

1 Like

Hi Alex,

This is an explanation of what I did to read my dumb, analogue, rotating dial gas meter - see here - no cameras needed.

It’s been very accurate and reliable and it is cheap to do, and easy to set up too.

I hope that helps! :+1:t2:

Cheers,

Mike.

ive got the QMC5883L hooked up to an esp8266, it sees the sensor, but does not appear to be returning correct values (all 0?):

is this expected behavior?

Definitely not. I used an ESP32 but that shouldn’t make a difference. What’s your YAML look like?

its a straight copy and paste:

# settings
esphome:
  name: gas-meter
esp8266:
  board: nodemcuv2

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  use_address: 192.168.2.58
  domain: .iot

logger:

api:
  encryption:
    key: !secret api_key

ota:
  password: !secret ota_password

# configuration
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'

interval:
  - interval: 0.1s
    then:
    - lambda: |-
       if (id(gasz).state > -75 && !id(gas_high)) {
          id(gas_counter_total) += 1;
          id(gas_counter) += 1;	
          id(gas_high) = true;
        } else if (id(gasz).state < -125 && id(gas_high)) {
          id(gas_high) = false;
        }   

i2c:
  sda: D2
  scl: D1


sensor:
  - platform: qmc5883l
    address: 0x0D
#    field_strength_x:
#      name: "Gas Meter Field Strength X"
#      id: gasx
#    field_strength_y:
#      name: "Gas Meter Field Strength Y"
#      id: gasy
    field_strength_z:
      name: "Gas Meter Field Strength Z"
      id: gasz
      internal: true
#    heading:
#      name: "Gas Meter Heading"
    range: 200uT
    oversampling: 512x
    update_interval: 0.1s

#8 counts per cubic foot, multiplied by 2 to get per minute based on update interval
  - platform: template    
    name: "Gas Rate"
    lambda: |-
      int temp = id(gas_counter);
      id(gas_counter) -= temp;
      float temp2 = temp;
      float temp3 = (temp2/8)*2; 
      return temp3;
    update_interval: 30s
    unit_of_measurement: ft³/min
    device_class: 'gas'

  - platform: template    
    name: "Gas Total"
    lambda: |-
      float temp = id(gas_counter_total);
      return temp/8;
    update_interval: 1s
    unit_of_measurement: 'ft³'
    state_class: 'total_increasing'
    device_class: 'gas'

First thing I’d try is remove everything but the QMC58831 stuff. I’d also uncomment the other parameters and lower the update interval (maybe the 8266 can’t handle such a small interval?). Basically just end up with this:

i2c:
  sda: D2
  scl: D1

sensor:
  - platform: qmc5883l
    address: 0x0D
    field_strength_x:
      name: "Gas Meter Field Strength X"
      id: gasx
    field_strength_y:
      name: "Gas Meter Field Strength Y"
      id: gasy
    field_strength_z:
      name: "Gas Meter Field Strength Z"
      id: gasz
    heading:
      name: "Gas Meter Heading"
    range: 200uT
    oversampling: 512x
    update_interval: 1s

You should definitely be getting values (and they should be moving all around if you move the sensor around, it is essentially a fancy compass after all). Lastly, you are giving the magnetometer board 3V and GND, right? Maybe try swapping the SDA & SCL pins? Other than all that, I’m kind of at a loss. The only other difference is like I said before, that I’m using an ESP32 but I don’t know why that would make a difference.

It did actuall work when i first set it up, only after i made a nice case for it and assembled it all it stopped working. idk how i2c works, but if it sees the sensor that means it should work no? it either says no device found or it should work?

Far from an expert, but yeah, that would be my assumption too.

My best guess is either a connection came loose or for some reason the magnetometer board died.

Turns out the ESP was cooked - probably becase a bit had corroded and it was covered in hot glue, the more you know :expressionless:

Would you have any suggestions on how to calibrate the esphome template?

I assume I would first install the magnetometer on the gas meter, and gather some data, change some values and i should have a pretty accurate readout?..

…I dont even know where to start after installing it

Thanks

Always good to find the root of a random issue like that!

What I did originally is left all the magnetometer sensors visible (so didn’t change them to internal: true or have them commented out). Set everything up and ran the furnace for a few minutes (which might be tricky now, depending where in the world you are). I picked the sensor/axis that had the largest/best variation (read: nice, big and clean sinusoidal waves). Then I edited the firmware, commenting out the other magnetometer sensors that weren’t needed and updated this part of the code:

interval:
  - interval: 0.1s
    then:
    - lambda: |-
       if (id(gasz).state > -75 && !id(gas_high)) {
          id(gas_counter_total) += 1;
          id(gas_counter) += 1;	
          id(gas_high) = true;
        } else if (id(gasz).state < -125 && id(gas_high)) {
          id(gas_high) = false;
        }  

Going off of memory, I believe the values I got for the sensor I ended up using (z-axis in my case) ranged from around -150 to -50. I ended up choosing values that were close to the peaks (-75 & -125), but still a little bit away from them (mainly just as a safety factor in case the values in the future become a little less extreme). In your case, you’ll want to change the above part of the code to use the axis (x,y or z) that has the best readings and change the -75 and -125 to whatever values make sense based on what you see when you’re using gas.

Upload your edited YAML and you should start getting useful data for gas usage/consumption. I ultimately ended up keeping an eye on the raw readings from the z-axis for a week or 2 just to make sure it didn’t change and everything was working as it should. Ultimately though, I changed it to internal: true so that it wouldn’t be sending so much data to HA (every 1/10th of a second) that I don’t actually care about.

The other thing I’ll mention, is if you haven’t already, you’ll need to calibrate it to match your meter (how many cycles of the diaphragm equal how many units of gas). In my case, the wave output from the sensor would go through exactly 8 cycles for 1 cf of gas. So while you’re calibrating things up above, pull up the raw data on your phone and while standing in front of the meter count how many cycles you see when the meter reads 1 of whatever unit it’s counting: presumably it should line up perfectly.

And that was it. Let me know if you run into any issues and good luck!

2 Likes

Got the sensor installed behind the meter, turned on the header and we have data :smiley:

I feel like the X axis had the best strength:


(X is purple, Y is dark blue)

I have done some testing, and in 5 minutes I got 118 cycles (up/down?) which used 0.2m3 on the meter


(This was on the Y axis but they should be the same)

I have updated the invterval based on my understanding, which is the peak plus a bit, and the low minus a bit?:

interval:
  - interval: 0.1s
    then:
    - lambda: |-
       if (id(gas_x).state > -69 && !id(gas_high)) {
          id(gas_counter_total) += 1;
          id(gas_counter) += 1;	
          id(gas_high) = true;
        } else if (id(gas_x).state < -78 && id(gas_high)) {
          id(gas_high) = false;
        }

I think above looks pretty good, going back to the top here, 118 cycles = 0.2m3, how would I put this in the template to proplery calculate flow/usage?

sensor:
  - platform: qmc5883l
    address: 0x0D
    field_strength_x:
      name: "Field Strength X"
      id: gas_x
    range: 200uT
    oversampling: 512x
    update_interval: 0.1s

  - platform: template    
    name: "Gas Rate"
    lambda: |-
      int temp = id(gas_counter);
      id(gas_counter) -= temp;
      float temp2 = temp;
      float temp3 = (temp2/8)*2; 
      return temp3;
    update_interval: 30s
    unit_of_measurement: m³/min
    device_class: 'gas'

  - platform: template    
    name: "Gas Total"
    lambda: |-
      float temp = id(gas_counter_total);
      return temp/8;
    update_interval: 1s
    unit_of_measurement: 'm³'
    state_class: 'total_increasing'
    device_class: 'gas'

I noticed that from the top to the bottom picture, the range of values changed quite a bit. In the top picture, the x-axis is going from (~60 to ~110) while in the last picture they only go from ~70 to ~80. Did you move it or end up going with the Y-axis maybe? You definitely want to go with the axis that gives you the largest difference between highs and lows, that way it’s easier to identify when you’ve gone high/low. Assuming the x-axis data looks the same as in the top picture, I’d probably go with counting high at ~95 and low at ~70 (just eyeballing).

This should get you to the right gas rate/consumptions, based on what you counted.

#118 counts per 0.2m3, or 590 per m3, multiplied by 2 to get per minute based on update interval
  - platform: template    
    name: "Gas Rate"
    lambda: |-
      int temp = id(gas_counter);
      id(gas_counter) -= temp;
      float temp2 = temp;
      float temp3 = (temp2/590)*2; 
      return temp3;
    update_interval: 30s
    unit_of_measurement: m³/min
    device_class: 'gas'

  - platform: template    
    name: "Gas Total"
    lambda: |-
      float temp = id(gas_counter_total);
      return temp/590;
    update_interval: 1s
    unit_of_measurement: 'm³'
    state_class: 'total_increasing'
    device_class: 'gas'

I got the axis names messed up in that first screenshot, then got the axis wrong again in the second screenshot, the correct axis is the last one there with the lines (real X). Because the other two axis had some sort of ballooning, which I assume was the diaphragm moving really slowly, but the X axis did not have this so it looked like the cleanest axis to use

I’d probably go with counting high at ~95 and low at ~70 (just eyeballing).

Where are these numbers from? Is it not the highest and lowest point? When the heaters going full blast (screenshot 3 from before) the lowest is -83 and the highest is like -68, I assume when you use “~” you mean minus (-) not around (~), or ~-…

Thanks for doing those calculations, gas total is working, but gas rate seems stuck at 0m3/min

Are you talking about the bit I circled in red? I think that’s just the diaphragm moving very slowly from a pilot light, so the fact that you can see it is a good sign (since it means it’s more sensitive).

I just eyeballed the same graph (so roughly where the green lines are in my picture.

If it’s working, then there isn’t necessarily a reason you HAVE to change it, but I’d definitely go with the axis I highlighted in my picture since it’s got the largest swing from high to low. In regards to your gas rate not moving, I think that just comes down to the fact that cubic meters are so much larger than cubic feet and you’re using a very tiny percentage of a cubic meter per minute (whereas when my furnace is running I’m using a big percentage of a cubic foot per minute). Might be worth using a rate per 15 minutes (or another unit like cubic feet). Not sure what would be more meaningful to you.

I noticed the style of a few suggestions and comments on this thread (mainly between @alexhyde and @brooksben11 ) which I really like as general development principles (and think contributed to productive/faster troubleshooting). Many are on the site guidelines. Probably pro developers know this stuff by heart but the rest of us might take-away a few things I reckon.

They are something roughly like:

  • Clear OP
  • Share visuals and your config
  • Visualise your sensor data (I like Grafana for granular Viz).
  • Have lots of lower level intermediate sensors during development for debugging and consolidate/internalise them once things are stable.
  • Strip things back to minimal for debugging.
  • suspect it’s hardware (especially power related or connections).

I think learning to debug ESPHOME projects is an important skill which I don’t see discussed too much at a meta level?

Anyway… Just some reflections.

3 Likes

I have changed to the axis you have highlighted (which was the Y axis, ignore the axis names in the screenshot) and have a peculiarity, apparently I have use 17.2 m³ of gas in 1 hour, which seems impractical. I am 100% sure that there was 118 pulses in the 5 minutes, using 0.2m3.

Im not insane that theres a 0.2m3 difference between these photos?

I assume that the decimal point is between the full meter and the mm, so 0.2m? = 200mm3?

I also got the gas rate working by converting m3 to mm3:

# 118 counts per 0.2m3, or 590 per m3, multiplied by 2 to get per minute based on update interval
  - platform: template    
    name: "Gas Rate"
    lambda: |-
      int temp = id(gas_counter);
      id(gas_counter) -= temp;
      float temp2 = temp;
      float temp3 = (temp2/59)*2; 
      return temp3;
    update_interval: 30s
    unit_of_measurement: mm³/min
    device_class: 'gas'

My calculations are probably wrong, I assume 59 pulses = 0.1m3