Log the PLC's packed I/O status word, such as the 16 inputs at V40400, to a USB stick as one decimal number on a 2-second time base. Decode each timestamped sample into its 16 on or off states in a spreadsheet with MOD(INT(B2/2^C1),2). One trend pen records 16 points, the CSV stays small, and the PLC program is never edited.
When an unattended machine misbehaves, the record you want is which inputs and outputs were on, and when. You can capture that without editing the PLC program. Trend the controller's packed I/O status word to a USB stick as one decimal number on a time base, then split each number back into its 16 bits in a spreadsheet. One trend pen carries 16 discrete points, the CSV holds only a timestamp and a number per row, and the whole decode is one formula copied across 16 columns. This page sets up the log, gives the toggle test that catches BCD-coded registers early, works one sample through the arithmetic, and ends with the sampling interval to start at.
What you need
- An HMI panel that trends numeric registers and logs the samples to USB on a time base. The panel reads the word over its normal PLC protocol, so nothing is added to the controller and the machine logic stays as it is.
- The address of the I/O status word. Discrete input and output channels live as individual bits in the PLC's data memory, and the controller's memory map names the register that holds them. On the machine this method was set up for, the 16 inputs X0 through X17 sit in V40400, with V40500 carrying more inputs beside it. Those two addresses come from that machine's map, so read your own map before trending anything.
- The bit-to-point list: bit 0 to X0, bit 1 to X1, and so on to bit 15. Where the point labels run in octal, they go X0 to X7 and then X10 to X17, which still fills bits 0 to 15 with 16 points.
- A PC with a spreadsheet for the decode.
- If the program copies its physical I/O into mapped internal registers, a common practice that decouples the logic from the wiring, trend those mapped registers and take the addresses from the program's I/O map.
Set up the USB log
- Find the word. Open the controller's I/O map or watch candidate registers online while the machine runs. The input image and the output image sit in different registers; give each its own trend pen.
- Test the encoding before trusting anything. Start a short capture, switch exactly one known point on, and read the logged value. A raw binary word steps by 2 to the power of the point's bit position: point 0 adds 1, point 5 adds 32, point 9 adds 512. A value that moves in decimal steps, 1 then 10 then 100, is BCD-coded; convert it before any bit decoding (see the FAQ below).
- Add the register as a single trend pen and set the sampling to a time base. Start at 2 seconds.
- Point the trend's data log at the USB stick and capture a few minutes of normal running.
- Pull the stick and open the CSV. The right shape is one column of date and time stamps and one column of decimal values, nothing else.
Check the log before you rely on it
With the log running, toggle a point whose bit position you know, then stop the capture and inspect the file. The value should step by the matching power of two: if the word reads 8741 and you switch on the point at bit 6, the next sample reads 8805, because 8741 plus 64 is 8805. A file that fails this step holds the wrong register or BCD data, and both are cheap to fix now and expensive to meet during a fault review.
Size the capture from the interval: one sample every 2 seconds grows one word by 1,800 rows per hour, 43,200 rows per day. Give each word its own trend chart; pasting one chart per word into the spreadsheet keeps the columns aligned. One chart carrying several words saves disk space if you prefer a single file per shift.
For a capture spanning days, check how the panel splits its files first; the way an HMI trend log file rolls over at midnight on USB is the kind of behavior worth knowing before you leave a capture unattended.
Decode every sample into 16 on or off states
Lay the sheet out with the bit numbers 0 to 15 in the header row and the samples in column B from row 2 down. In cell C2 enter:
MOD(INT(B2/2^C1),2)
Read it in words: divide the word by 2 to the power of the bit number, INT drops the fraction, and MOD by 2 leaves the bit, because every higher bit contributes an even number at that scale. Make B2 and C1 absolute references when you copy, then fill the cell across 16 columns and down every row. Color 1 and 0 differently, label each column with the physical point from your map, and keep the timestamp column beside them so every state change carries its time.
Three notes from real installs:
- To watch the same bits live while the log runs, displaying 16 PLC input and output bits on one screen covers the screen side of the same word.
- For more points than one word holds, log two consecutive registers as one unsigned 32-bit value and decode bits 0 to 31; one machine logged V40400 and V40500 that way to cover all 20 of its inputs. Before combining, confirm which register supplies the low 16 bits.
- Many spreadsheets also offer a DEC2BIN function that converts the whole word to a binary string in one call; your spreadsheet's documentation lists its arguments. The MOD and INT formula still suits this job better, because it fills all 16 columns in one drag and skips string splitting.
Worked example: one 2-second sample of the 16-input word
The inputs: register V40400, 16 input points, taken from the machine's I/O map; the example's bit map names bit 9 the part-present sensor and bit 15 the guard switch. The panel samples on a 2-second time base and logs decimal values to USB. At 10:14:02 the file shows 8741. The question: which of the 16 inputs were on at that stamp?
The rule: bit n of a nonnegative whole number equals MOD(INT(value/2^n),2).
The arithmetic, for the five bits that come out high and two checks that come out low:
- bit 0: 8741 / 1 = 8741; MOD 8741 by 2 = 1, so X0 is on
- bit 2: 8741 / 4 = 2185.25; INT gives 2185; MOD 2185 by 2 = 1, so X2 is on
- bit 5: 8741 / 32 = 273.16; INT gives 273; MOD 273 by 2 = 1, so X5 is on
- bit 9: 8741 / 512 = 17.07; INT gives 17; MOD 17 by 2 = 1, so X11 is on (bit 8 is X10, because the labels run in octal)
- bit 13: 8741 / 8192 = 1.07; INT gives 1; MOD 1 by 2 = 1, so X15 is on
- bit 1: 8741 / 2 = 4370.5; INT gives 4370; MOD 4370 by 2 = 0, so X1 is off
- bit 3: 8741 / 8 = 1092.63; INT gives 1092; MOD 1092 by 2 = 0, so X3 is off
The cross-check: 8192 + 512 + 32 + 4 + 1 = 8741, so the set bits are exactly 13, 9, 5, 2 and 0, written 0010 0010 0100 0101.
The result: five inputs on, X0, X2, X5, X11 and X15; the other eleven off.
The decision: at 10:14:02 those five conditions were true and no others. Read one row back at 10:14:00 and one forward at 10:14:04; any input that differs across those rows changed inside the 2-second window, which is as tight as this interval can place a change. If the machine stopped at 10:14:03, the word says the part-present sensor at X11 was still made and the guard switch at X15 still closed at the last sample before the stop, so the search moves to the output word and the rows after it.
Pick the sampling interval
Start at 2 seconds and shorten to 1 second once you know the shortest event you need to see; the install that used this method ran between those two values. The interval must be shorter than the shortest transition you intend to diagnose: a change that lasts less than one interval can open and close between two samples and leave no row behind. Before a capture matters, trigger one pulse of known length at the machine's fastest and check that its rows appear.
The cost follows the interval directly: 1 second gives 86,400 rows per day per word, 2 seconds gives 43,200, 5 seconds gives 17,280. Trend slow signals at 10 seconds and tighten only around the event you are chasing.
When the panel cannot see a status word
Some controllers keep their I/O image in registers outside the panel's address range, or the map is unknown. Two routes remain, in this order.
Trend a surrogate value per point. One small rung per point writes a high value into a register when the point is on and a low value when it is off. The original install wrote 80 for on and 20 for off and trended the register on a 0 to 100 range, which draws a clean square wave on the chart. This costs a PLC edit, so schedule it in a controlled window with the program backed up, and run the toggle test on the new register before trusting it.
Use the panel's event machinery. Tag events on transitions can stamp each change without touching the ladder; counting discrete input events on an HMI without PLC edits walks through that route, which trades a bigger file for one record per change.
If the map is unknown and access is unsafe, stop there. A guessed address produces a confident-looking file full of wrong bits.
Recommendation: log each 16-point I/O word as one unsigned decimal sample on a 2-second time base to USB, decode it with MOD(INT(B2/2^C1),2) across 16 columns, and drop to 1 second once you know your shortest event runs about 1 second; keep the surrogate rungs for points the panel has no address for, and never trust an address the toggle test has failed.
Questions
How do I tell a binary word from a BCD-coded one?
Toggle one known point and read the logged value. A raw binary word steps by a power of two matching the bit position: 1 for bit 0, 32 for bit 5, 512 for bit 9. A BCD-coded register moves in decimal digit weights instead, so the value reads as tidy decimal digits. One install captured two words as BCD and had to convert each 4-bit digit group before any bit decoding made sense. Where the panel offers a choice, log the register as an unsigned integer and the problem disappears.
How much USB stick does this consume?
One word at one sample every 2 seconds produces 43,200 rows a day, and a two-column row of timestamp plus decimal value runs roughly 25 bytes, so about 1 MB a day per word. Even with four words logged the stick sees about 4 MB a day, which even a small stick holds for years. Widen the interval or stop the log while the machine sits idle if you want more headroom.
Why is a fast pulse missing from the log?
A pulse shorter than the sampling interval can open and close entirely between two samples, so it never lands in the file. Cut the interval to 1 second, then verify the fix by triggering a pulse of known length and checking that its row appears. For points whose shortest pulse is still below the interval, move those points to transition-based event records, which write one row per change and miss nothing the panel's own tag scan can see.
Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.