Gas meter monitoring with optical sensor



  • Hi all,

    This project enables me to read the gas meter using an optical sensor, the TCRT5000. The last digit of the meter has a reflective '6' that triggers the optical circuit. The board is powered by the well known HLK-PM01, and uses an arduino pro mini (clone). The nrf24 is fitted into a board that provides a proper 3.3v voltage. The board can receive OTA firmware upgrades :)

    The sketch (that i adapted from Sandor Incze & Michel Schilthuizen) uses debounce, and raises the counter only if filtered pin value goes from 0 to 1. There is no problem if the meter stops at the '6'. If the sketch starts, it asks the controller for the last known value.

    I use domoticz to present the readings. At this moment, there seems to be a problem with the large numbers that my meter uses, I still need to figure this out.

    Future updates consist of using a fuse and thermistor with the power supply to make it more safe, and to create a nice casing.

    5_1473413948459_IMG_20160909_111734.JPG 4_1473413948458_IMG_20160909_110618.JPG 3_1473413948458_IMG_20160909_110324.JPG 2_1473413948458_IMG_20160909_110304.JPG 1_1473413948458_IMG_20160909_110255.JPG 0_1473413948458_domoticz.png

    code: github



  • @rubyan , I used this method too many years ago, but it was not reliable in my case because the meter was located in the garage, and every time we turned on the light, it would add pulses.

    Can you post a picture of you complete gas meter? Depending on your meter I might have a better solution ;-)



  • Could you place the sketch here? Thanks





  • @rubyan

    Thanks, i have some trouble with adjusting it. I set the trct5000 when the 6 comes by the led goes on. When i use this sketch from the forum

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Mark Verstappen
     * 
     * DESCRIPTION
     * Use this sensor to measure volume and flow of your house gasmeter.
     * You need to set the correct pulsefactor of your meter (pulses per m3).
     * The sensor starts by fetching current volume reading from gateway (VAR 1).
     * Reports both volume and flow back to gateway.
     *
     * Unfortunately millis() won't increment when the Arduino is in 
     * sleepmode. So we cannot make this sensor sleep if we also want  
     * to calculate/report flow.
     * http://www.mysensors.org/build/pulse_water
     */
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    #include <Time.h>
    #include <TimeLib.h>
    
    #include <SPI.h>
    #include <MySensor.h>  
    
    #define DIGITAL_INPUT_SENSOR 3                  // The digital input you attached your sensor.  (Only 2 and 3 generates interrupt!)
    #define SENSOR_INTERRUPT DIGITAL_INPUT_SENSOR-2        // Usually the interrupt = pin -2 (on uno/nano anyway)
    
    #define PULSE_FACTOR 100                       // Nummber of blinks per m3 of your meter (One rotation/liter)
    
    #define SLEEP_MODE false                        // flowvalue can only be reported when sleep mode is false.
    
    #define MAX_FLOW 0,1                             // Max flow (l/min) value to report. This filters outliers.
    
    #define CHILD_ID 1                              // Id of the sensor child
    
    unsigned long SEND_FREQUENCY = 30000;           // Minimum time between send (in milliseconds). We don't want to spam the gateway.
    
    MyMessage flowMsg(CHILD_ID,V_FLOW);
    MyMessage volumeMsg(CHILD_ID,V_VOLUME);
    MyMessage lastCounterMsg(CHILD_ID,V_VAR1);
    
    double ppl = ((double)PULSE_FACTOR)/1000;        // Pulses per liter
    
    volatile unsigned long pulseCount = 0;   
    volatile unsigned long lastBlink = 0;
    volatile double flow = 0;  
    boolean pcReceived = false;
    unsigned long oldPulseCount = 0;                 
    unsigned long newBlink = 0;   
    double oldflow = 0;
    double volume =0;                     
    double oldvolume =550.67;                              // Oude meterstand
    unsigned long lastSend =0;
    unsigned long lastPulse =0;
    
    void setup()  
    {  
      // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion) 
      pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);
      
      pulseCount = oldPulseCount = 0;
    
      // Fetch last known pulse count value from gw
      request(CHILD_ID, V_VAR1);
    
      lastSend = lastPulse = millis();
    
      attachInterrupt(SENSOR_INTERRUPT, onPulse, FALLING);
    }
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Gas Meter", "1.0");
    
      // Register this device as Gasflow sensor
      present(CHILD_ID, S_GAS);       
    }
    
    void loop()     
    { 
      unsigned long currentTime = millis();
          
      // Only send values at a maximum frequency or woken up from sleep
      if (SLEEP_MODE || (currentTime - lastSend > SEND_FREQUENCY))
      {
        lastSend=currentTime;
        
        Serial.println("--------- Debug void loop ------------");
        
        if (!pcReceived) {
          //Last Pulsecount not yet received from controller, request it again
          request(CHILD_ID, V_VAR1);
          return;
        }
    
        if (!SLEEP_MODE && flow != oldflow) {
          oldflow = flow;
    
          Serial.print("m3/min:");
          Serial.println(flow);
    
          // Check that we dont get unresonable large flow value. 
          // could hapen when long wraps or false interrupt triggered
          if (flow<((unsigned long)MAX_FLOW)) {
            send(flowMsg.set(flow, 2));                   // Send flow value to gw
          }  
        }
      
        // No Pulse count received in 2min 
        if(currentTime - lastPulse > 120000){
          flow = 0;
        } 
    
        // Pulse count has changed
        if ((pulseCount != oldPulseCount)||(!SLEEP_MODE)) {
          oldPulseCount = pulseCount;
          
          Serial.println("flow:   ");
          Serial.print(flow);
          
    //      Serial.println(Time.now()); 
          Serial.print("pulsecount:   ");
          Serial.println(pulseCount);
    
          send(lastCounterMsg.set(pulseCount));                  // Send  pulsecount value to gw in VAR1
    
          double volume = ((double)pulseCount/((double)PULSE_FACTOR));     
          if ((volume != oldvolume)||(!SLEEP_MODE)) {
            oldvolume = volume;
    
            Serial.print("volume:   ");
            Serial.println(volume, 3);
            Serial.println("---------------------------------------------------");
            
            send(volumeMsg.set(volume, 3));               // Send volume value to gw
          } 
        }
      }
      if (SLEEP_MODE) {
        sleep(SEND_FREQUENCY);
      }
    }
    
    void receive(const MyMessage &message) {
      if (message.type==V_VAR1) {
        unsigned long gwPulseCount=message.getULong();
        pulseCount += gwPulseCount;
        flow=oldflow=0;
        Serial.println("--------------- Debug void receive ---------------"); 
        Serial.print("Received last pulse count from gw:   ");
        Serial.println(pulseCount);
        Serial.println("---------------------------------------------------");
        pcReceived = true;
      }
    }
    
    void onPulse()     
    {
      if (!SLEEP_MODE)
      {
        unsigned long newBlink = micros();   
        unsigned long interval = newBlink-lastBlink;
        
        Serial.println("--------------- Debug void onPulse ---------------"); 
    //    Serial.println("newblink:   "); 
    //    Serial.print(newBlink);
    //    Serial.println("interval:   "); 
    //    Serial.print(interval);
    //    Serial.println();  
        
        if (interval!=0)
        {
          lastPulse = millis();
          if (interval<500000L) {         
            // Sometimes we get interrupt on RISING,  500000 = 0.5sek debounce ( max 120 l/min)
            return;   
          }
          flow = (60000000.0 /interval) / ppl;
          Serial.println("flow = (60000000.0 /interval) / ppl");
          Serial.println(flow);
          Serial.println("---------------------------------------------------");
        }
        lastBlink = newBlink;
      }
      pulseCount++; 
    }
    

    The counter goes up but it is still off with the gasmeter. Then i upload you're sketch and the counter doesn't go up and the serial monitor says Stable pin value different!
    Can you help?


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.