← Articles
Historian/8 min read/ views

How to Validate a Historian Calculated Tag Before Reports Depend On It

A calculated tag quietly becomes an official number. Checking formula, quality rules, period boundaries and counter resets before reports depend on it.

HistorianTagsSCADATrendsTroubleshooting

The maintenance planner said pump P-101 ran 412 hours last month. The reliability dashboard said 511. Both numbers came out of the same historian, from two calculated tags built eighteen months apart by two people who never talked. One counted runtime from motor current above 4 A. The other counted it from the run feedback contact. The current-based one kept accumulating through every jog and every recirculation test; the feedback-based one dropped 90 hours of low-load running that the drive never reported as a fault.

Nobody was wrong. Nobody had written down what "runtime" meant.

That is the whole problem with calculated tags. They start as a convenience — an hourly average so the trend screen loads faster, a daily total so somebody stops exporting CSVs — and within a year they are feeding the shift report, the energy review, and an MES interface that nobody wants to touch. A calculated tag with no definition is worse than no calculated tag, because it looks official.

Write the rule in process language before you write the expression

Before opening the expression editor, write the rule in a sentence an operator can argue with. For the pump above:

  • Running means P101_StatusCode = 30. Not motor current, not VFD speed feedback.
  • Intervals where the source quality is Bad do not accumulate; they accumulate into a separate P101_RuntimeUnknown tag.
  • The total is stored in hours against the site production day (06:00–06:00), not the UTC calendar day.
  • Late data triggers a recalculation of the previous 48 hours.

Four bullets. It takes ten minutes and it settles the 412-versus-511 argument permanently, because the next person can read it without reverse-engineering an expression.

I put this text in the tag description field, not in a Word document on a share drive. Descriptions travel with the tag through backups and migrations; the Word document does not.

The five kinds of calculated tag fail differently

Do not validate them all with one trend screenshot.

TypeExampleWhat actually breaks
Instant expressionDensity-corrected flowBad input produces believable junk, not an obvious spike
Time-weighted averageHourly tank temperatureIrregular sampling and deadband compression bias the mean
Event durationTime in running / faulted / blockedStale values and missed transitions
Totalizer rollupDaily water or gas volumeCounter resets and rollover
Shift or batch summaryOEE, downtime minutes, material totalBoundary timestamps and late data

The instant expression is the sneaky one. If the density transmitter fails to a plausible 998 kg/m³ instead of going Bad, the corrected flow stays inside the trend's normal band forever and no alarm fires.

Decide what Bad quality does — explicitly

If one input is Bad for ten minutes out of the hour, what is the hourly average? There are five defensible answers and one indefensible one.

Defensible: mark the whole result Bad; produce a partial value plus a companion ValidPercent tag; hold the last good value for operator display only; exclude the Bad interval from the average and report the excluded duration; stop accumulating entirely.

Indefensible: let the expression coerce Bad to zero and keep going. That is how you get a false 12% energy saving on the day a meter lost communication.

This is worth doing properly because the standards already give you the vocabulary. IEC 62541-13 (OPC UA Part 13, Aggregates) defines an AggregateConfiguration with TreatUncertainAsBad, PercentDataBad, and PercentDataGood — the aggregate returns Uncertain or Bad based on how much of the interval had usable data, rather than silently averaging whatever showed up. If your historian exposes those settings, use them instead of writing your own quality logic in an expression. If it does not, at least mirror the concept: store the coverage percentage next to the value.

Watch out for Uncertain_LastUsableValue in particular. Some clients render it exactly like Good, and a held value that stays flat for four hours looks like a very stable process.

Time boundaries break more calculated tags than arithmetic does

In my experience most calculated-tag defects are not math errors. Run through these before commissioning:

  • Is the rollup stamped at the start or the end of its period? A daily total stamped at 00:00 and a daily total stamped at 23:59:59 will land in different months once a year.
  • Does the day boundary follow midnight, shift change, or the production day? Pick one per report and say which.
  • Are values stored in UTC and displayed in local time? Then two days a year have 23 and 25 hours. A "daily average" over a 25-hour day using a fixed 24-hour divisor is off by 4%.
  • Does the calculation key off source event time or historian arrival time? With a store-and-forward collector these differ by minutes to days.
  • Can a late sample reopen a closed period, and if so, does anything notify the person who already exported the report?

A correct number in the wrong hour is still a wrong report, and it is much harder to spot than a number that is obviously garbage.

Validate against a hand calculation, on a window you chose deliberately

Do not start with a month of data. Pick a two-hour window that contains, ideally, all of:

  1. Normal operation.
  2. One state transition or stop.
  3. One Bad-quality or comms-loss interval.
  4. A boundary crossing — hour, shift, or day.
  5. A counter reset or rollover, if the tag depends on counters.

Export the raw source samples and the calculated samples for that window and reproduce the result in a spreadsheet or twenty lines of Python. Nine times out of ten the disagreement is at the edges: the first sample of the interval, the last sample, or whether an interval is [start, end) or (start, end].

One caution on the export itself. If your retrieval mode is interpolated rather than raw, you are validating the historian's interpolation against the historian's aggregate, which proves nothing. Pull raw.

Counter resets are the most common single defect

Daily totals usually come from cumulative counters — kWh, m³, cycle count, kilograms. Those counters reset on PLC download, device replacement, power cycle, and rollover. A 16-bit Modbus register rolls at 65,535; a 32-bit DINT at 4,294,967,295; a mechanical-style meter register may roll at 999,999 regardless of what the data type allows.

If the rollup is last − first, one reset produces a large negative daily total, and one rollover produces a comically large one. A rollup you can trust distinguishes:

  • Normal positive movement.
  • Flat because the equipment is stopped.
  • Reset to zero.
  • Rollover at a known maximum (add the modulus).
  • A jump too large to be physical — cap it against the maximum flow rate times the interval, and discard.
  • A manual correction entered by operations.

Whatever the calculation throws away, log it. A WaterTotal_Discarded tag or a historian event costs nothing and is the only thing that will tell you, six months later, why March looks light.

The failure modes I keep seeing

Units taken from the display. The PLC tag is L/min, the HMI shows m³/h, the report assumes gallons. Put the unit in the tag name or the description; a tag called FIT201_Daily tells you nothing.

Averaging averages. A daily average built from 24 hourly averages is only correct if every hour had equal valid coverage. Once one hour is 40% Bad, the arithmetic mean of the hourly means is not the time-weighted daily mean. Roll up from raw, or carry the weights.

No recalculation after backfill. The raw trend gets repaired, the calculated tag does not, and the report stays wrong forever. Ask specifically whether your historian recalculates derived data on late arrival, or only on manual trigger — the answer varies by product and sometimes by tag configuration.

Engineering boundaries used for business questions. Compressor efficiency wants calendar hours. Production loss wants shift boundaries. Reusing the existing rollup because it exists is how downtime gets attributed to the wrong crew.

No owner for formula changes. A one-line expression edit silently changes years of reporting history if the historian recalculates, or creates a discontinuity if it does not. Put formula changes under change control with an effective date, the same way you would treat a PLC download.

Before you hand the tag to reporting

Formula, source tags, units and period documented in the tag description. Bad-quality behaviour tested by actually pulling a cable, not by reasoning about it. Rollup timestamp convention confirmed against what the report writer assumes. Backfill behaviour known. Counter reset tested if counters are involved. Hand calculation matched on a window with edges in it. And the name is one you are willing to live with, because renaming a tag that MES already queries is a change-control exercise, not an edit.

The test I would add if you only have time for one: change a source tag to Bad and see what the report shows tomorrow. Most sites discover their quality handling that way anyway — usually during an audit.