Skip to content
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
dpcrD

dpcr

@dpcr
  • Getting Started
  • Controller
  • Build
  • Hardware
  • Download/API
  • Forum
  • Store
About
Posts
38
Topics
3
Shares
0
Groups
0
Followers
1
Following
0

Posts

Recent Best Controversial

  • 💬 Water Meter Pulse Sensor
    dpcrD dpcr

    @rejoe2 A magnetometer doesn't need a magnet to work, my gas meter doesn't have a magnet and it works fine. Most all smartphones have magnetometers in them to sense direction. However your solution looks to work as well and probably with less code.

    Announcements

  • 💬 Water Meter Pulse Sensor
    dpcrD dpcr

    @smilvert You could try a magnometer. I successfully used one on my gas meter that didn't have a magnet in it. Look up "gas meter using a magnometer" in this forum. The code is much different than using the standard water meter sketch.

    Announcements

  • 💬 Water Meter Pulse Sensor
    dpcrD dpcr

    @ladislav Sounds like a radio problem. Are you using a capacitor on the radio power supply pins? A capacitor on all radios in your network. I have a an Ethernet gateway in our basement and a node in our attic that is two floors above it and it works fine using a NRF24 for all radios and the radio power is on the default setting and it communicates fine.

    Announcements

  • 💬 Water Meter Pulse Sensor
    dpcrD dpcr

    Has it ever received a pulse count?

    Announcements

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @pihome I power mine with an adapter as well. This node sends too much information to be battery powered. I was researching solar because the sensor sits outside on the south side of our home but never followed up on it. Maybe for another day.

    My Project

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @Ed1500 Good luck on on your project, keep us updated on your progress. I'm also thinking about trying to measure our electricity consumption using CT's rather than at the meter.

    My Project

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @dynamite Makes sense, how would you measures the flow when it gets real low?

    My Project

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @Ed1500 As Dynamite said, it measures the change in the magnet field produced by the movement inside of the meter. I believe all ferris metals can have some sort of effect as well as an electrical field (something like that produced by an AA battery) on the sensor. There is no magnet in my gas meter (Rockwell 250). I used an app on my phone to determine the best possible location of the sensor. Look at the first post.

    My Project

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @dynamite Just checking in, how is your set up working? We just had some major problems with too many extra pulses. It looks like something you experienced earlier, we added some smoothing to the readMag output similar to what you have in your sketch and it seems to working fine. Any updates?

    My Project

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @dynamite I noticed some pulses missing as well. It looks like the newer sketch catches them. I also checked the volume used with our gas suppliers volume used and it was pretty close. We added an error correction variable to try to be more accurate. When I get a chance I'm going to try your sketch, it looks interesting.

    My Project

  • 💬 Domoticz
    dpcrD dpcr

    @breimann I didn't do anything special to install Domoticz on a pi3, I just used their instructions for a pi3. Then I used our router to assign the pi a static IP address on our local network. I then set up an OpenVPN connection on our router so I can connect remotely and securely to our home lan (your router needs to have a support VPN). I installed an OpenVPN app on my phone to connect to our local network, then use a browser to go to the IP and port of Domoticz. Hope this makes sense.

    Announcements

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @dynamite Great idea (top and bottom). We were kicking that around when we made this but wanted to err on the side of missing little to no gas flow. We have a pilot light on our water heater the draws around .1 lpm and I want to capture that as well.

    I agree with you on the accuracy of using a magnetometer over a hall or reed switch, but they (hall or reed) are much easy to program. Too bad there isn't a library for converting a sine wave to pulses, don't forget that sometimes it doesn't look like a sine wave.

    I'm curious to see how you mounted your magnetometer to your gas meter, mine seems a little too bulky and obtrusive. I did manage to buy another magnetometer and dip it in some stuff called PlastiDip. Its used for insulating the handles of tools. I just haven't switched them out yet to see how well it works.

    My Project

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @dynamite I just scanned quickly over your code. So there is no need to store the top and bottom values? What do you do on a power failure? I look forward to hearing from you more.

    Do you have any pics of your hardware?

    My Project

  • Gas Meter Reading Using a Magnetometer
    dpcrD dpcr

    @dpcr New Sketch: This one is version 1.0 and works well with the hardware I'm using. It has an interactive start up menu in the serial monitor when starting which allows one to choose several options and var1 (variable used to store the pulse count on the controller) was removed and the pulse count is now stored in FRAM. It's been running for several months with no problem.

    /*
     * Created by Sean Creel <creels15@gmail.com>
     * 
     * Based on these projects by Henrik Ekblad and Korneliusz Jarzębski:
     * https://www.mysensors.org/build/pulse_water
     * https://github.com/jarzebski/Arduino-HMC5883L
     * 
     * 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.
     * 
     * DESCRIPTION:
     * Uses an I2C triple-axis magnetometer to measure a home's gas usage by
     * detecting small fluxuations in the local magnetic field caused by the
     * meter's bellows pumping in and out. Requires users to determine how 
     * many cycles their meter completes per unit volume of gas flow.
     */
    
    
    
    #define MY_DEBUG                        //enables debugging of MySensors messages
    #define MY_RADIO_NRF24                  //lets MySensors know what radio you're using
    
    #include <MySensors.h>         
    #include <Wire.h>                       //I2C communications library
    #include <Adafruit_FRAM_I2C.h>          //Adafruit FRAM memory library
    
    #define CHILD_ID 1                      //ID of the sensor child
    #define SLEEP_MODE false                //prevent sensor from sleeping
    #define address 0x1E                    //0011110b, I2C 7bit address of HMC5883 magnetometer
    #define topAddr 4                       //address of Top in FRAM
    #define bottomAddr 6                    //address of Bottom in FRAM
    #define pulseAddr 0                     //address of pulseCount in FRAM
    
    //USER-DEFINED CONSTANTS
    #define METRIC true                     //specifies the units of measurement
    #define AXIS "Y"                        //specifies which axes of the magnetometer to read from (multiple axes permitted, e.g. "ZX" or "YXZ")
    #define CYCLES_PER_CUFT 8               //cycles of the meter's bellows per cubic foot of gas (varies by  meter model)
    #define NUM_DIVISIONS 10                //desired number of subdivisions per cycle. higher => more accuracy, lower => more tolerant of noise
    #define ERR 0.00221513400975639000      //used to fix discrepancies between theoretical and actual volume per pulse (vpp)
    #define LEN 3                           //number of flow rate measurements to save for moving average. set to 1 if you want to send raw flow data instead
    #define SEND_FREQUENCY 30000            //Minimum time between messages to the GW (msec)
    #define TOL 50                          //margin of error to account for noise coming from the sensor
    
    bool autoDetect = false;                //true if the program is auto detecting Top and Bottom
    bool rising = true;                     //whether or not a pulse has been triggered
    bool safe = false;                      //whether or not it is safe to switch directions
    unsigned long pulseCount = 0;           //total number of pulses measured ever
    unsigned long oldPulseCount = 0;        //old total
    double vpp = ERR + (METRIC ? 28.3168 : 1.0) / (CYCLES_PER_CUFT * 2 * (NUM_DIVISIONS + 1));//Volume of gas per pulse ft^3/L
    unsigned long lastSend = 0;             //time since last transmission - msec
    double flow [LEN];                      //array of previous gas flow rate measurements
    double avgFlow = 0;                     //average of all elements in flow array
    double oldAvgFlow = 0;                  //previous average flow
    int b = 0;                              //magnetic field reading
    int oldB = 0;                           //previous magnetic field reading
    int top = 0;                            //highest magnetic field registered from meter (Ga)Initialize low if using autoDetectMaxMin
    int bottom = 0;                         //lowest magnetic field registered from meter (Ga) Initialize high if using autoDetectMaxMin
    int newTop = -9000;                     //potential new Top
    int newBottom = 9000;                   //potential new Bottom
    int increment = 0;                      //space b/w dividers
    int counter = 0;                        //used to count pulses over periods longer than SEND_FREQUENCY
    
    MyMessage flowMsg(CHILD_ID,V_FLOW);
    MyMessage volumeMsg(CHILD_ID,V_VOLUME);
    
    Adafruit_FRAM_I2C fram = Adafruit_FRAM_I2C();
    
    void setup(){
      //Initialize Serial, I2C, and FRAM communications
      Serial.begin(9600);
      Wire.begin();
      fram.begin();
      
      //Put the HMC5883 IC into the correct operating mode
      Wire.beginTransmission(address); //open communication with HMC5883
      Wire.write(0x02); //select mode register
      Wire.write(0x00); //continuous measurement mode
      Wire.endTransmission();
    
      //Prompt user for permission to clear all or part of FRAM
      Serial.println("Do you wish to clear all or part of long-term memory?");
      Serial.println("Please enter a number 0-3:");
      Serial.println("0: (default) Clear nothing");
      Serial.println("1: Clear Top and Bottom");
      Serial.println("2: Clear Pulse Count");
      Serial.println("3: Clear Top, Bottom, and Pulse Count");
      int choice = 0;
      lastSend = millis();
      while(Serial.available() == 0 && millis() - lastSend < 30000); //wait 30s max for user input
      choice += Serial.parseInt();
      if(choice == 1){
        clearFram(4,8);
        Serial.println("Top and Bottom values reset");
      }
      else if(choice == 2){
        clearFram(0,4);
        Serial.println("Pulse Count reset");
      }
      else if(choice == 3){
        clearFram(0,8);
        Serial.println("All stored values reset");
      }
    
      //get pulseCount from FRAM
      pulseCount = readUL(pulseAddr);
      oldPulseCount = pulseCount;
      //get Top and Bottom from FRAM
      newTop = readInt(topAddr);
      newBottom = readInt(bottomAddr);
      updateBounds();
      
      //WARNING: MAKE SURE GAS IS RUNNING ON FIRST RUNNING OF THIS PROGRAM!!!
      if(top == 0 && bottom == 0){    
        autoDetect = true;
        newTop = -9000;
        newBottom = 9000;
        
        //determine max and min magnetic field strength over a few minutes
        Serial.println("FRAM has been cleared. Auto-detecting max and min magnetic field reading.");
        Serial.println("WARNING: MAKE SURE GAS IS RUNNING!!");
        lastSend = millis();
        
        while(millis() - lastSend < 120000){
          readMag();
          detectMaxMin();
    
          //display details
          Serial.print("Magnetic Field: ");
          Serial.print(b);
          Serial.print("  Top: ");
          Serial.print(newTop);
          Serial.print("  Bottom: ");
          Serial.print(newBottom);
          unsigned long remainingTime = 120000 + lastSend - millis();
          Serial.print("  Time remaining: ");
          Serial.print(remainingTime / 60000);
          Serial.print(":");
          remainingTime = (remainingTime % 60000) / 1000;
          if(remainingTime >= 10){
            Serial.println(remainingTime);
          }
          else{
            Serial.print("0");
            Serial.println(remainingTime);
          }
        }
    
        updateBounds();
        autoDetect = false;
      }
    
      readMag();
      oldB = b;
      while(abs(b - oldB) < increment / 2){ //wait until difference b/w b and oldB is greater than half an increment
        readMag();
      }
      rising = (b > oldB);
      Serial.println(rising ? "Magnetic field is rising" : "Magnetic field is falling");
      Serial.print("Volume Per Pulse = ");
      Serial.print(vpp,16);
      Serial.println(METRIC ? " L/pulse" : "cuft/pulse");
      lastSend = millis();
    }
    
    void presentation()
    {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("Gas Meter", "1.0 (4/4/17)");
    
        // Register this device as Gas sensor
        present(CHILD_ID, S_GAS);
    }
    
    void loop(){  
      //detecting magnetic pulses - variable boundary method
      while(millis() - lastSend < SEND_FREQUENCY){
        //check if the signal has significantly increased/decreased
        if(abs(oldB - b) > increment){
          pulseCount ++;
          //increment or decrement oldB by one increment based on direction
          oldB += rising ? increment : -1 * increment;     
          safe = false;             //reset safe now that oldB has updated     
        }
        //check if the signal has recently switched directions
        else if(safe){                  //first make sure b has moved a significant distance from oldB
          if((rising && b <= oldB) || (!rising && b >= oldB)){
            pulseCount ++;              //add one extra pulse
            rising = !rising;           //update direction
            safe = false;
          }
        }
        
        //take another reading
        readMag();
        //check if b has moved a significant distance from oldB
        if(abs(b - oldB) > TOL / 2){
          safe = true;
        }
        
        //update newTop and newBottom
        detectMaxMin();                
      }
      
      //shift all flow array elements to the right by 1, ignore last element
      for(int idx = LEN - 1; idx > 0; idx--){
        flow[idx] = flow[idx - 1];
      }
      //calculate newest flow reading and store it as first element in flow array
      flow[0] = (double)(pulseCount - oldPulseCount) * vpp * 60000.0 / (double)SEND_FREQUENCY;
      //display flow array state
      Serial.print("Flow Array State: [");
      for(int idx = 0; idx < LEN - 1; idx++){
        Serial.print(flow[idx]);
        Serial.print("|");
      }
      Serial.print(flow[LEN - 1]);
      Serial.println("]");
      //calculate average flow
      avgFlow = 0;                                //reset avgFlow
      for(int idx = 0; idx < LEN; idx++){         //calculate weighted sum of all elements in flow array
        avgFlow += (flow[idx] * (LEN - idx));
      }
      avgFlow /= (LEN * (LEN + 1) / 2);           //divide by triangle number of elements to get linear weighted average
      Serial.print("Average flow: ");             //display average flow
      Serial.println(avgFlow);
      //send flow message if avgFlow has changed
      if(avgFlow != oldAvgFlow){
        oldAvgFlow = avgFlow;
        send(flowMsg.set(avgFlow, 2));
      }
    
      //send updated volume data if necessary
      if(pulseCount != oldPulseCount){
    
        //send volume data to gw
        send(volumeMsg.set(((double)pulseCount * vpp / (METRIC ? 1000.0 : 1)), 3));
    
        //store updated pulse count total in FRAM
        writeUL(pulseAddr,pulseCount);
    
        counter += (pulseCount - oldPulseCount);      //update counter
        if(counter >= ((NUM_DIVISIONS + 1) * 2)){
          updateBounds();                 //update bounds if at least 1 cycle has been read
          counter = 0;                    //reset counter
        }
    
        oldPulseCount = pulseCount;              //update old pulse count total
      }
    
      lastSend = millis();
      
    }
    
    void updateBounds(){
      if((top != newTop) && (bottom != newBottom)){   //check if anything has actually changed
        //lock in Top and Bottom
        top = newTop;
        bottom = newBottom;
        
        //recalculate increment to match new top and bottom
        increment = (top - bottom - (2 * TOL)) / NUM_DIVISIONS;
      
        //store updated Top and Bottom in FRAM
        writeInt(topAddr,top);
        writeInt(bottomAddr,bottom);
    
        //reset newTop and newBottom
        newTop = -9000;
        newBottom = 9000;
      
        //display new bounds
        Serial.println("NEW BOUNDARIES SET:");
        Serial.print("Top = ");
        Serial.println(top);
        Serial.print("Bottom = ");
        Serial.println(bottom);
        Serial.print("Increment = ");
        Serial.println(increment);
      }
    }
    
    void detectMaxMin(){
      if(b > newTop){
            newTop = b;                    //update newTop if new max has been detected
          }
      else if(b < newBottom){
        newBottom = b;                     //update newBottom if new min has been detected
      }
    }
    
    void writeInt(int addr, int val){       //write an int value to FRAM
      byte b = highByte(val);
      fram.write8(addr,b);
      b = lowByte(val);
      fram.write8(addr + 1,b);
    }
    
    void writeUL(int addr, unsigned long val){  //write an unsigned long falue to FRAM
      byte b = B00000000;
      for(int idx = 0; idx < sizeof(unsigned long); idx++){
        b = val >> 8 * (sizeof(unsigned long) - 1 - idx);
        fram.write8(addr + idx,b);
      }
    }
    
    unsigned long readUL(int addr){         //read an unsigned long value from FRAM
      unsigned long result = 0;
      for(int idx = 0; idx < sizeof(unsigned long); idx++){
        result = result << 8;
        result += (unsigned long)fram.read8(addr + idx);
      }
      return result;
    }
    
    int readInt(int addr){                  //read an int value from FRAM
      int result = 0;
      result += (int)fram.read8(addr);
      result = result << 8;
      result += (int)fram.read8(addr + 1);
      return result;
    }
    
    void clearFram(int first, int last){
      for(int addr = first; addr < last; addr++){
        fram.write8(addr,byte(0));
      }
    }
    void readMag(){
      static int x = 0, y = 0, z = 0;
      
      //Tell the HMC5883 where to begin reading data
      Wire.beginTransmission(address);
      Wire.write(0x03); //select register 3, X MSB register - was called Wire.send but the compiler had an error and said to rename to to Wire.write
      Wire.endTransmission();
    
      //Read data from each axis, 2 registers per axis
      Wire.requestFrom(address, 6);
      if(6<=Wire.available()){
        x = Wire.read()<<8; //X msb
        x |= Wire.read(); //X lsb
        z = Wire.read()<<8; //Z msb
        z |= Wire.read(); //Z lsb
        y = Wire.read()<<8; //Y msb
        y |= Wire.read(); //Y lsb
      }
    
      if(String(AXIS).equalsIgnoreCase("X")){
        b = x;
      }
      else if(String(AXIS).equalsIgnoreCase("Y")){
        b = y;
      }
      else if(String(AXIS).equalsIgnoreCase("Z")){
        b = z;
      }
      else if(String(AXIS).equalsIgnoreCase("XY") || String(AXIS).equalsIgnoreCase("YX")){
        b = x * x + y * y;
      }
      else if(String(AXIS).equalsIgnoreCase("XZ") || String(AXIS).equalsIgnoreCase("ZX")){
        b = x * x + z * z;
      }
      else if(String(AXIS).equalsIgnoreCase("YZ") || String(AXIS).equalsIgnoreCase("ZY")){
        b = y * y + z * z;
      }
      else if(String(AXIS).equalsIgnoreCase("XYZ") || String(AXIS).equalsIgnoreCase("XZY")
              || String(AXIS).equalsIgnoreCase("YXZ") || String(AXIS).equalsIgnoreCase("YZX")
              || String(AXIS).equalsIgnoreCase("ZYX") || String(AXIS).equalsIgnoreCase("ZXY")){
        b = x * x + y * y + z * z;
      }
      else {
        b = 0;
      }
    
      if(!autoDetect){
        //show real-time magnetic field, pulse count, and pulse count total
        Serial.print("Magnetic Field: ");
        Serial.print(b);
        Serial.print(rising ? "  Rising, " : "  Falling, ");
        Serial.print("next pulse at: ");
        Serial.print(rising ? oldB + increment : oldB - increment);
        Serial.print("  Current Number of Pulses: ");
        Serial.print(pulseCount - oldPulseCount);
        Serial.print("  Last Total Pulse Count Sent to GW: ");
        Serial.println(oldPulseCount);
      } 
    }```
    My Project

  • Can a Node Send json?
    dpcrD dpcr

    @AWI Thanks for all your information, it gives me some direction. So from what I have read it sounds like MySensors can't send a json command to Domoticz.

    Development

  • Can a Node Send json?
    dpcrD dpcr

    @gohan No I haven't, I'll give it a try. Thanks.

    Development

  • Can a Node Send json?
    dpcrD dpcr

    Please forgive my ignorance but I have searched and searched and not found what I was looking for. Please help.

    I am making an RFID garage door opener (another) using the MIFARE Classic tags and a MySensors Node. It differs in that I am using the tags to store the tag holder name and encryption keys A & B (I know the generic MIFARE classic encryption has been hacked). What I am trying to do is send the card holders name, time scanned, time access granted or denied to Domoticz. I initially tried a text sensor (V_TEXT) but it only held 16 characters. However using json I can enter up to 40 easily. I can't use the Domoticz logs because from what I have found they only hold their log for several days at the max. I would rather have a dedicated log just for the garage door RFID system.

    My question is, is there a way to send a json command through the mysensors network to my Ethernet gateway then onto Domoticz which is on a Pi on the same network.

    Here is a the json format that Domoticz accepts:

    http://"Domoticz_IP":8080/json.htm?type=command&param=udevice&idx="IDX_of_TextSensor"&nvalue=0&svalue=Hello World
    
    Development

  • RFID Log
    dpcrD dpcr

    @martins It worked out well, I had to tweak it a bit for my situation, but all is well. Thanks for pointing me in the right direction.

    Development

  • RFID Log
    dpcrD dpcr

    @martins Thanks so much, I'll give it a try and let you know how it works out. In my node I'm saving (FRAM) the UID along with the name of the person who hold the tag, so I'd like to send not only the UID but the persons name as well. Again thanks so much for pointing me in the right direction.

    Development

  • RFID Log
    dpcrD dpcr

    I am developing an RFID read/writer based on the one in the hardware section here that actuates our garage door. I have a functioning Ethernet gateway, several function nodes and am using Domoticz as a controller. What I would like to do is write to the Domoticz log when a card is scanned. I would like to keep a record of who comes and goes. I can't seem to find any documentation on how to do this. Any suggestions?

    I have thought about using a pi and write to the Domoticz log through json but I would rather use the MySensors network.

    Development
  • Login

  • Don't have an account? Register

  • Login or register to search.
  • First post
    Last post
0
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular