GPIO meter pulse counting with instant power calculation

Moderator: leecollings

salvacalatayud
Posts: 112
Joined: Monday 26 June 2017 21:16
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Spain
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by salvacalatayud »

I'm totaly zero to scripts, so sorry if I say anithing stupid.

As my pi is far from the counter, I would like to use a wemos d1 and send data via mqtt, is it possible to use this script to calculate instant power this way?

Thanks in advance
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by MikeF »

I have been using this script successfully for electricity only. I am using the photosensor as described in the OP, together with a dedicated RPi Zero W, sending readings via WiFi to Domoticz. Here's how it looks in my meter cupboard:
Image Image
I've also amended the script, to show the meter reading, which - over the last 48 hours - has been spot on with the actual meter (never missed a pulse)!
Image
I am very pleased with this script - thank you! :D :D :D
RidingTheFlow
Posts: 72
Joined: Friday 11 March 2016 18:23
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Essex, UK
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by RidingTheFlow »

salvacalatayud wrote: Friday 01 February 2019 12:31 As my pi is far from the counter, I would like to use a wemos d1 and send data via mqtt, is it possible to use this script to calculate instant power this way?
You can count pulses on wemos and periodically send number of pulses via mqtt (resetting wemos counter to zero).
And you will need to change script not to count pulses directly, but rather get them from mqtt message.

Great setup @MikeF, glad its been of help!
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by MikeF »

I've now added a gas counter, using a reed switch version of the optical sensor mentioned in the original post: https://www.ebay.co.uk/itm/Reed-Sensor- ... Sw6CJbEYRS

I've also created a 'smart meter' dashboard, using ImperiHome (via MyDomoAtHome) on an Android tablet:

Image
DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by DarkG »

Is there a manual how to use this?
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by MikeF »

DarkG wrote: Wednesday 06 May 2020 21:15 Is there a manual how to use this?
None, I'm afraid - but there's some very useful information in the original post (OP) on this thread.

Implementation depends entirely on what meters you have - I have a digital electricity meter, with an LED which blinks once per Wh; I use the optical sensor as shown in the original post. My gas meter is a mechanical one, with a magnet in place of the zero digit on the last reel, which rotates once per 1/100 m3; I've used a reed switch sensor as shown in my previous post. Both sensors are connected to the GND, 3.3V (not 5V) and GPIO pins on the RPi (24 for electricity sensor, 17 for gas sensor).

I use a modified version of RidingTheFlow's python script:
Spoiler: show

Code: Select all

#!/usr/bin/env python

'''
Based on https://www.domoticz.com/forum/viewtopic.php?f=32&t=11315
by RidingTheFlow
'''

import time
import json
import requests
import threading
from gpiozero import DigitalInputDevice

get_url = 'http://<domoticz url:port>/json.htm?type=devices&rid=%s'
set_url = 'http://<domoticz url:port>/json.htm?type=command&param=udevice&idx=%s&svalue=%s'
gas_idx = <idx for gas sensor>
gas_gpio = 17
elec_idx = <idx for electricity sensor>
elec_gpio = 24

gas_delta = 0
gas_counter_lock = threading.Lock()
elec_delta = 0
elec_counter_lock = threading.Lock()
elec_last_time = 0
elec_post_time = 0

def gas_intr():
    global gas_delta
    with gas_counter_lock:
        gas_delta += 10

def elec_intr():
    tme = time.time()
    global elec_delta
    global elec_last_time
    global elec_post_time
    with elec_counter_lock:
        elec_last_time = tme
        if elec_post_time == 0:
            elec_post_time = elec_last_time
        else:
            elec_delta += 1

def main():
    global gas_delta
    global gas_counter
    global elec_delta
    global elec_last_time
    global elec_post_time
    global elec_counter
        
    res = requests.get(get_url % elec_idx).json()
    elec_counter = int(float(res['result'][0]['Data'][:-4]) * 1000)

    res = requests.get(get_url % gas_idx).json()
    gas_counter = int(float(res['result'][0]['Data']) * 1000)
    
    elecSensor = DigitalInputDevice(elec_gpio, pull_up=True)
    elecSensor.when_deactivated = elec_intr

    gasSensor = DigitalInputDevice(gas_gpio, pull_up=True)
    gasSensor.when_activated = gas_intr  
    
    while True:
        time.sleep(60)

        gas_delta_post = gas_delta

        if gas_delta_post >= 0:
            gas_counter += gas_delta_post
            with gas_counter_lock:
                gas_delta -= gas_delta_post
            meter  = format(gas_counter / 1000.0, '.3f')
            res = requests.get(set_url % (gas_idx, gas_counter))

        with elec_counter_lock:
            if elec_last_time > elec_post_time:
                elec_load = elec_delta * 3600 / ( elec_last_time - elec_post_time )
            else:
                elec_load = 0

            elec_counter += elec_delta
            meter  = format(elec_counter / 1000.0, '.2f')

            elec_delta = 0
            elec_post_time = elec_last_time

        if elec_load != 0:
            res = requests.get((set_url+';%s') % (elec_idx, int(elec_load), elec_counter))


if __name__=="__main__":
    main()  

- you'll need to substitute your own Domoticz url and port, and idx's for the two dummy sensors you need to set up to receive the data. I run the script via cron every 5 minutes.

I've extended this further, with a dzVents script to display energy and costs, using custom Domoticz sensors:
Spoiler: show

Code: Select all

-- dzVents script to calculate electricity and gas costs

return {
    on = { timer   = { "every minute" }}, 

    execute = function(dz)
        -- devices
        local elecUsage     = dz.devices("Electricity usage").counterToday
        local elecCost	    = dz.devices("Electricity cost")
        local elecEnergy    = dz.devices("Electricity energy")
        local gasUsage		= dz.devices("Gas usage").counterToday
        local gasCost		= dz.devices("Gas cost")
        local gasEnergy		= dz.devices("Gas energy")
        local totalCost		= dz.devices("Total cost")
        local costTest		= dz.devices("Cost_test")
        
        -- prices in pence
        local elecStdChge = 20.44
        local elecUnitPrice  = 13.587
        local m3_kWh = 1.02264 * 39.3 / 3.6 -- conversion factor x calorific value / kWh
        local gasStdChge = 20.44
        local gasUnitPrice = 3.371
        
        -- calculate values
        local elecCostVal	= dz.utils.round((elecUsage * elecUnitPrice + elecStdChge),1)   -- rounded to 1 dp
        local elecUsageVal	= dz.utils.round(elecUsage,3)            	                  -- rounded to 3 dp's
        local gasCostVal   	= dz.utils.round((gasUsage * m3_kWh * gasUnitPrice + gasStdChge),1)   -- rounded to 1 dp
        local gasEnergyVal  = dz.utils.round((gasUsage * m3_kWh),3)  -- rounded to 3 dp's
        local totalCostVal  = elecCostVal + gasCostVal
        --print(elecCostText, gasCostText, totalCostText)

        -- update devices
        elecCost.updateCustomSensor(elecCostVal)
        elecEnergy.updateCustomSensor(elecUsageVal)
        gasCost.updateCustomSensor(gasCostVal)
        gasEnergy.updateCustomSensor(gasEnergyVal)
        totalCost.updateCustomSensor(totalCostVal)
        costTest.updateCounter(totalCostVal)
    
    end
}
Here, you'll need to substitute your own energy unit costs.

This gives me the following in my Utilities tab in Domoticz:
Image

Finally, the 'smart meter' display in my previous post was created in ImperiHome on an Android tablet - you'll need MyDomoAtHome for this (see the Domoticz wiki for this).
DarkG
Posts: 89
Joined: Friday 15 September 2017 18:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10076
Location: Germany
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by DarkG »

Thank you.

My questions is where to put the script and how to autostart it.
I put the script in home directory and ecexuted it, but I get no Data in Domoticz. IDX is right.

But first of all it must start himself.
RPi4 Shelly1 Shelly2.5 ESPEasy Tuya Domoticz Beta Dashticz 3.6
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by MikeF »

DarkG wrote: Wednesday 13 May 2020 11:10 Thank you.

My questions is where to put the script and how to autostart it.
You can add a line to /etc/rc.local like this:

Code: Select all

python /home/pi/devices/elec_gas_meter.py &
at the end (but before the line which says 'exit 0'
- or you can run it from cron, like this:

Code: Select all

@reboot python /home/pi/elec_gas_meter.py > /dev/null 2>&1 &
I put the script in home directory and ecexuted it, but I get no Data in Domoticz. IDX is right.
- and the domoticz url and GPIO pin numbers are correct?
azonneveld
Posts: 157
Joined: Wednesday 02 October 2019 7:37
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.4
Location: Netherlands
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by azonneveld »

RidingTheFlow wrote: Tuesday 29 March 2016 14:34 For gas meter I detected a magnet which was located *after* the last digit disk.
I am also looking for a solution to read my gasmeter.
Could you post a picture of you gasmeter, so I could determine if my gasmeter also has this magnet?
rpi4 - zigbee2mqtt - roborock - espeasy - rfxcom - homewizard p1 - otgw - homebridge - surveillance station - egardia - goodwe - open weather map - wol - BBQ detection - rsync backup
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by MikeF »

azonneveld wrote: Thursday 14 May 2020 12:17
RidingTheFlow wrote: Tuesday 29 March 2016 14:34 For gas meter I detected a magnet which was located *after* the last digit disk.
I am also looking for a solution to read my gasmeter.
Could you post a picture of you gasmeter, so I could determine if my gasmeter also has this magnet?
Image
This is an Actaris G4 meter - as you can see, there is a small silver magnet in place of the 0 digit in the last reel.

I've placed a reed switch in a plastic case underneath (there is a cutout), which is activated as the magnet passes over it. 1 revolution = 1/100 m3.
azonneveld
Posts: 157
Joined: Wednesday 02 October 2019 7:37
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.4
Location: Netherlands
Contact:

Re: GPIO meter pulse counting with instant power calculation

Post by azonneveld »

MikeF wrote: Thursday 14 May 2020 13:32 This is an Actaris G4 meter - as you can see, there is a small silver magnet in place of the 0 digit in the last reel
Thnx for the quick reply! Unfortunately my meter is a lot older... I guess my meter doesnt have a magnet...
I have considered installing a Cognex, but the budget is not sufficient :-P
rpi4 - zigbee2mqtt - roborock - espeasy - rfxcom - homewizard p1 - otgw - homebridge - surveillance station - egardia - goodwe - open weather map - wol - BBQ detection - rsync backup
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests