DDS238-1 Cheap Energy-meter with S0 (no RS458)

Moderator: leecollings

Post Reply
fozzyg
Posts: 3
Joined: Saturday 16 January 2016 14:39
Target OS: Raspberry Pi / ODroid
Domoticz version: V3.7xx
Contact:

DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by fozzyg »

This topic describes to connect the cheap DDS238-1 S0 pulse energy meter (without the RS485 that is the DDS238-1ZN) direct to the raspberry GPIO
I could not find a topic for the simple S0 energy meter

Aliexpress https://nl.aliexpress.com/item/5-32-A-2 ... 0.0.SuQ44h
or any other cheap counter. This counter has 1000 pulses, if u use a different one recalculate the power use

connections
Port 22 (plus) of the DDS238 is connected to Raspberry 5v (pin 2 or 4)
Port 20 (minus) of the DDS238 is connected to Raspberry GPIO-13 (pin 33)

Function of the script
This script sends the counter and the power
The script reads from domoticz the last value of the meter, if this is a first start, take a preset

Every pulse is 1/1000 Kw = 1 Watt
Calculate the time between the last puls and the current one.
The energy used over one pulse = 1/time_diff * 3600 seconds

If the time between 2 pulses is 4.08 seconds the used power is 1/4.08 * 3600 = 882 W/H over the period of 4 seconds
Debugline --2017-06-07 19:12:33.264379 power 890.8 W/H in 4.041127 seconds

This value is send to Domoticz directly in a python script that calls a json line to 2 virtual switches (energy actual/counter) in 'from device' mode

I made a divider so the interface is only sending every 5 pulses (0.005 kWh)
The counter is send to a logfile every 100 pulses (0.1 kWh) in my case +/- 12 kWh / day = 120 lines a day


Script S0.py

Code: Select all

#!/usr/bin/python

import RPi.GPIO as GPIO
import datetime
import urllib
import urllib2
import json
import base64
from string import whitespace

GPIO.setmode(GPIO.BCM)
GPIO.setup(13, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

# Settings for the domoticz server
domoticzserver="192.168.0.135:8080"
domoticzusername = "user"
domoticzpassword = "password"
switchid="253"
switchid2="254"


watts=1
lastpuls = datetime.datetime.now()	


base64string = base64.encodestring('%s:%s' % (domoticzusername, domoticzpassword)).replace('\n', '')
domoticzurl = 'http://'+domoticzserver+'/json.htm?type=devices&filter=all&used=true&order=Name'

debug = True
debug = False

logfile = '/var/log/S0power'
print ("Log in " + logfile)

def domoticzrequest (url):
	request = urllib2.Request(url)
	request.add_header("Authorization", "Basic %s" % base64string)
	response = urllib2.urlopen(request)
	return response.read()
		
		
def domoticzstatus (switchid):
	json_object = json.loads(domoticzrequest(domoticzurl))
	switchfound = False
	level = ""
	ilevel = 1.1
	#print json_object
	#print json_object["status"]
	if json_object["status"] == "OK":
		for i, v in enumerate(json_object["result"]):
			if json_object["result"][i]["idx"] == switchid:
				#print(json_object["result"][i])
				switchfound = True
				dlevel = json_object["result"][i]["Data"]
				slevels = dlevel.split(' ')
				level = slevels[0]
	return level
		
		
		

# give here the value of your official  meter
realmeter= 164670400


# read lastmeter from domoticz in W/H
meter_new = float(domoticzstatus(switchid)) * 1000

# if first start  meter is adjusted
if meter_new < realmeter:
	meter_new = realmeter
	
meter_old = meter_new
print('Last value is '  +  str(meter_new/1000))

# write restart to logfile
logregel = str(datetime.datetime.now()) + " Restart S0 counter with value "  +  str(meter_new/1000)
l = open(logfile, 'a')
l.write (logregel + '\n')
l.close()


while True:
	GPIO.wait_for_edge(13, GPIO.RISING)
	GPIO.wait_for_edge(13, GPIO.FALLING)

	now = datetime.datetime.now()
	
	datediff= now - lastpuls
	aantalseconden = datediff.total_seconds()
	power = (meter_new - meter_old) /aantalseconden * 3600


	logregel = str(now) + ' meter_new ' +   str(meter_new/1000) +  ' kW/h'
	
	if debug == True:
		print (logregel)

	if meter_new % 100 == 0: 
		l = open(logfile, 'a')
		l.write (logregel + '\n')
		l.close()
		
	if (meter_new) % 5 == 0 :   # send to Domoticz 
		print (logregel)
		pulsmeter = str(meter_new ) 
		domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid  + "&nvalue=0&svalue="  + str(power) + ";" + str(meter_new))
		domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid2  + "&nvalue=0&svalue="   "0;" + str(meter_new))

		lastpuls = now
		meter_old = meter_new
		
	watts = watts + 1
	meter_new = meter_new + 1


GPIO.cleanowp()
I put this script S0.py in /home/pi/S0
To start the script at startup of the raspberry a service starts the S0.sh script

Code: Select all

chmod 755 S0.sh
S0.sh

Code: Select all

#!/bin/sh
scriptk='/home/pi/S0/S0.py'
exec /usr/bin/python $scriptk  
/etc/init.d/S0meter

Code: Select all

#!/bin/sh

### BEGIN INIT INFO
# Provides: S0 energy meter
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Put a short description of the service here
# Description: Put a long description of the service here
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/home/pi/S0
DAEMON=$DIR/S0.sh
DAEMON_NAME=S0meter

# Add any command line options for your daemon here
DAEMON_OPTS=""

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
start-stop-daemon --start --background --nicelevel -19 --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}

case "$1" in

start|stop)
do_${1}
;;

restart|reload|force-reload)
do_stop
do_start
;;

status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
;;
*)
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
exit 1
;;

esac
exit 0
put the script in the startup of the runlevels

Code: Select all

sudo update-rc.d S0meter defaults
Attachments
usage.JPG
usage.JPG (63.66 KiB) Viewed 11511 times
DDS238layout.jpg
DDS238layout.jpg (254.14 KiB) Viewed 11511 times
Last edited by fozzyg on Monday 12 June 2017 20:00, edited 8 times in total.
Toulon7559
Posts: 843
Joined: Sunday 23 February 2014 17:56
Target OS: Raspberry Pi / ODroid
Domoticz version: mixed
Location: Hengelo(Ov)/NL
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by Toulon7559 »

Why not using Domoticz with the S0-interface connected as pulse-counter for energy?
Search in Domoticz' wiki for implementations.
You don't mention, but for good operation of the S0-interface, the read-out of pin22 of the kWh-meter is OK, but don't forget the pull-up resistor between pin22 and the raspberry's 3V3-power supply.
Set1 = RPI-Zero+RFXCom433+S0PCM+Shield for BMP180/DS18B20/RS485+DDS238-1ZNs
Set2 = RPI-3A++RFLinkGTW+ESP8266s+PWS_WS7000
Common = KAKUs+3*PVLogger+PWS_TFA_Nexus
plus series of 'satellites' for dedicated interfacing, monitoring & control.
fozzyg
Posts: 3
Joined: Saturday 16 January 2016 14:39
Target OS: Raspberry Pi / ODroid
Domoticz version: V3.7xx
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by fozzyg »

I rewrote the code, I wanted not only the counter but also the current power
At startup i read the last value from domoticz

The code puts a pullup resistor in
GPIO.setmode(GPIO.BCM)
GPIO.setup(13, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
gerardwr
Posts: 32
Joined: Saturday 28 January 2017 11:30
Target OS: -
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by gerardwr »

fozzyg wrote: Friday 09 June 2017 16:53 I rewrote the code, I wanted not only the counter but also the current power
Could you share your most recent code please?
User avatar
bbqkees
Posts: 407
Joined: Sunday 17 August 2014 21:01
Target OS: Linux
Domoticz version: 4.1x
Location: The Netherlands
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by bbqkees »

Personally I would never use a Chinese power meter in my fusebox.
If you check locally, approved ones are not even that expensive (<30 Euro).
Remember you need to follow regulations if you are messing inside the fusebox.
Bosch / Nefit / Buderus / Junkers / Worcester / Sieger EMS bus Wi-Fi MQTT Gateway and interface boards: https://bbqkees-electronics.nl/
guillaume1
Posts: 1
Joined: Monday 05 February 2018 22:41
Target OS: -
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by guillaume1 »

Hello
I want to go with a counter to 2000 pulses.
which parameter should we change?

thank you in advance ;) ;)

P.S. I am French, sorry for the translation :(
Pahkis
Posts: 11
Joined: Thursday 23 November 2017 9:03
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by Pahkis »

Hi, I am new user with Domoticz and I would like also to count pulses from energy meter. Actually I have 4 energy meters which are counting pulses 800-1000 pulses/kWh.

What would be best way to add these readings to Domoticz? What hardware I should be using, I have to read pulses from LED on one meter, but three other have S0 output.

I have Raspberry PI 3 on my platform and I am measuring temperatures with DS1820 on 1-wire net.

BR: Mika
paoel73
Posts: 1
Joined: Sunday 25 March 2018 17:11
Target OS: Raspberry Pi / ODroid
Domoticz version: 9054
Location: Netherlands
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by paoel73 »

Hi fozzyg,

Thank you very much for this post. I used your code and it worked out of the box :!:
Very handy way to measure all kinds of input via this 'cheap' meter.
Thanks again for sharing!

Paul.
Pahkis
Posts: 11
Joined: Thursday 23 November 2017 9:03
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by Pahkis »

Is it possible to use this code to count pulses 800-2000 /kwh with 1-wire DS2423 counter?
I bought counter from here: https://tm3d.de/shop/kategorien/bausaetze

Problem is that Domoticz can see all four counters , but on my kWh meters outputs are 800-2000 pulses/kWh s how can I read all those in Domoticz?
fozzyg
Posts: 3
Joined: Saturday 16 January 2016 14:39
Target OS: Raspberry Pi / ODroid
Domoticz version: V3.7xx
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by fozzyg »

If you have a problems with the urrlib2 after upgrading Pi or a fresh install try install urllib3 with pip
sudp pip install urrlib3

I made som redesigns in my script with error correction
my S0Meter needs a 2% correction
my current version

Code: Select all

#!/usr/bin/env python

import RPi.GPIO as GPIO
import datetime
import urllib    
import urllib2	
import json
import base64
import time
from string import whitespace

GPIO.setmode(GPIO.BCM)
GPIO.setup(13, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

# Settings for the domoticz server
domoticzserver="192.168.x.xx:8080"
domoticzusername = "xxx"
domoticzpassword = "xxxx"
switchid="253"
switchid2="254"
switchidzc="280"
switchidstroom="284"

watts=1
lastpuls = datetime.datetime.now()	
correctie = 97  # skip every  x pulse   97 = 3%  correction
correctiecounter = 80  # dit is startpunt voor de correctie teller 

base64string = base64.encodestring('%s:%s' % (domoticzusername, domoticzpassword)).replace('\n', '')
domoticzurl = 'http://'+domoticzserver+'/json.htm?type=devices&filter=all&used=true&order=Name'

debug = True
debug = False

logfile = '/var/log/s0meter'
print ("Log in " + logfile)

def domoticzrequest (url):
	request = urllib2.Request(url)
	request.add_header("Authorization", "Basic %s" % base64string)
	response = urllib2.urlopen(request)
	return response.read()
		
		
def domoticzstatus (switchid):
	json_object = json.loads(domoticzrequest(domoticzurl))
	switchfound = False
	level = ""
	ilevel = 1.1
	#print json_object
	#print json_object["status"]
	if json_object["status"] == "OK":
		for i, v in enumerate(json_object["result"]):
			if json_object["result"][i]["idx"] == switchid:
				#print(json_object["result"][i])
				switchfound = True
				dlevel = json_object["result"][i]["Data"]
				slevels = dlevel.split(' ')
				level = slevels[0]
	return level

# give here the value of your official  meter
realmeter= 168526800  # 27-05-2018 11.00
realmeter= 168609000  # 03-06-2018 11:00

while True:
	try: 
		# read lastmeter from domoticz in W/H
		meter_new = float(domoticzstatus(switchid)) * 1000
		meter_new_zonder_corr = float(domoticzstatus(switchidzc)) * 1000

		# if first start  meter is adjusted
		if meter_new < realmeter:
			meter_new = realmeter
			
		meter_new_zonder_corr = meter_new
			
		meter_old = meter_new
		meter_old_zonder_corr=meter_new_zonder_corr

		print('Last value is '  +  str(meter_new/1000))

		# write restart to logfile
		logregel = str(datetime.datetime.now()) + " Restart S0 counter with value "  +  str(meter_new/1000) + ' zonder corr '  +  str(meter_new_zonder_corr/1000)
		l = open(logfile, 'a')  # add to file 
		#l = open(logfile, 'w')  # new file 
		l.write (logregel + '\n')
		l.close()


		while True:
			GPIO.wait_for_edge(13, GPIO.RISING)
			GPIO.wait_for_edge(13, GPIO.FALLING)

			now = datetime.datetime.now()
			
			datediff= now - lastpuls
			aantalseconden = datediff.total_seconds()
			power = (meter_new - meter_old) /aantalseconden * 3600
			stroom = ((meter_new - meter_old) /aantalseconden * 3600) / 230
			powerzc = (meter_new_zonder_corr - meter_old_zonder_corr) /aantalseconden * 3600
			

			meter_diff = meter_new_zonder_corr - meter_new
			logregel = str(now) +  ' Corr_counter '  +  str(correctiecounter) +  '  meter_new ' +   str(meter_new/1000) +  ' kW/h' +  '  ---  meter_new_zonder_corr ' +   str(meter_new_zonder_corr/1000) +  ' kW/h' + '  ---  Verschil ' + str(meter_diff/1000) +  ' kW/h'
			
			if debug == True:
				print (logregel)

			if meter_new % 100 == 0: 
				l = open(logfile, 'a')
				l.write (logregel + '\n')
				l.close()
				
			if (meter_new) % 5 == 0 :   # send to Domoticz elke 5 Watt
				print (logregel)
				domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchid  + "&nvalue=0&svalue="  + str(power) + ";" + str(meter_new))

				# send current
				domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchidstroom  + "&nvalue=0&svalue="  + str(stroom) )

				# send power withou correction
				domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=udevice&idx=" + switchidzc  + "&nvalue=0&svalue="  + str(powerzc) + ";" + str(meter_new_zonder_corr))

				lastpuls = now
				meter_old = meter_new
				meter_old_zonder_corr = meter_new_zonder_corr
				
				
			# make correction
			if correctiecounter < correctie: 	
				watts = watts + 1
				meter_new = meter_new + 1
				meter_new_zonder_corr = meter_new_zonder_corr + 1
				correctiecounter = correctiecounter + 1
			else:	
				meter_new_zonder_corr = meter_new_zonder_corr + 1
				correctiecounter = correctiecounter + 1
				if correctiecounter > 99:
					correctiecounter = 1
	except :
		print("Domoticz not running ")
		time.sleep(10)
	## end while true
		

GPIO.cleanup()


visioncvg
Posts: 4
Joined: Wednesday 21 November 2018 22:52
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by visioncvg »

Try to get the Energy reader working in Domoticz.
I get a error when give the command sudo update-rc.d S0meter defaults

insserv: script S0meter is not an executable regular file, skipped!

Martin
hjvdheuvel
Posts: 1
Joined: Friday 04 January 2019 23:04
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by hjvdheuvel »

Hello,

Thanks for you code,

i am trying to get ik work but i have a small problem.
the value of the watts is arren't the right one.
he gives me a number like 215144 Watts whit no dots.
i hope you can help me.

the kwh meter that i use is the SDM120DB with S0
Sjuul
Posts: 4
Joined: Tuesday 22 October 2019 19:43
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by Sjuul »

Hello,

I try to read the S0 domoticz PI4.
My setup is a litle bit different I use a Pulgwise UEC80-4D instead of the DDS238-1. The used input is GPIO25

My isseu is the next one:
The pi doesn't count the S0 puls. So I check the hardware with my oscilloscoop there is a puls 3v3..0V and is 50ms long.
My concluision is the hardware works.

The questions is
1. how can the PI4 count this puls,
2. is there a setting for it put a interrupt on this?

Any post is welcome

Regards Sjuul
Sjuul
Posts: 4
Joined: Tuesday 22 October 2019 19:43
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: DDS238-1 Cheap Energy-meter with S0 (no RS458)

Post by Sjuul »

I got a little further. When I run this simplified script it works in the CLI. Now a question remains as to why this is not possible with a "wiring PI" described in the https://raspberryautomation.com/configu ... dvents-lua /

Code: Select all

#!/usr/bin/python

import RPi.GPIO as GPIO #werkt niet omdat deze lib niet gevonden word door Domoticz
import datetime

GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

# give here the value of your official  meter
realmeter= 70000

# init values
meter_new= 0
watts= 0
lastpuls= datetime.datetime.now()

# if first start  meter is adjusted
if meter_new < realmeter:
	meter_new = realmeter
	
meter_old = meter_new
print('Last value is '  +  str(meter_new/1000))

while True:
	GPIO.wait_for_edge(25, GPIO.RISING)
	GPIO.wait_for_edge(25, GPIO.FALLING)

	now = datetime.datetime.now()
	
	datediff= now - lastpuls
	aantalseconden = datediff.total_seconds()
	power = (meter_new - meter_old) /aantalseconden * 3600


	logregel = str(now) + ' meter_new ' +   str(meter_new/1000) +  ' kW/h'
	
		
	if (meter_new) % 5 == 0 :   # send to Domoticz 
		print (logregel)
		pulsmeter = str(meter_new )
		lastpuls = now
		meter_old = meter_new
		
	watts = watts + 1
	meter_new = meter_new + 1

GPIO.cleanowp()
Post Reply

Who is online

Users browsing this forum: Droll and 1 guest