Readout of domestic water meter using a coil and reading the LC loop in the meter

Thread Starter

mar10

Joined Mar 23, 2019
69
@michael8 wrote:
Could you accumulate a fixed amount of charge in a capacitor for each pulse and then read
the charge via the A/D?
This is an interesting idea which I tested in LT-Spice. The default voltage of the LM339 output is Vcc and the A/D of the ESP8266 works from 0-1V. Considering that the sinking of current is with a much lower resistance than the return via the pull-up resistors R11/R12, a diode is not needed. The readout has to happen at a fixed time after the excitation of the LC. 200µs seems a good choice. It is not sure if the ESP can do the timing of such a measurement reliable. But this is a matter of testing.
The next measurement can be done as soon as 2ms for the capacitor to have recharged enough but we would only measure once per 100ms or so. Also note that the current through R7 suddenly drops as the input offset reaches the driving threshold of the LM339.
Screenshot 2021-11-02 at 17.34.25.pngAnd it beats waiting for the 74HC590 till christmas...
 

Attachments

Thread Starter

mar10

Joined Mar 23, 2019
69
Output as expected. Next: test with ADC.
Picture of zero loaded coil. Good dynamic range...
Zero is lowest dotted line.
Screenshot 2021-11-04 at 08.55.22.png
 

Thread Starter

mar10

Joined Mar 23, 2019
69
Huge progress, but results not very promising.

In order to make sure the setup is stable and properly deployed, I made the 3D printed base, and made power supply, ESP8266 etc the 'final' version. And indeed, when testing it standalone, using the tester LC, it is possible to see that each coil behaves as the simulated circuit. BUT when mounted on the watermeter, the output of each coil is almost not moving outside of the variation when there is no movement.
The ADC output is around 978 in rest and very stable so this suggests there is no interference. The output average is like 360 and 500 at 60µs after triggering.
Future debugging will go into this. For now, reporting on the situation.

Finished circuit, AC fed, with ESP07 module
Screenshot 2021-11-07 at 18.57.33.png
I now wonder if the coils align correctly. I was pretty sure it was fine, but this picture suggest otherwise. Something for later scrutiny.
Screenshot 2021-11-07 at 18.56.15.png
2Bcontinued
 

Thread Starter

mar10

Joined Mar 23, 2019
69
Screenshot 2021-11-08 at 18.21.44.pngThe coils are correctly aligned. So that is not the issue.



Screenshot 2021-11-08 at 18.20.29.pngWaving the test-LC shows a clear measurement effect.





BUT in the position of the picture, we should have a clear difference between Coil1 and Coil2... Not so.
base1 978 C1 386 base2 978 C2 390
base1 977 C1 386 base2 978 C2 396
base1 978 C1 388 base2 978 C2 407
base1 978 C1 386 base2 978 C2 394
base1 978 C1 382 base2 978 C2 398
base1 978 C1 385 base2 978 C2 398
base1 978 C1 378 base2 978 C2 408
base1 978 C1 386 base2 978 C2 398
base1 978 C1 380 base2 977 C2 392
base1 978 C1 385 base2 978 C2 395
base1 978 C1 398 base2 978 C2 396
base1 978 C1 382 base2 978 C2 404
base1 978 C1 389 base2 978 C2 401
base1 978 C1 390 base2 976 C2 400

Maybe the coils were not enough tuned?

After tuning the coils a bit (with no visible effect), I ran half a liter of water and the output is not at all useful ;-(
The two gaps are at the point of best coupling.
Screenshot 2021-11-08 at 18.40.51.png

Regarding the tuning, UN-tuning it seems to work because if I remove the core by half, the readings go to 600 or so, indicating that the current LC is resonating best at 320kHz.

I guess a good night sleep is appropriate.

2Bcontinued

C:
    while (1) {
        printf("base1 %4d   ",sdk_system_adc_read());fflush(stdout);
        gpio_write(COIL1_PIN, 0); //enable COIL1
        sdk_os_delay_us(20); //stabilise the output?
        i2s_dma_start(&dma_block); //transmit the dma_buf once
        sdk_os_delay_us(60);
        printf("C1 %4d   ",sdk_system_adc_read());fflush(stdout);
        gpio_write(COIL1_PIN, 1); //disable COIL1
        vTaskDelay(25); //250ms
        printf("base2 %4d   ",sdk_system_adc_read());fflush(stdout);
        gpio_write(COIL2_PIN, 0); //enable COIL2
        sdk_os_delay_us(20); //stabilise the output?
        i2s_dma_start(&dma_block); //transmit the dma_buf once
        sdk_os_delay_us(60);
        printf("C2 %4d\n",sdk_system_adc_read());
        gpio_write(COIL2_PIN, 1); //disable COIL2
        vTaskDelay(25); //250ms
    }
 
Last edited:

Thread Starter

mar10

Joined Mar 23, 2019
69
Some more observations, no solution
I did many ADC_readings in a row and measured the total time expired.
This suggests that two consecutive ADC_readings are 450µs apart!!
Using the below code, I observe how the reading depends on the µs after the trigger.
It suggests that this already is late for the dip minimum and we are on the rise already.
Maybe part of that 450µs is present BEFORE the actual measurement.
It also shows how much variation the measurements of a completely static setup have.
Whether this is due to variation in the time of measurement or variation of the voltage is unclear.
Remember the base voltage readout is very stable.
Screenshot 2021-11-12 at 18.02.42.png
C:
    while (1) {
        for (int i=1;i<100;i++) {
            printf("%2d  ",i);fflush(stdout);
            gpio_write(COIL1_PIN, 0); //enable COIL1
            sdk_os_delay_us(20); //stabilise the output?
            i2s_dma_start(&dma_block); //transmit the dma_buf once
            sdk_os_delay_us(i);
            printf("C1 %4d  ",sdk_system_adc_read());fflush(stdout);
            gpio_write(COIL1_PIN, 1); //disable COIL1
            vTaskDelay(25); //250ms
            gpio_write(COIL2_PIN, 0); //enable COIL2
            sdk_os_delay_us(20); //stabilise the output?
            i2s_dma_start(&dma_block); //transmit the dma_buf once
            sdk_os_delay_us(i);
            printf("C2 %4d\n",sdk_system_adc_read());
            gpio_write(COIL2_PIN, 1); //disable COIL2
            vTaskDelay(25); //250ms
        }
    }
 

Thread Starter

mar10

Joined Mar 23, 2019
69
OK, some ideas discarded. Like maybe I had blown the capacitor in the watermeter when I tested with the 1A coil in post #34. But the GDO still shows the resonance at 320kHz. It is not very strong though. The gap because of the glass is like 2.5mm and that makes a difference compared to the testLC.
Then I decided that an air coil might couple better. However, it does not.
The below chart shows samples between the aircoil (orange, L1) and the corecoil (blue, L2) when running 3.5 litres of water.
The corecoil shows 3 detections, the aircoil does not show any valid info, it is all noise with perhaps the exception at value 530.

Next step, increase the sample rate and see if noise can be averaged to become less of a problem and return to two corecoils.
Screenshot 2021-11-14 at 17.03.32.png

code used is very fundamental now
C:
while (1) {
    gpio_write(COIL1_PIN, 0); //enable COIL1
    sdk_os_delay_us(20); //stabilise the output?
    i2s_dma_start(&dma_block); //transmit the dma_buf once
    reading1=sdk_system_adc_read();
    sdk_os_delay_us(200); //stabilise the output?
    gpio_write(COIL1_PIN, 1); //disable COIL1
    vTaskDelay(25); //250ms
    gpio_write(COIL2_PIN, 0); //enable COIL2
    sdk_os_delay_us(20); //stabilise the output?
    i2s_dma_start(&dma_block); //transmit the dma_buf once
    reading2=sdk_system_adc_read();
    sdk_os_delay_us(200); //stabilise the output?
    gpio_write(COIL2_PIN, 1); //disable COIL2
    printf("C1 %4d C2 %4d\n",reading1,reading2);
    vTaskDelay(25); //250ms
}
 

Thread Starter

mar10

Joined Mar 23, 2019
69
OK, getting the subject under control. It shows why analogue is often a pain... which doesn't mean it is not likeable ;-)
It also shows that the 74HC590 might be a good idea in the end...
For now we see if this can result in a solid system.

I ran the samples with a spacing of 10ms instead of 250ms (lines 8 and 16 above). This produced a steady picture where there is some heavy sample errors, and the error intensity even shift from one channel to the other... (diagram based on aircoil for orange)
Screenshot 2021-11-15 at 17.54.57.png



The errors are a rhythmic issue (now with two corecoils)
Screenshot 2021-11-15 at 17.55.45.png


It also shows that the minimum is a good indicator of the actual position. So I made it to collect the minimum of 20 samples.
Note that near 2300 there is a gap in orange, which would have exceeded the blue if only 10 samples taken.
Screenshot 2021-11-15 at 18.09.58.png
The overall spacing between reports of the minimums is now 400ms, which is a good value I guess. The meter cannot turn super fast anyway, although we might have to speed this up a little maybe based on future testing.

Screenshot 2021-11-15 at 17.51.54.png
The potential solution for deciding if the counter moved is "if the lines switch position and the diff is at least 5" And maybe an offset is needed which is determined dynamically considering the lowest and highest minimum for both coils are not the same.
This will be implemented and long term comparison between actual counter and measured value should indicate no missing water...

C:
while (1) {
    min1=1023;min2=1023;
    for (i=0;i<WINDOW;i++) {
        gpio_write(COIL1_PIN, 0); //enable COIL1
        sdk_os_delay_us(20); //stabilise the output?
        i2s_dma_start(&dma_block); //transmit the dma_buf once
        reading1=sdk_system_adc_read();
        sdk_os_delay_us(200); //stabilise the output?
        gpio_write(COIL1_PIN, 1); //disable COIL1
        if (min1>reading1) min1=reading1;
        vTaskDelay(1); // 10ms

        gpio_write(COIL2_PIN, 0); //enable COIL2
        sdk_os_delay_us(20); //stabilise the output?
        i2s_dma_start(&dma_block); //transmit the dma_buf once
        reading2=sdk_system_adc_read();
        sdk_os_delay_us(200); //stabilise the output?
        gpio_write(COIL2_PIN, 1); //disable COIL2
        if (min2>reading2) min2=reading2;
        vTaskDelay(1); // 10ms
    }
    printf("%6d %3d %3d\n",sdk_system_get_time()/1000,min1,min2);
}
 

Thread Starter

mar10

Joined Mar 23, 2019
69
The first 3.5 litres have been measured. Checking long term reliability.
Screenshot 2021-11-16 at 21.32.34.png
C:
#define  OFFSET  -8       // how much coil1 is higher than coil2
#define  HYSTERESIS  10   // to prevent noise to trigger
  if (direction) {
      if ((min1-min2)>OFFSET+HYSTERESIS) { halflitres++; direction=0; }
  } else {
      if ((min1-min2)<OFFSET-HYSTERESIS) { halflitres++; direction=1; }
  }
 

Thread Starter

mar10

Joined Mar 23, 2019
69
I didn't expect to report so soon, and it is not good news. It is too noisy!

The normal noise exceeds the hysteresis and at the same time the hysteresis is too big.
This means we have false positives (account for +0.5 litres) and false negatives (account for -1 litre).
The false positives can BTW generate MANY litres of usage while there is zero usage if the counter stops in the break even zone.

Altogether, this shows that the mechanism cannot work unless I bring the noise down.
The question is where this noise is from... Probably the timing of the ADC or whatever. But this cannot be controlled, since the ESP8266 Wifi routines and whatnot have high priorities and they might influence the exact ADC sample time.

One attempt for an alternative fix is that the R9/R10 divider could use a capacitor to keep it stable and/or to use one or two decades smaller resistors.

If that won't help, I hope the 74HC590 counter will do a better job...

2Bcontinued
Screenshot 2021-11-18 at 18.06.52.png
 
Last edited:

Thread Starter

mar10

Joined Mar 23, 2019
69
first test at applying a Capacitor of 100nF in parallel with R10 seems successful
Let us see if this is false hit resistant

Screenshot 2021-11-19 at 19.01.44.png
 

Thread Starter

mar10

Joined Mar 23, 2019
69
Small update. After 2500 litres of used water, the counter only has 2.5 l too much. Which is quite reasonable.
Despite that, I think that the counter instead of the ADC will have to be tried. The maximum speed at which this can count is border case, and I had to tune a bit with hysteresis, offset etc before it became almost reliable.
So, not bad, but when the 74HC590 arrives, I'll test with that.
2Bcontinued
 
Last edited:
Top