Average value of a tag over last 20s

I want to calculate the average value of my OPC tag in Ignition for the last 20 seconds.
I tried using an Expression Tag and the following code:

avg(toMillis(now()) - toMillis(tag("OPC TAG PATH)), -20000, now())

Is there any error or issue you encountered with this code? could you please help :slight_smile:

I tried

toMillis(tag("OPC TAG PATH)
und couldent get any value. I got Just Erro_Configuration

A few things wrong here:

  • the expression function for averaging values is mean
  • what is the value of your "OPC TAG PATH"?
  • is the opc tag path the path to the tag in the ignition tag browser? or is it the opc item path from the opc tag browser? (you should be using the ignition tag browser tag)
  • what you have now, assuming it was syntactically correct, would average 3 values: the difference in milliseconds between now and your tag, -20000, and the datetime now. This is definitely not what you're after, I assume

How do you want to calculate the average? Do you just want it using two data points, at -20s and now? or do you want a time-weighted avg using multiple data points over the 20s period?

The most likely answer will be to use system.tag.queryTagCalculations(...) with calculations='Average' in which case you'll need to enable history on the tag

Thanks for your reply :slight_smile:

the value of my OPC TAG PATH is the speed in meters per minute. I want to display the average value of the past 20 seconds with an expression tag.
I am using the ignition tag browser tag
I would like to take into calculation all the values

I will take a look on this

More problems:

  1. Where is the speed from 20 seconds ago stored? You can't just read an OPC tag and subtract time from it. You have to build a shift register in the PLC (best) or in Ignition and calculate from that.
  2. Getting the average of speed now and speed 20 s ago only works if the the speed is constant or accelerating at a constant rate. If the rate changes then you haven't got it!

You should be recording distances or positions and then the average speed becomes
vavg = (s1 - s0) / (t1 - t0)
This will give the true average speed no matter what the speed profile is.


Tip: Use code formatting for code, not > quote which indicates that you are quoting someone else's post.

Formatted code

1 Like

Maybe from the History Tag of Speed?

Then you are goint to have to consider the size of your history table and the speed of your history queries.

Yes, it's by no means going to be terribly efficient to calc the avg of a tag all the time. 20s is very short though so I can't imagine it being that bad. I would try to limit calcing the avg to only when you want to see it. And I also wouldn't go crazy doing this for 100s of tags

For simple displays you can just use a timer control with a dataset.
Create a custom property of dataset type on the root container.
Add a timer control to the window and put this code in it.

from random import randint
sDS = event.source.parent.avgDS
#Create a custom property on the root container called avgDS of dataset type.
#Check for a blank dataset or a dataset larger than 20
# Blank the dataset and create a single INT record to set the datatype of the column
if sDS.getRowCount()>=21 or sDS.getRowCount() < 0:
	hdr=['value']
	blankDS = [[1]]
	event.source.parent.avgDS=system.dataset.toDataSet(hdr,blankDS)
	event.source.parent.avgDS = system.dataset.deleteRow(event.source.parent.avgDS,0)

#grab the current value, add it to the dataset at row 0
sDS = event.source.parent.avgDS
#Replace randint with the tag value you want to average
val = randint(1,450)
nDS = system.dataset.addRow(sDS, 0,[int(val)])
event.source.parent.avgDS = nDS
#delete the oldest row in the dataset
if sDS.getRowCount()>19:
	nDS = system.dataset.deleteRow(nDS,20)
	event.source.parent.avgDS = nDS

Then you can add a label or text box to the window and do an expression of
mean({Root Container.avgDS},0)

Take this with a big grain of salt, this is for a simple window with a simple calculation needed for display.
I would not be doing this for more than a few things.

My recorder() expression function (from Simulation Aids) can maintain this kind of very short term history in a dataset. But if possible, I'd record positions instead of speed, as @Transistor pointed out. Much more precise.