840D Measurement Logging: TRUNC Cuts, It Does Not Round

David Krause12 min read
Other TopicSiemensTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Each measurement record follows a defined path: transform the values, build the active-file name, write one record, and rotate the file when the counter reaches its limit. The critical corrections are that TRUNC truncates rather than rounds, the rotation copies rather than renames the active file, and every file operation must be accepted or rejected from its returned error code.

Retention Architecture

The R-parameter shift register and the file logger solve different retention problems. The R-parameter method provides an immediate view in the parameter table, while the file method preserves timestamped records for later analysis.

Method Stored information Retention behavior Primary use
R-parameter shift Measurement values only Every new value shifts older values by one register Quick inspection of recent parts
WRITE/READ/DELETE logger Date, time, X, Y, and Z Up to 100 active records, followed by a one-generation archive Traceability and external evaluation

The shown register chain places the newest value in R10:

R20=R19
R19=R18
...
R11=R10
R10=_OVR[4]

After the assignments execute in that order, each old value moves toward the higher register number. The value previously in R20 is discarded. One indexing detail matters: the inclusive range R10 through R20 contains 11 registers, although the stated objective is the last 10 measurements. An exact ten-value buffer using the same starting register would end at R19.

Check 1: Count the registers actually displayed and shifted. Expect ten storage locations for a ten-result buffer. If the program uses R10 through R20, decide whether the intended depth is 11 or revise the upper endpoint before evaluating the file logger.

Check 2 — Measurement Source and Value Transformation

The procedure declaration contains REAL parameters such as _VARI_PROT_01 and _VARI_PROT_02, but the visible logging statements do not use them. The recorded coordinates come directly from $P_UBFR[X,TR], $P_UBFR[Y,TR], and $P_UBFR[Z,TR]. Before reusing the routine for another measurement, trace the complete procedure and identify whether omitted logic uses the formal parameters. Changing only a call argument will not change the logged X, Y, or Z values in the shown statements.

ROUND_X=TRUNC($P_UBFR[X,TR]*1000)/1000
ROUND_Y=TRUNC($P_UBFR[Y,TR]*1000)/1000
ROUND_Z=TRUNC($P_UBFR[Z,TR]*1000)/1000

The term truncation here means removal of the fractional remainder after scaling. Multiplication by 1000 moves three decimal positions into the integer portion; TRUNC removes everything beyond that point; division by 1000 restores the scale. For a positive input of 0.1239, the derived result is 0.123, not 0.124. The variable names beginning with ROUND_ therefore describe an operation the code does not perform.

If nearest-value rounding is required, replace this expression with a rounding operation documented for the installed controller and test it at values immediately below, at, and above a half-step. Do not emulate rounding until negative-value behavior has also been specified; truncation and rounding can diverge differently on the negative side.

Check 2 reading: Inject or observe a value with more than three decimal places. Expect the stored value to lose all digits after the third decimal place without incrementing the third digit. If the fourth digit changes the third digit, another calculation outside the excerpt is acting on the value. If the process specification calls for nearest rounding, correct the transformation before proceeding to the file checks.

Check 3 — File-Name Construction

The << operator concatenates values into one string. In the shown routine, FIELD is assigned from TSA+1, converted to text during concatenation, and inserted between a fixed prefix and the fixed _MPF suffix:

FIELD=TSA+1
"/_N_WKS_DIR/_N_STRAT_PROTOCOL_WPD/_N_ACT_PROT_"
<<FIELD<<
"_MPF"

If FIELD evaluates to 2, the resulting active-file argument is:

/_N_WKS_DIR/_N_STRAT_PROTOCOL_WPD/_N_ACT_PROT_2_MPF

The archive path is formed in the same way, with _N_OLD_PROT_ replacing _N_ACT_PROT_. The counter remains indexed by TSA, while the filename uses TSA+1. That offset must match the machine's work-field convention; otherwise the counter for one field can govern a differently numbered file.

Check 3 reading: Record the live values of TSA and FIELD, then inspect the generated active filename. Expect the suffix to equal the textual value of TSA+1. If the active work field and filename disagree, correct the mapping before writing test records. If they agree, continue to the record-content check.

Check 4 — Record Construction and WRITE Results

The call has three functional parts: an error destination, a filename, and the string written to that file.

WRITE(
  ERROR[1],
  "/_N_WKS_DIR/_N_STRAT_PROTOCOL_WPD/_N_ACT_PROT_"<<FIELD<<"_MPF",
  "DATE:"<<$A_DAY<<"."<<$A_MONTH<<".0"<<$A_YEAR
  <<" TIME:"<<$A_HOUR<<":"<<$A_MINUTE<<":"<<$A_SECOND
  <<" X:"<<ROUND_X<<" Y:"<<ROUND_Y<<" Z:"<<ROUND_Z
)
Argument Role Required check
ERROR[1] INT destination for the operation result or error code Compare it with the success value and error definitions in the Siemens documentation for the installed system
Active-file expression NC-storage path assembled with FIELD Confirm the resolved field suffix and directory
Record expression Date, time, and transformed X/Y/Z values Confirm field labels, separators, and displayed values

The date expression contains the literal text .0 immediately before $A_YEAR. It does not dynamically select a four-digit year format. Read an actual record and verify the rendered year on every controller variant in scope, including the cited 840D powerline and 840D sl configurations with PCU50 or TCU display. Change the format only after observing what $A_YEAR contributes.

The record uses spaces and labels rather than a dedicated tabular delimiter. That is readable by an engineer, but downstream parsing must recognize tokens such as DATE:, TIME:, X:, Y:, and Z:. If spreadsheet import is a requirement, define the delimiter, decimal representation, header policy, and missing-value behavior before deploying a reusable cycle.

Check 4 reading: Execute one controlled write and inspect both ERROR[1] and the resulting record. Expect the documented success result, the intended date and time representation, and X/Y/Z values matching the truncation test. On an error, stop the sequence and decode the returned integer from the applicable Siemens command documentation. Do not increment the record counter after a failed write.

Check 5 — Counter Boundary and Rotation Trigger

The branch tests ST_DOCUCOUNT[TSA]<100. Under the labeled assumption that the counter starts at zero and every write succeeds, the normal branch writes records while the pre-write counter is 0 through 99, incrementing it after each write. The active file therefore reaches 100 records with the counter equal to 100. Rotation begins on the next procedure call, before that call's new measurement is written.

Pre-call counter Selected branch Operation Post-call counter
Less than 100 Normal Write current measurement, then increment Previous value plus one
100 or greater Rotation Replace the archive with 100 copied lines, recreate active storage with the current measurement 1

This is not a test for “more than 100 records.” It is a test of the stored counter before the current call. The distinction matters after restarts, manual file edits, deleted files, or failed writes because the counter and actual line count can diverge.

Check 5 reading: Immediately before a controlled boundary call, inspect ST_DOCUCOUNT[TSA] and count the active records. Expect both to represent 100 completed records. If the counter is 100 but the file has fewer lines, repair the state or derive the counter from verified file content. If the file has 100 records and the counter agrees, proceed to the rotation trace.

Check 6 — READ, WRITE, DELETE, and STOPRE Sequence

The rotation branch does not rename ACT to OLD. It deletes the existing archive, reads the active file line by line, writes each result into a new archive, deletes the active file, and then writes the current measurement into a new active file.

  1. DELETE(ERROR[2], ..._N_OLD_PROT_...) removes the previous archive from NC storage.
  2. STOPRE establishes a preprocessing boundary before the file-copy loop so execution does not depend on already preprocessed downstream blocks.
  3. The loop runs ZAEHLER=1 TO 100.
  4. READ(ERROR[3], active-file, ZAEHLER, 1, RESULT) reads the selected program line into the result container.
  5. WRITE(ERROR[4], old-file, <<RESULT[0]) writes that returned text to the archive.
  6. RESULT[0]="" clears the used result element before the next iteration.
  7. DELETE(ERROR[5], active-file) removes the copied active file.
  8. ST_DOCUCOUNT[TSA]=1 declares that the new active generation contains one record.
  9. The final WRITE stores the current measurement in the active file.

The fixed 1 argument in the READ call is part of the command signature, but its precise interpretation must be taken from the Siemens work-preparation documentation matching the installed control. The actionable line selector is ZAEHLER, which advances from 1 through 100, and the copied text is taken from RESULT[0].

Check 6 reading: At the boundary, trace all four error destinations: ERROR[2] for archive deletion, ERROR[3] for every read, ERROR[4] for every archive write, and ERROR[5] for active deletion. Expect the documented success result at every stage, 100 records in the archive, and one current record in the recreated active file. A failed intermediate operation must branch to fault handling rather than continue destructively.

Check 7 — Error Handling and Data Integrity

The calls capture error codes but the visible routine never evaluates them. Capturing an error is not handling it. In the normal branch, ST_DOCUCOUNT[TSA] increments even when WRITE fails. During rotation, the prior archive is deleted before the new archive has been fully copied, and the active file is deleted without a visible test proving all 100 reads and writes succeeded.

Failure point Result if execution continues Required decision
Normal active WRITE Counter can exceed the actual record count Increment only after a confirmed successful write
Old-file DELETE Archive state is unknown before copying begins Accept only the documented success condition, including the defined treatment of a missing target
Active-file READ RESULT[0] may not contain the requested record Do not write or clear it as a valid record after a failed read
Old-file WRITE The archive becomes incomplete Abort rotation and retain the active source
Active-file DELETE Two generations or an unexpected active state can remain Report the error and reconcile files before resetting the counter
Final active WRITE Counter is set to one although no current record may exist Set the counter only after successful creation of the first record

The safer state transition is copy, verify, then retire the source. The shown order first deletes the only prior archive, so a copy failure leaves less historical coverage. If the command set permits a temporary destination within the applicable storage rules, build and verify that destination before replacing the archive. Where that mechanism is unavailable, preserve the active file whenever any copy operation fails and expose the first error code to the operator or diagnostic log.

Check 7 reading: Force or safely reproduce a non-success file operation during commissioning. Expect the counter to remain aligned with successfully stored records and the active source to remain available after a failed rotation copy. If execution still deletes the source or advances the counter, add explicit branches around each operation before production use.

Logging Load and Export Format

Every WRITE consumes execution time, and rotation adds one deletion, 100 reads, 100 archive writes, another deletion, and a final write. No fixed duration can be assigned without measuring the specific 840D configuration and storage state. Place logging where its measured delay cannot violate the machine sequence, measurement handshake, or part-transfer timing.

Measure both paths separately: an ordinary one-record write and the 100-record rotation. The rotation call is the worst case in the shown design. If that delay is unacceptable, reduce synchronous file work, log at a less time-sensitive point, or keep the R-parameter buffer for live inspection and perform file export outside the critical motion sequence.

A reusable logging cycle needs a stable record contract. Define the measurement source, units, truncation or rounding policy, field order, delimiter, timestamp representation, retention depth, field-to-file mapping, and response to storage errors. Values without units or an invariant column order can be displayed but cannot be reliably compared across programs.

Check 8 reading: Measure cycle behavior once on the normal branch and once at rotation. Expect both paths to remain within the process timing allowance established for the machine. Import the resulting records into the intended analysis tool and expect each label or column to map without manual repair. If timing or parsing fails, revise the logger contract and repeat the check.

Resolving Procedure and Acceptance Checks

  1. Choose the retention objective. Use exactly ten R parameters for a ten-result live window; use the file logger when timestamps and historical export are required.
  2. Replace or relabel the TRUNC(...*1000)/1000 expressions according to the measurement specification. Keep truncation only when cutting to three decimal places is intentional.
  3. Bind the desired measurements to the written fields. Confirm whether the procedure's REAL arguments are required elsewhere; the visible X/Y/Z records currently use $P_UBFR values.
  4. Verify that TSA, FIELD=TSA+1, ST_DOCUCOUNT[TSA], and the resolved filename all refer to the same active work field.
  5. Define the timestamp and export format from an actual controller record, including the result of the literal .0 before $A_YEAR.
  6. Evaluate every ERROR[] result immediately. Advance counters, delete source files, and reset rotation state only after documented success results.
  7. At a controlled boundary, confirm that 100 active records are copied to the archive and that the triggering measurement becomes record one in the new active generation.
  8. Measure normal-write and rotation execution times on each relevant controller configuration. Accept the implementation only when the worst case fits the machine timing allowance.

Verification 1: Write a positive test value containing more than three decimal places. Expect truncation to three places, or the specified nearest value after an approved rounding change.

Verification 2: Switch or simulate each work field. Expect the active filename suffix to equal TSA+1 and its counter to remain isolated at ST_DOCUCOUNT[TSA].

Verification 3: Complete 100 successful records. Expect the active line count and counter to agree at 100 before the next call.

Verification 4: Execute the next call. Expect the archive to contain the preceding 100 records in order and the active file to contain only the current record, with the counter equal to 1.

Verification 5: Exercise each error branch. Expect no counter increment after a failed active write, no deletion of the active source after an incomplete copy, and a diagnostic containing the exact returned error code.

FAQ

How do I keep exactly the last 10 measurements in 840D R parameters?

Use ten inclusive registers, such as R10 through R19, shift from the highest register downward, and load the newest value into R10. The shown R10-through-R20 range actually provides 11 locations.

How do I make TRUNC round an 840D measurement?

TRUNC(value*1000)/1000 does not round; it cuts the value to three decimal places. Use a controller-supported rounding operation documented for the installed system, then test positive and negative values around a half-step.

How do I decode WRITE, READ, and DELETE arguments?

WRITE receives an error destination, a file expression, and a text expression; DELETE receives an error destination and file expression. The shown READ selects lines 1 through 100 with ZAEHLER and returns copied text in RESULT[0]; verify the fixed argument's definition in the matching Siemens work-preparation documentation.

How do I verify the 100-record rotation?

Start with 100 confirmed active records and ST_DOCUCOUNT[TSA]=100, then execute one more logging call. The final check must show 100 prior records in OLD, one current record in ACT, a counter value of 1, and documented success results in every used ERROR[] element.

Back to blog