Calculate Kwh consumption and store it together with Kwh meter

Hello I store every 15 minutes the actual Kwh value of about 100 electrical meters to a database record with fields meternumber, kwhvalue, timestamp with the use of a scheduled block transaction group.
Now I would like to store the power consumption over the last 15 minutes in every database record too. (kwh meter actual record - kwhmeter previous stored record)

What’s the best way to do this ? Can this be done in the block transaction group?

If found following explanation on the forum but it’s not very clear to me.


With that said, it is probably better to store the difference in the table using the transaction group. You can create some expressions to do this:**
1) The first expression item called “lastkwh” grabs the last kwh from a variable and if it is the first time bring back a default value like 0:

getVariable(“lastkwh”, 0)
2) The next expression item does the subtraction using the latest tag value and the previous expression item:

{[GROUP]LiveKWHTag} - {[GROUP]lastkwh}
_Store that expresssion to a column in the database. _
3) The last expression will update the lastkwh variable to the new tag:

storeVariable(“lastkwh”, {[GROUP]LiveKWHTag})
That is it! You should get the difference in your table.

This can be done in a block group. The trick is to understand the execution cycle of the transaction group, and most important is that the Triggered Expression Items will run after the Basic OPC/Group Items, and the Run-Always Expression Items.

One way to get the result you are looking for is to read the meter value as a Basic OPC/Group item, then configure an expression item in the Triggered Expression Items section. Lastly, you will configure the expression item that performs the calculation int he Run-Always Expression Items section. Because the Triggered Expression Item will be evaluated after the calculation, it will still contain the previous value during the calculation.

What I did :

I have created an UDT (with many tags) for an electrical meter, UDT instances are created by passing a “meternumber” parameter.
In the Tag browser there is now a folder EM, with about 100 meter instances, with each instance about 50 tags.
The tagpath for tag “Kwh” from meternumber 50 for instance = EM/M50/Kwh

All tags are coming in OK and we want to save some variables to database for calculating the power consumption.

I used for this a block transaction group :

created a “block item” “meternumber”, therein 100 items (tagpaths) with use of pattern EM/M{?}/meternumber
created a block item “kWHTotal”, therein 100 items (tagpaths) with use of pattern EM/M{?}/KwhTotal

and scheduled the transaction group every 15 minutes.

This works, every 15 minutes there is now for every meter 1 record saved with fields

Timestamp,meternumber,KwhTotal

Is it possible to setup this block transaction group so that there will be saved one extra field “power consumption” in above record.
( = the calculated power consumption from the last 15 minutes for the meter.)

I can add 4 possible items to a transaction group ( OPC / block / expression / tag ),
they all seem to add an extra column to the database record (when you click the blockview tab).

But only in the block item it’s possible to add rows ( 1 for every meter)

Can’t find out how to add an extra calculated field in the database record for every meter with this block transaction setup.

With that many meters I would consider using a script to log your information, assuming you have the Tag Historian module. You would enable historical logging on your Kwh tag. Then you would call a script that would log the data. Your script would first find all the tag paths of your UDT using system.tag.browseTags(), then you would use system.tag.queryTaghistory() to obtain the data from the Tag Historian, finally use system.db.runUpdateQuery() to write the data to your database.

Using a script to log your data has the following advantages 1) It’s easier to maintain, actually there’s nothing to maintain since system.tag.browseTags() is always getting the tags you have created, there’s nothing to update when you add or remove tags from the system. 2) It’s more fault tolerant, since you are querying the history for your data, you’re not relying on a transaction group firing at an exact time. If by chance your transaction group fails to execute, you’ve lost that data. If your script fails to execute, no big deal, just run it again, the data in the historian is still there.

I found a neat solution when I faced the same problem for my power meters. I decided not to mess with the table structure and data but to calculate the differences between readings as needed. I will post code tomorrow (when I’m at work) but the basic trick was:

  • Create a table with binding to the historian data source. This will, effectively, give you Timestamp, meternumber, KwhTotal as you have stated. You have all the advantages of the Ignition monthly partitioning, calendar functions, etc. all handled automatically.
  • Now create a second blank “difference” table. This can cover the other one if you don’t need it.
  • You then create a Python script that is triggered by the historian table’s OnChange event. This script imports the historian table into a list - effectively the same as an array - and you can work on that to output the differences between rows to your new table.
  • If the calendar date range or the meter number is changed the historian table will be updated and retrigger the difference table generation.
  • I also created a chart which uses the difference table as its data source.

I decided that kWh/15 minutes wasn’t awfully useful way of looking at the data. Instead I multiply the 15 minute differences by four to give me the kWh/h or average power in kW for that 15 minute period.

More tomorrow.

OK, thank you for the information already.

  • Create the “HistorianTable” and “DiffTable” table objects.
  • Bind HistorianTable to tag history for the meters in question. The example below uses my meters A to E. (Modify to suit.)
  • Leave DiffTable blank.

Here’s the code for the “Historian” table, Event Handlers, propertyChange, propertyChange.

# Difference between dataset rows.
# This script takes the dataset from a table component and generates an array
# giving the timestamp and difference between rows.
# The original application has five main meters, A - E.

if event.propertyName == "data":
	# Pull the dataset property from a table component
	data = event.source.parent.getComponent("HistorianTable").data
	# Create an array for the output data.
	rowsOut = []
#	system.gui.messageBox(str(type(data.getValueAt(0, 1))))
	# Loop through the dataset, perform the diff calculation and add to the array.
	for row in range(data.rowCount - 1):
		# For 15 minute recording multiply the result by 4 to give meaningful kW.
		if data.getValueAt(row, 1) > 0:
			kWhA = (data.getValueAt(row + 1, 1) - data.getValueAt(row, 1)) * 4
		else:
			kWhA = 0

		if data.getValueAt(row, 2) > 0:
			kWhB = (data.getValueAt(row + 1, 2) - data.getValueAt(row, 2)) * 4
		else:
			kWhB = 0

		if data.getValueAt(row, 3) > 0:
			kWhC = (data.getValueAt(row + 1, 3) - data.getValueAt(row, 3)) * 4
		else:
			kWhC = 0

		if data.getValueAt(row, 4) > 0:
			kWhD = (data.getValueAt(row + 1, 4) - data.getValueAt(row, 4)) * 4
		else:
			kWhD = 0

		if data.getValueAt(row, 5) > 0:
			kWhE = (data.getValueAt(row + 1, 5) - data.getValueAt(row, 5)) * 4
		else:
			kWhE = 0

		kWhSum = kWhA + kWhB + kWhC + kWhD + kWhE 
		oneRow = [data.getValueAt(row, 0), kWhSum, kWhA, kWhB, kWhC, kWhD, kWhE]
		rowsOut.append(oneRow)
	# Create headers for the new table.
	headers = ["Timestamp", "Total", "Board A", "Board B", "Board C", "Board D", "Board E"]
	# Create the new dataset from the array.
	dataOut = system.dataset.toDataSet(headers, rowsOut)
	# Use our new dataset to fill in a Table
	chart = event.source.parent.getComponent("Chart")
	chart.Data = dataOut
	table = event.source.parent.getComponent("DiffTable")
	table.data = dataOut

Scan Class for on-the-hour and 15-minute logging
You seem to have it sorted out already but this may be of interest to others.

  • Create an expression tag “15 minute scan class trigger”, Boolean, Read/Write and have it run at your Default scan class.
  • In the Expression properties of the tag enter the following code:
//Turn on for one minute at 00, 15, 30 and 45 past the hour.
dateExtract(now(0), "minute") = 0
|| dateExtract(now(0), "minute") = 15
|| dateExtract(now(0), "minute") = 30
|| dateExtract(now(0), "minute") = 45
  • Now create a new scan class “15 minute energy logging” with the above tag as the driving tag, operator “=”, value “1” and one-shot execution enabled.
  • Use this scan class for your history logging. You’ll get one reading on the hour and every 15 minutes after that.

See Project screenshots - share yours to see my early attemps at the meter pages.

1 Like