S0 counter from power meter - how to get kwh?

Hi,
i connected my power meter from the heatpump (s0) with my knx binary sensor.

Now i get the counts of the power meter. The power meter has 2000 impuls/kwh. I get the absolute counts (sum of the counts), not only “1” every time there is a impuls.

What is the best way to get kwh on my sitemap?

knx actor counting internal and only sending new data every xxx counts to the bus or sending every count to the knx bus?

I need a rule to get kwh out of the counts. How can i do this? Is there anybody who has a complete rule for me?

How can i get the “real time” power? I want to know how many watt my heatpump consums at the moment? I think i have to do this in a rule measuring the delay between two impulses?

Hi,

i have kind of a similar setup like yours, and it’s not completed yet, but it goes something along these lines:

  • For calculating kWh, it’s pretty easy - you take the tick count and divide it by 2000, that’s your kWh count (also possible through a defined period of time with persistence).
  • For power, you have to take in time, more ticks per time mean more power consumed. In your case, having 2000 ticks in one hour means you have 1kW power during that period of time in average. So dividing your ticks per hour by 2 gives you the average power over one hour.

Since my actor also only sends every x ticks, not ticks every minute, your rule for calculating power every minute should go along like this (thanks to @Udo_Hartmann):

// Stromzaehler_Gesamt is the tick counter, 
// Stromzaehler_Gesamt_Watt is an unbound Number item persisted every minute
rule "Stromzaehler_Gesamt_Berechnung"
when
  Item Stromzaehler_Gesamt changed
then
  Stromzaehler_Gesamt_Watt.postUpdate(((Stromzaehler_Gesamt.state as DecimalType) - (Stromzaehler_Gesamt.historicState(now.minusMinutes(1)).state as DecimalType)*30))
end

Best regards,
Alex

This should be ))*30) i think ??? Math-Rule point before line (Punkt vor Strich)?

But if only very small power is needed, the rule can´t work, when there is only a new impulse every 2-3 minutes.

Is there a way to measure the time between two impulses and get the actual power from this?

You’re absolutely right, my mistake :slight_smile:

You can always widen the average you do on a longer timebasis, but that would also reduce your granularity i guess.

In theory, one could start a timer when an impulse arrives and stop it when the next arrives, but depending on your setup and the current power used, calculation time needs to be constantly low to yield correct results.

I have same strange things now - but only when the heatinpump is running…

The power from the compressor of my heatingpump ist about 1,1 kW (electrical). The rule shows 1,1 - then it counts in short intervals to 2,2 and falls down to 1,1 … and so on.

I think, i get the counter value 1 minute before, then this is the given value to calculate the watt. The real time counter gets higher - but the counter 1 minute ago is still the same in the rule…

So short time before the next minute beginns, i get the watt calculated from nearly 2 minutes shown in my sitemap.

I hope you can follow my explanations…

Persistence service is rrd4j with strategy every change and every minute. So i think, rrd4j stores a new value every 1-2 second, when heatingpump is running. But the rule only uses the values from every minute…

If heatingpump is in standby (only 30 watt) all is shown correctly, but in this case i only get a impulse from the s0 counter every 1-2 minutes - so there can´t be a big error.

I had sort of the same problem with the rule depending on previous values - granularity. 5 Ticks from my counter mean 300W up or down in a minute for my calculation, so i decided to go another way (as outlined above): Measuring time between 5 ticks coming in and evaluating power from there:

import org.joda.time.DateTime

var lastUpdate = null
var lastCount = 0
var ticksBetween = 5

var smoothingSamples = 5
var total = 0.0d
var average = 0.0d
val samples = newLinkedList()
rule "Stromzaehler_Gesamt_Berechnung"
when
  Item Stromzaehler_Gesamt received command
then
  /*
   * Take 2: React on every input, get the time inbetween and calculate power based
   * on time passed.
   * Very granular, calculation takes about 20ms on Raspi3B
   */
  var newCommand = (receivedCommand as DecimalType).intValue 
  var tickDiff = newCommand - lastCount
  if (lastUpdate != null && lastCount > 0) {
  	if (tickDiff == ticksBetween) {
	  	var startMillis = now().millis
	  	var nowMillis = now().millis
	  	var lastUpdateMillis = (lastUpdate as DateTime).millis
	  	var diff = nowMillis - lastUpdateMillis
	  	var watt = ((3600.0 / diff) * 1000.0 * ticksBetween) as Double

	  	// Calculate moving average
	  	if (samples.size == smoothingSamples) {
	  		total -= (samples.first as Double).doubleValue
	  		samples.removeFirst
	  	}
	  	total += watt
	  	samples.addLast(watt)
	  	average = total / samples.size
	  	
	  	var endMillis = now().millis
		logInfo("Stromzaehler_Gesamt_Berechnung", "Timediff since last update: " + diff.toString() + " ms, posting average: " + average.toString() + " W, calculated "+ watt.toString() + " W")
		logInfo("Stromzaehler_Gesamt_Berechnung", "Calculation took " + (endMillis - startMillis).toString() + " ms")
		Stromzaehler_Gesamt_Watt.postUpdate(average)
	} else {
		logInfo("Stromzaehler_Gesamt_Berechnung", "Tick difference not what we expected: " + tickDiff)
	}
  }
  
  lastUpdate = now()
  lastCount = newCommand
  
  /*
   * Take 1:
   * 
   * Get last historicState from the counter from DB and compare to current Value
   * Yields correct values, but granularity is quite coarse (300W for 5 ticks)
   * 
   */
  //var cur = Stromzaehler_Gesamt.state as DecimalType
  //var prev = Stromzaehler_Gesamt.historicState(now()).state as DecimalType
  //var diff = cur - prev
  //logInfo("Stromzaehler_Gesamt_Berechnung", "Current state: " + cur + ", Previous State: " + prev + ", Difference: " + diff)
  //logInfo("Stromzaehler_Gesamt_Berechnung", "Posting Update to Stromzaehler_Gesamt_Watt: " + (diff * 60).toString()) 
  //Stromzaehler_Gesamt_Watt.postUpdate(diff*60)
end

Code’s a bit of a mess, but i get constant (and very precise) readings from it. You only have to consider that your counter sends 2000 ticks per kWh - adjust my 3600 to your 1800 and you should be ok.

Best regards,
Alex

Super! Thanks a lot. It is working good.

A few questions to your rule:

var ticksBetween = 5

var smoothingSamples = 5

If i want to have a higher resolution with less average values, i have to change this two things to maybe “2” ? Then i measure the time between 2 impulses only and i get the real power of the last time without any average values?

var total = 0.0d
var average = 0.0d

What is this “d” ? Is this 0.0d only 1 decimal behind the point?

Can i calculate the power with this rule with only 1 decimal (= x.x kW --> 100 Watt)?

Can i calculate the power with 3 decimals also? (= x.xxx kW --> 1 Watt)?

ticksBetween is set according to the setting on my binary actuator, which posts the current counter value to be bus every 5 ticks.

smothingSamples is purely for smoothing the value in this rule, you can set it to anything you like - and since it’s a linked list which is not iterated, it should work out in O(1) and only consumes a little bit more memory for each smoothing value.

0.0d tells openhab, that this is to be taken as a double value, so i can neglect casting and/or autoboxing.

The result of this calculation will always be a double, you can set the shown decimal digits in your UI afterwards, somethings like this (that’s my item definition for the power value):

Number  Stromzaehler_Gesamt_Watt   "Stromzähler Gesamt Leistung [%.0f W]"   (gTest,gStromzaehler)

Actually setting smothingSamples to 1 will average over just the current sample, so there will be no averaging.

Yesterday i forgot to remove the old rule, so i did only get my old values. The new rule wasn´t working. Today i removed the old rule but now i always get error messages about this rule:

2017-01-18 09:57:24.280 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Stromzaehler Waermepumpe Berechnung Watt': The name 'lastCount' cannot be resolved to an item or type.

Here is the top of my rule-file:

//
import org.openhab.core.library.types.*   
import org.openhab.core.types.Command
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.joda.time.*
import java.lang.Math
//
import java.util.concurrent.locks.ReentrantLock

// Variablen Waschmaschine + Trockner
val Number MODE_OFF = 0
val Number MODE_STANDBY = 1
val Number MODE_ACTIVE = 2
val Number MODE_FINISHED = 3
var java.util.concurrent.locks.ReentrantLock finishLock  = new java.util.concurrent.locks.ReentrantLock()

// Variablen Stromzähler Wärmepumpe
var lastUpdate = null
var lastCount = 0
var ticksBetween = 1

var smoothingSamples = 2
var total = 0.0d
var average = 0.0d
val samples = newLinkedList()


rule "Stromzaehler Waermepumpe Berechnung Watt"
when
  Item HeatPump_Stromzaehler received command
then
  /*
   * Take 2: React on every input, get the time inbetween and calculate power based
   * on time passed.
   * Very granular, calculation takes about 20ms on Raspi3B
   */
  var newCommand = (receivedCommand as DecimalType).intValue 
  var tickDiff = newCommand - lastCount
  if (lastUpdate != null && lastCount > 0) {
  	if (tickDiff == ticksBetween) {
	  	var startMillis = now().millis
	  	var nowMillis = now().millis
	  	var lastUpdateMillis = (lastUpdate as DateTime).millis
	  	var diff = nowMillis - lastUpdateMillis
	  	var watt = ((1800.0 / diff) * 1000.0 * ticksBetween) as Double

	  	// Calculate moving average
	  	if (samples.size == smoothingSamples) {
	  		total -= (samples.first as Double).doubleValue
	  		samples.removeFirst
	  	}
	  	total += watt
	  	samples.addLast(watt)
	  	average = total / samples.size
	  	
	  	var endMillis = now().millis
		logInfo("Stromzaehler Waermepumpe Berechnung Watt", "Timediff since last update: " + diff.toString() + " ms, posting average: " + average.toString() + " W, calculated "+ watt.toString() + " W")
		logInfo("Stromzaehler Waermepumpe Berechnung Watt", "Calculation took " + (endMillis - startMillis).toString() + " ms")
		Heatpump_Stromzaehler_Watt.postUpdate(average)
	} else {
		logInfo("Stromzaehler Waermepumpe Berechnung Watt", "Tick difference not what we expected: " + tickDiff)
	}
  }
  lastUpdate = now()
  lastCount = newCommand
end

Here is my items-file:

Number	HeatPump_Stromzaehler			"Wärmepumpe Stromzaehler [%d Impulse]"				<energy>		(gHeatpump_Strom,gMapDB)								{knx="12.001:4/3/1"}
Number	HeatPump_Stromzaehler_kwh		"Wärmepumpenzaehler [%.1f kWh]"						<energy>		(gMapDB)										//Calculated via rule
Number	HeatPump_Stromzaehler_Watt		"Wärmepumpe [%.3f kW]"								<energy>														//Calculated via rule
Number	HeatPump_Stromzaehler_kwh_today	"Wärmepumpenzaehler heute [%.1f kWh]"				<energy>		(gMapDB)										//Calculated via rule

Is there something missing???

Can this be a problem of openhab 1.8.3?

Are the imports in my rule file the right ones?

Can i use lastCount in my rule?

Do i have to persist some of the items?

You have some stuff in your rule that i don’t have and you don’t need it for my rule to run:

Replace that with

import org.joda.time.DateTime

and you should be fine.

My rule does not rely on persistence, only that the counter gets posted to the item from knx, but i do persist the calculated value each minute for graphing later on.

This things are for other rules in this rule file…
Ok, i make a new rule file only for my power meter things.

I tend to put everything in seperate rulefiles, makes mantainability and readability better for me :slight_smile:

I did so, but now i get the following error:

2017-01-18 21:37:35.126 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Stromzaehler Waermepumpe Berechnung Watt': Cannot cast org.openhab.core.library.types.DecimalType to void
2017-01-18 21:38:44.419 [INFO ] [c.internal.ModelRepositoryImpl] - Refreshing model 'powermeter.rules'
2017-01-18 21:39:27.950 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Stromzaehler Waermepumpe Berechnung Watt': The name 'lastCount' cannot be resolved to an item or type.

First error i removed with adding of import org.openhab.core.library.types.* on top of my rule-file. Then you can see the refreshing and after that, still the old error message.

I don’t quite get it, try to copy / paste my rule from above and only replace all occurences from my items with your corresponding items - restart openhab to be sure.

Ok, i will do this.

But i did a test the last minutes:

I changed

var lastCount = 0

to

var Number lastCount = 0

Now old error is gone but i get an error message for the next thing in the rule: lastUpdate

I didn’t mention i’m using this rule on OH2 - what version are you on? Maybe there are some syntactical differences that i’m not aware of when it comes to variable initialization?

I told you some postings before…

OH 1.8.3

Maybe @rlkoshak knows something about that???

Oops, must have overread… Let me see -

ticksBetween is an int, as is smoothingSamples and lastCount
lastUpdate is org.joda.time.DateTime
total and average are decimal (already declared by the d at the initialization)

I’m actually not sure if newLinkedList() is available in OH1, but samples is of type java.util.LinkedList