Measure grid consumption – Raspbery pie


Measure grid consumption – Raspbery pie

In this video i go through how I hook up my energy meters for measure the energy consumption. Both sold and bought from grid.

 

This is how its hooked up to the RS485 device:

SDM630 connection for Modbus RS485 adapter

Build it

Building this setup is easy. Modbus protocol is rather simple and it will work on short and long distances. On some setups like in my case where i have more than 100meters i use end termination resistors. Though added extra since the device do have it from the start.

if you hook up the wires the wrong way around nothing will happen. In fact nothing will happen 🙂 On some devices they have not mentioned if its data minus or positive. Like you can see on this meter they only mentioned them as A and B.

My script is designed in such a way that it will fetch the data more then 1 time per second and that it needs atleast 2 sets of data to register them.

Links to Ebay for getting above stuff:

 

Grafana Raspberry PI image – Download and information  (You need version 6 or higher. Will be up 2017-07-19)

The script used

#!/usr/bin/env python
import sys
import httplib
import signal
import socket
import time
import paho.mqtt.client as mqtt
from twisted.internet import task
from twisted.internet import reactor

from pymodbus.constants import Endian
from pymodbus.constants import Defaults
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.transaction import ModbusRtuFramer

#————————- basic settings —————————–
DEBUG = 1

# settings for USB-RS485 adapter
SERIAL = ‘/dev/ttyUSB0’
BAUD = 9600

# settings for SDM630 Modbus
MB_ID = 1
READ_INTERVAL = 0
WRITE_INTERVAL = 2

# settings for EmonCMS
DOMAIN = “emoncms.org”
# DOMAIN = “192.168.0.23”
EMONPATH = “”
APIKEY = “”
NODEID = 1

 

#———————————————————————-
# set Modbus defaults
Defaults.UnitId = MB_ID
Defaults.Retries = 5

 

p1_sum = p2_sum = p3_sum = 0
v1_sum = v2_sum = v3_sum = 0
pl1 = pl2 = pl3 = p14 = 0
vl1 = vl2 = vl3 = 10
il1 = il2 = il3 = 0
msg_count = 0
count = 0
failed = 0

def send2emon(domain, emoncmspath, key, nodeid, data):
conn = httplib.HTTPConnection(domain)
array = []
for c in data:
array.append(str(c))
csv = “,”.join(array)
conn.connect()
conn.request(“GET”,”/”+emoncmspath+”/input/post.json?apikey=”+key+”&node=”+str(nodeid)+”&csv=”+csv)
response = conn.getresponse()
return response.read(), csv

def send2node(fase, watt):
client = mqtt.Client()
client.connect(“192.168.8.142”,1883,60)
client.publish(“electricity/fase/”+ fase, watt);
client.disconnect();

print “Should send now” , fase ,watt
#conn2 = httplib.HTTPConnection(“192.168.8.142”,1880,timeout=1)
#conn2.connect()
#conn2.request(“GET”,”/”+fase+”&watt=”+str(watt))
#conn2.close()

def send2graphite(name, data):
CARBON_SERVER = ‘192.168.10.200’
CARBON_PORT = 2003

message = ‘solar.grid.main.%s %s %d\n’ % (name, data, int(time.time()))

#print ‘sending message:%s’ % message
sock = socket.socket()
sock.settimeout(4)
try:
sock.connect((CARBON_SERVER, CARBON_PORT))
sock.sendall(message)
sock.close()
except (sock.timeout, sock.gaierror) as error:
print ‘Error occourred’

def sig_handler(signum, frame):
reactor.callFromThread(reactor.stop)
client.close()
if DEBUG:
print ‘stopped by Ctrl-C’

def doWork():
print ‘###################################’
global failed, v1_sum, v2_sum, v3_sum, p1_sum, p2_sum, p3_sum, count, msg_count, export, imp
result = client.read_input_registers(0x000, 18)
result2 = client.read_input_registers(0x048, 4)
if result2:
if count >= WRITE_INTERVAL:
decoder2 = BinaryPayloadDecoder.fromRegisters(result2.registers, endian=Endian.Big)
imp = decoder2.decode_32bit_float()
export = decoder2.decode_32bit_float()
print “Export: %.2f import: %.2f” % (export, imp)
if result:
failed = 0
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, endian=Endian.Big)
v1_sum = v1_sum + decoder.decode_32bit_float()
v2_sum = v2_sum + decoder.decode_32bit_float()
v3_sum = v3_sum + decoder.decode_32bit_float()
i1 = decoder.decode_32bit_float()
i12 = decoder.decode_32bit_float()
i13 = decoder.decode_32bit_float()
p1_sum = p1_sum + decoder.decode_32bit_float()
p2_sum = p2_sum + decoder.decode_32bit_float()
p3_sum = p3_sum + decoder.decode_32bit_float()
count = count + 1
print “Count: “, (“%.2f” % count)
if count >= WRITE_INTERVAL:
vl1 = v1_sum / count
vl2 = v2_sum / count
vl3 = v3_sum / count
pl1 = p1_sum / count
pl2 = p2_sum / count
pl3 = p3_sum / count
ts = (p1_sum + p2_sum + p3_sum) / count
v1_sum = v2_sum = v3_sum = 0
p1_sum = p2_sum = p3_sum = 0
count = 0
msg_count = msg_count + 1
data1 = [pl1, pl2, pl3, vl1, vl2, vl3, msg_count, 0, ts]
if DEBUG:
print “V1: %.2f V2: %.2f V3: %.2f” % (vl1, vl2, vl3)
print “P1: %.2f P2: %.2f P3: %.2f” % (pl1, pl2, pl3)
print “Total: “,(“%.2f” % ts)

try:
send2node(“R”, pl1)
send2node(“S”, pl2)
send2node(“T”, pl3)
except:
print “Cannot send to mqtt deamon”, sys.exc_info()

try:
send2graphite(“v1” , vl1)
send2graphite(“v2” , vl2)
send2graphite(“v3” , vl3)
send2graphite(“p1” , pl1)
send2graphite(“p2” , pl2)
send2graphite(“p3” , pl3)
send2graphite(“total” , ts)
except:
print “Problem with graphite”, sys.exc_info()
#try:
#print “borde skicka men avstangd”
#send2emon(DOMAIN, EMONPATH, APIKEY, NODEID, data1)
#except:
#print “Fehler beim Senden:”, sys.exc_info()
else:
if DEBUG:
print “Sent!”
else:
failed = failed + 1
print “no result: “, (“%.2f” % failed)
pass

client = ModbusClient(method=’rtu’, port=SERIAL, stopbits=1, bytesize=8, timeout=0.25, baudrate=BAUD, parity=’N’)
connection = client.connect()
if DEBUG:
print “Readout started”

signal.signal(signal.SIGINT, sig_handler)

l = task.LoopingCall(doWork)
l.start(READ_INTERVAL)

reactor.run()

Liked it? Take a second to support daromer on Patreon!