Old analog gas meter located outdoors

I’ve got my electricity monitoring figured out, would like to monitor our gas consumption as well as that is a pretty big portion of our energy use (heating).

The sticky part of this is that my gas meter is an antique and its located on the exterior of my house. I’ve seen where people use hall effect sensors and ESP camera modules to read their analog meters. I’ve not seen anything that would solve this problem while also being waterproof. The sensor itself would need to be waterproof, it would be a simple thing for me to route the data line through the wall into the house to a dry ESP device.

I’m open to suggestions, and I’m aware and OK with the answer might be simply cost prohibitive or impossible to set up.

I’m in the US and have the typical gas meter you see pretty much everywhere (giant diaphragm type). A magnetometer is working fantastic for me. I more or less followed the guidance on this thread:

I made/3D printed a simple case for the sensor that I stuck to the side of the meter to make it mostly waterproof and then ran the wire inside and actually to the same ESP I’m using to also capture electrical usage. I don’t expect the sensor to fail anytime soon from weather, but it also only cost a few bucks and I have spares.

I get a very clean sinusoidal wave that I can use to measure consumption. Happy to dig up the ESPHome YAML code if that would be helpful.

1 Like

How long have you had the sensor out there in the elements? I just assumed it would fail in the weather (snow+rain here in western NY)

Admittedly only a month or 2. But I’m in Kansas City, so we get our fair share of fun weather and I’m not really concerned about it. Outside of humidity, there’s really no way any moisture is getting in it (I’ve got an actual ESP32 outside for another project in a much less water-tight setup and haven’t had any problems after a year).

If you have a 3D printer, if also be happy to share my enclosure design. It’s dead-simple but seemed to work quite well with the magnetometer I went with (QMC5883L):

Hmm, I could always waterproof the board with varnish or epoxy if I see fit

If I ever have an issue with mine, a giant pile of hot glue is going to get added to the new one. :slight_smile:

it couldn’t hurt. :wink:

you might as well post a link to your stl for the enclosure, too.

And a few pics of how it all comes together at the meter if you have any.

Basically what I’m asking is for you to document your setup so I can tell if it could work for me and then steal your idea if so. :grinning_face_with_smiling_eyes:


Here ya go!

I more or less copied code from the forum post I linked to earlier and then tweaked it to my needs. I cleaned up the code here so only the relevant bits are shown (I’ve got a fair bit extra, since I’m also capturing my electrical data on this device as well as using it as a BT proxy). You’ll probably want to uncomment out the other axis (as well as the internal true part) on yours so you can see all the data that you’re getting. Obviously you’ll have to see what kind of readings you get on yours before adjusting the high and low thresholds in the interval lambda bit to match.

   - 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: 0.1s
    - 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;

  sda: GPIO21
  scl: GPIO22

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

Thanks! :slightly_smiling_face:

I know pretty much nothing about the “standard” gas meters in use so where does the sensor mount on the actual gas meter to be able to pick up the pulses?

There’s a picture of where I ended up putting mine on the Thingiverse page. I originally used an app on my phone to use it’s magnetometer to find the best spots (while I had the furnace running). I found both sides worked, but one side gave larger swings in readings while the diaphragm moved (which is good).

And I’ll add to clarify, this method isn’t capturing pulses. This type of gas meter has a large diaphragm that expands and contracts and the magnetometer is able to ‘see’ this movement as a sinusoidal wave. Each cycle represents a certain volume of gas. I originally tried to capture pulses from the face of the meter but never got it to work; not sure if there isn’t a magnet on mine or if it’s just located in a spot too far to be detected.

Ok thanks for all of the clarification. I had never clicked thru to the Thingiverse page yet.

So basically it just senses how close or far the diaphragm is to the sensor?

Yep, that’s exactly it. I just turned on my furnace and watched the cycles while also watching the gauge on the meter to see that in my case 4 cycles corresponded to a single rotation of the half cubic foot dial. A bonus, is that since you have a higher resolution than the actual gauge, it makes calculating low flowrates a lot more doable since you’re getting more data points.

1 Like

This is really cool. I think I’m going to try this on my meter!

@brooksben11 , do you have a photo of the front of your meter? I’ve pulled all the parts together to set this up, and have it working in ESPHome on the bench, just need to adjust my numbers to suit once I mount it on my meter.
I’m pretty sure mine is the same as yours, but would like to visually compare to be sure.
Or can you take a look at mine, and confirm yours is the same? Model # ACM250

Has anyone else successfully set this up on their natural gas meter with Enbridge (formerly Union Gas) in Ontario, Canada?

Yeah, that’s definitely a diaphragm meter. I believe I got better results on one of the sides (in my case, the back). I just plopped it right in the middle of that plate.

Goos luck!

1 Like

Hoping to get some guidance on this, as I try to set it up.

I’ve got everything wired up and “attached” to the back of my gas meter, as seen in these photos.

This is the weatherproof junction box containing the QMC5883L magnetometer and attached to my ESP8266 D1 Mini in my basement on the other side of the exterior brick wall via some CAT-3 cable.

This is the junction box “wedged” between the gas meter and the brick wall to keep it in position.

I’ve added everything to HA and see the x, y and z readings as seen here:

I still need to work through the code and figure out what I’m looking at, and adjust any of the numbers that @brooksben11 had used.

Any helpful tips or thoughts that will get me through this?

I think your first step is to adjust your graph so you only see the last minute or two. Then turn on your furnace (or gas stove, etc.) so you can see what your realtime data looks like (see which axis gives you the best data, what the max/min values of it are and calibrate that data to your meter). Then adjust your code accordingly.

Am I correct that the “z-axis” is giving me the best data. I narrowed down the graph to a 5 minute period and the z-axis appears to have the widest spread from max to min. (-20 to -60 ut)

Here’s a snip of all 3 axis over 5 minutes

And here’s a snip of only the z-axis over another (different) 5 minute period.

One question, what does the “internal: true” part of the code do? I noticed when I comment it out, the graph doesn’t show me any data, however when it is included, the graph shows as above.


That affects whether the data is sent to HA or kept internal to the ESP. Since you don’t need that data (and there’s a LOT of it), it’s best to change it to internal once you get everything setup/calibrated.

1 Like

Can you share what junction box that is? Thanks