Close

Calibrating the flow sensor

A project log for Water Flow Monitor

Measuring and totalizing water flow from our well, IoT style

dan-maloneyDan Maloney 12/06/2020 at 03:460 Comments

I bought a flow sensor from Amazon: https://www.amazon.com/gp/product/B086W73NXN

It's made by Gredia, whatever that means -- I could find exactly zero information on the manufacturer and no data sheets on the sensor. All I knew is what was in the Amazon description - 3/4", brass, Hall effect, up to 30 liters per minute. Brass seemed good because I want this sturdy and safe for drinking water, and 3/4" worked because all the piping in the pump house is 3/4" and I don;t wan to introduce any flow restrictions. One problem: it's only available with British Standard Plumbing (BSP) threads.

I bought adapters that claimed to go from BSP to NPT threads: https://www.amazon.com/gp/product/B07Q6SSTRB. These have bonded washers that are supposed to go over the male BSP threads and form a seal against the sensor when the adapter bottoms out and squashes the bonded washer. But the sensor doesn't have a flat bearing surface for the washer to bear against, so I put an O-ring in the BSP side of the adapter which seal the end of the male BSP spud to the flat surface of the female thread in the adapter. I see that they now have these adapters that basically do the same thing: https://www.amazon.com/GESHATEN-Connector-Adapter-Industrial-Fittings/dp/B089D8NF7H

Next I decided to replace the connector on the sensor with screw terminals. I just added a scrap of perfboard and wired the three leads to screw terminals.

My idea for calibration hit me while I was in the shower -- rig up a scale to weigh water flowing through the flow sensor and count the number of pulses. The weight tells you how much water you have, and you can figure out how many pulses per liter the sensor sends back. My first thought was to use a load cell and an HX711 amplifier to build a digital scale. I worked on that for a few nights before coming to the conclusion that I have a bad load cell -- I could never get a stable reading. Then it dawned on me that I cold build a much, MUCH simpler calibration rig:

It's a little hard to see what's going on, so I'll explain. The blue pipe is 3/4" PEX, and the brass bit near the lower end of the pipe is the flow meter, followed by a quarter-turn valve. I made the pipe above the flow sensor long and vertical so that the flow through the sensor would be as close to laminar as possible. Water feeds into the calibrator through the white hose on the back of the upright.

The two buckets on the board are a crude balance. The back bucket catches the water coming out of the flow sensor, while the other bucket has either a 1-kg or 5-kg weight in it. There's a piece of conduit under the board to act a a fulcrum, and a switch under the teeter-totter:

The switch stays closed until there's enough water in the first bucket to tip the balance. My code starts counting pulses from the flow sensor and waits for the input connected tot he switch to change state. When it does, it stops looping and displays the number of pulses. Here's the code:

#include <Arduino.h>


volatile int pulses; // Measures flow sensor pulses
unsigned char flowsensor = 12; // Sensor Input
unsigned char limitsensor = 14;
volatile bool flag = false;

ICACHE_RAM_ATTR void flow () // Interrupt function
{
   pulses++;
}

ICACHE_RAM_ATTR void limit () // Interrupt function
{
   flag = true;
}


void setup() {
   
   pinMode(flowsensor, INPUT);
   pinMode(limitsensor, INPUT);
   digitalWrite(flowsensor, HIGH); // Optional Internal Pull-Up
   digitalWrite(limitsensor, HIGH);
   Serial.begin(115200);
   Serial.println("Starting...");
   attachInterrupt(digitalPinToInterrupt(flowsensor), flow, RISING); // Setup Interrupt
   attachInterrupt(digitalPinToInterrupt(limitsensor), limit, RISING); // Setup Interrupt
   sei(); // Enable interrupts
}

void loop() {
  if (flag == true) {
    Serial.println("Done");
    delay(100000);
  }

  Serial.print("time: \t\t");
  Serial.print(millis());
  Serial.print("\t\tpulses: \t\t");
  Serial.println(pulses);
  delay(100);
}

I used a Wemos D1 Mini because I had one handy, and because I managed to fry one Nano and find another that won't output anything to serial.

I did a bunch of runs and here's the data:

volumestartendelapsedpulsesppl
1276858733.105447447.0
1379666732.877407407.0
1277163763.605524524.0
1267051742.504376376.0
1297060743.104460460.0
532702200018.732488497.6
529692159918.632240448.0
529681989716.9292138427.6
513661819716.8312195439.0
525691959717.0282205441.0
531002069917.5992256451.2
531701839515.2252238447.6
542731869614.4232185437.0
563761979813.4222039407.8
526671675014.0832126425.2

Start, end , and elapsed are just the number of milliseconds -- no real reason to keep track of them, just did it for the heck of it. The numbers were pretty tight -- averaged 442.4 pulses per liter. I think I'll use 442 pulses as my constant. For gallons -- I don't mind calibrating in liters, but gallons is more useful to me in production -- it'll be 1,674.66 pulses. I'll probably use 167.5 pulses and keep track of flow in tenths of a gallon.

Discussions