Counting pulses from an electricity meter

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
User avatar
ghayne
Posts: 38
Joined: Sat Jun 08, 2019 9:31 am
Location: Cwmllynfell, Wales

Counting pulses from an electricity meter

Post by ghayne » Fri Nov 08, 2019 6:54 pm

I intend using the following code to read the pulses coming from an electricity meter to calculate instantaneous power and total consumption.

I have a photodiode connected to an ADS1015 A/D converter (many thanks to Roberthh for his modifications to the driver) and everything is working fine on the converter side. Basically I am measuring the time between pulses and writing the resulting delay in microseconds to an InfluxDB database. All subsequent calculations are done with a database query, eliminating lengthy calculations in code.

This works fine for 1-3 hours and then I get the dreaded ECONNABORTED (103) error.
I am pretty new to this and would appreciate comments on how to eliminate the error which I suspect has something to do with urequests.

I am simulating a load of 3.6kW with a Pyboard using the red LED which is flashing about 4 times a second.

Code: Select all

from machine import I2C, Pin, Timer, idle, disable_irq, enable_irq
from ads1x15 import ADS1015
import urequests
import utime
import gc

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)
adc = ADS1015(i2c, 72, 3)


adc.alert_start(4, 0, threshold_high=500,threshold_low=498,latched=False)

server='http://192.168.1.2:8086/write?db=energy'
data = 'useconds value='
now_ms =  utime.ticks_us()
last_ms = utime.ticks_us()
diff=0
pulsed=False

alert = Pin(12, Pin.IN)

def pulse(p):
    global now_ms, last_ms, diff, pulsed
    state = disable_irq()
    pulsed=True

    last_ms = now_ms
    now_ms =  utime.ticks_us()
    diff = utime.ticks_diff(now_ms, last_ms)
    enable_irq(state)

alert.irq(trigger=Pin.IRQ_FALLING, handler=pulse, hard = True)

while True:
    try:
        if pulsed:
            ms = str(diff)
            send_data=data+ms

            resp = urequests.post(server, data=send_data)
            resp.close()
            pulsed = False
        gc.collect()
        gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
        idle()

    except Exception as err:
        print("Exception", err)

User avatar
pythoncoder
Posts: 3669
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Counting pulses from an electricity meter

Post by pythoncoder » Sat Nov 09, 2019 9:10 am

Perhaps 4Hz is too fast for your peer/database. I would try dialling down the LED flash rate to see if it stays up longer. If so you could amend your code to post at a lower rate, averaging the duration between flashes.
Peter Hinch

User avatar
ghayne
Posts: 38
Joined: Sat Jun 08, 2019 9:31 am
Location: Cwmllynfell, Wales

Re: Counting pulses from an electricity meter

Post by ghayne » Sat Nov 09, 2019 10:29 am

pythoncoder wrote:
Sat Nov 09, 2019 9:10 am
Perhaps 4Hz is too fast for your peer/database.
I checked the InfluxDB logs and the entries just stop with no error. I am running this on a Feather Huzzah so the hardware should be reliable. Is there any way to recover from an ECONNABORTED or debug it further?

jonaslorander
Posts: 10
Joined: Tue Nov 08, 2016 12:33 pm

Re: Counting pulses from an electricity meter

Post by jonaslorander » Sat Nov 09, 2019 3:39 pm

I count pulses using a NodeMCU. It has been running för almost two years with no hickups.

The difference is that I use MQTT, I use a comparator to get a digital signal that runs a small interrupt. But, I make all the calculations on the Esp8266 and send totalt energy since boot, energy for the last 15 minutes, and I send power in W.

Before sending data, I checkto see that I am connected to the WiFi. Otherwise I connect. Also, I check if I am connected to the broker before sending data.

Skickat från min BLA-L29 via Tapatalk


User avatar
pythoncoder
Posts: 3669
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Counting pulses from an electricity meter

Post by pythoncoder » Sun Nov 10, 2019 9:35 am

The difference between sending a summary every 15 minutes and sending raw data at 4Hz may explain this. If the database reported no errors my guess is that the peer which receives the data and forwards it to the database is failing to keep up and aborting the transfer. If I'm right, writing code on the ESP8266 to recover from this would be a hack which masks the problem rather than fixes it. Is the PC software still running after you get ECONNABORTED?
Peter Hinch

User avatar
ghayne
Posts: 38
Joined: Sat Jun 08, 2019 9:31 am
Location: Cwmllynfell, Wales

Re: Counting pulses from an electricity meter

Post by ghayne » Sun Nov 10, 2019 10:58 am

pythoncoder wrote:
Sun Nov 10, 2019 9:35 am
Is the PC software still running after you get ECONNABORTED?
I am writing directly to InfluxDB, no software involved. The original scenario was using a Raspberry Pi running InfluxDB but yesterday I installed InfluxDB on a laptop and everything worked fine for about 5 hours, which is over 70,000 successful writes, so the event causing the error is pretty rare. I assume my code is OK? I know the ESP8266 is notorious for reconnects and this may be part of the problem, I'm stumped.
I am going to retry after adding

Code: Select all

esp.sleep_type(esp.SLEEP_NONE)
and see if it improves. Many thanks for the input!

User avatar
pythoncoder
Posts: 3669
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Counting pulses from an electricity meter

Post by pythoncoder » Sun Nov 10, 2019 11:12 am

Perhaps rate isn't the problem, although I'd regard 4Hz as high. Another possibility is WiFi outages.

tl;dr Expect outages and ensure your code can reconnect.

I am currently performing a long term test on an ESP8266 running resilient MQTT in a location with a marginal WiFi signal; I have also done a comparative test with a Pyboard D. The ESP8266 sometimes maintains connectivity for a couple of days. Other times it suffers from repeated outages (from which the code is designed to recover). In a week it's clocked up 236 outages, compared with the Pyboard D's one in 13 days.

While this is a deliberately challenging test, in a location where RSSI varies from -78dB to -88dB, you can expect occasional outages even in areas with good signal strength.
Peter Hinch

User avatar
ghayne
Posts: 38
Joined: Sat Jun 08, 2019 9:31 am
Location: Cwmllynfell, Wales

Re: Counting pulses from an electricity meter

Post by ghayne » Sun Nov 10, 2019 2:58 pm

pythoncoder wrote:
Sun Nov 10, 2019 11:12 am
I am currently performing a long term test on an ESP8266 running resilient MQTT
My original plan was to use MQTT to send data, but as the standard library is blocking I dropped the idea.Your resilient driver looks very interesting! It may be worthwhile to revisit that idea. I am also considering putting a Pyboard D on my Christmas wishes list.

I will also keep the connectivity point in mind.

Garry Hayne

User avatar
pythoncoder
Posts: 3669
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Counting pulses from an electricity meter

Post by pythoncoder » Mon Nov 11, 2019 7:30 am

While the resilient MQTT library has been extensively tested, we have never tried to publish at rates anywhere near 4Hz. The test scripts handle messages at one every 5 seconds.
Peter Hinch

kevinkk525
Posts: 511
Joined: Sat Feb 03, 2018 7:02 pm

Re: Counting pulses from an electricity meter

Post by kevinkk525 » Mon Nov 11, 2019 7:41 am

The micropython-iot library however has been tested at high speed. I did run many tests without any delays, at least my fork with my server implementation.. But I would expect the server version of Peter to have no problem with that either.

On the client side 4Hz however is quite a high rate. It only leaves 250ms for each message and from our experience with the esp8266 this might work as long as there are no delays, socket reads or wifi hickups and you send it as qos=0 when using mqtt_as but I wouldn't expect it to reliably keep up with that message frequency if you use qos=1 or the micropython-iot library (at least Peter's implementation as it sends an ACK to every message, my fork doesn't) as receiving the ACK messages for not losing qos messages will take quite some time.

The simplest latency test of opening a socket, writing a message and immediately receiving a message is on average 180ms. So with additional code etc the target of 250ms is quite tight when expecting an ACK packet from the server.
Kevin Köck
Micropython Smarthome Firmware: https://github.com/kevinkk525/pysmartnode

Post Reply