Twenty bytes went out and a handful of letters came back. Nothing corrupted anything. FILEWRITE moved the bytes it was pointed at, verbatim, and the text viewer on the PC did its best with a block of IEEE-754 floating point.
Work the checks below in order. Each one tells you what to read and which branch you land on.
Dump the File in Hex Before You Change Anything
Upload the file with PLC -> Browse PLC File System and open it in a hex editor, not Notepad. Five reals at four bytes each is exactly 20 bytes on disk. Decode them as IEEE-754 single precision:
| Value in block | IEEE-754 single | What a text viewer shows |
|---|---|---|
| 10.0 | 41 20 00 00 |
A, space, two invisible nulls |
| 20.0 | 41 A0 00 00 |
A, unprintable box |
| 30.0 | 41 F0 00 00 |
A, unprintable box |
| 40.0 | 42 20 00 00 |
B, space |
| 50.0 | 42 48 00 00 |
B, H
|
Only the sign/exponent bytes land in printable ASCII, which is why you got a run of A, B, H, spaces and boxes. The pairs above are written most-significant-byte first; if your dump reads 00 00 20 41 instead, the file is little-endian. Either way the two zero bytes render as nothing, so only the letters surface.
- File is 4 x N bytes and decodes as IEEE-754 → the write instruction worked. Your problem is the encoding you chose. Go to the format decision.
- File length is wrong or the values do not decode → recheck the start element of the numeric data block (
PTX0) and the byte count, and confirm the block is really reals and not 16-bit integers.
Skip These Quick Fixes
Every one of these gets tried on the first night and none of them changes a byte of the output.
- Raising the byte count. Forty bytes of binary instead of twenty. Same problem, twice as long.
- Renaming the file to .CSV. The PLC has no concept of file types. The extension only tells Windows which application to launch, and Excel will happily open binary and show you one column of rubbish.
- Hunting the FILEOPEN and FILEWRITE dialogs for a format selector. There isn't one. Format is whatever your ladder emits, byte by byte.
- Assuming the FILELOG file layout is what your source tool produces. A CAD export or a spreadsheet save follows its own rules. Get a real sample file before you write parsing logic.
| Symptom | Cause | Next check |
|---|---|---|
| Few letters and boxes; file size is exactly 4 x number of reals | Raw memory image of IEEE-754 values | Rebuild the record as text |
| Excel opens it, everything in one cell | .CSV extension applied to binary content | STRPRINT the record first |
| Last record trips the error branch, all others parse | Trailing blank line or a stray terminator byte | Route empty reads to the close stage |
| Fields separated by semicolons | Windows list separator set by locale | Parse the delimiter that is actually in the file |
| Second value on every line reads 0.0 | Substring index never advanced past the comma | INC the stop index, then STRSUB |
Decide Who Owns the Format
This is the branch that decides all the code below it. Ask what produces the file and what consumes it.
- Raw bytes. Most compact, unreadable in an editor, and both ends must agree on IEEE-754 layout and byte order. No delimiters means one dropped byte shifts every value after it. Only worth it when the same controller writes and reads and size genuinely matters.
- Text with delimiters. Commas or spaces between elements, CR/LF terminating each record. Human readable, hand-editable, opens in Excel, survives a co-worker looking at it. This is the right call if you are not fluent in IEEE-754 and endianness.
For 50 XY pairs, compactness is a non-argument: 50 records of roughly 20 characters is about 1 KB. Take the text path. If a third-party tool generates the file, open its output in a hex editor first and note the delimiter, the quoting, the decimal separator and the line endings. You are writing the read side against that file, not against a spec you invented.
Write the Record With STRPRINT, Then FILEWRITE
Build the line as a string, then ship the string. One record per FILEWRITE.
FILEOPEN
STRPRINT SL0 "10.0, 20.0, 1$0D$0A"
FILEWRITE SL0
STRPRINT SL0 "30.0, 40.0, 2$0D$0A"
FILEWRITE SL0
FILECLOSE
-
FILEOPENthe target file, with the error branch wired before you write anything. -
STRPRINTthe record intoSL0, including the separators and the$0D$0Aterminator. -
FILEWRITE SL0. - Loop steps 2 and 3 over your table.
-
FILECLOSE.
With live data you embed the real registers in the STRPRINT format string instead of literals. Check the numeric field specifiers in the instruction help and set width and decimal places deliberately, or 123.456 gets rounded on its way to disk and your fine-tuned probe position comes back short.
Give the file a .CSV extension so the upload double-clicks straight into Excel. .TXT works identically as far as the PLC is concerned.
The index column decision. A leading step number looks helpful and is a maintenance trap:
- Delete a row in Excel and every index below it needs renumbering. Swap two rows and two indices swap. By hand, that is a guaranteed failure eventually; by macro, it is a second program to maintain.
- If the number is documentation rather than true random access, put it last in the record so the read side can ignore everything past the second field.
- Default: leave it out. Row order is the index. Add it later, to both sides, only if it pays for itself.
Parse the Read Side One Record at a Time
Read a line, convert the first number, step past the delimiter, convert the second, store, repeat. A stage program keeps the error paths honest because each stage has exactly one job and one exit.
PROGRAM ReadRecords
SG S0
reset table index to 0
FILEOPEN OnSuccess -> S1 OnError -> S99
SG S1
FILEREAD terminate on CR/LF into SL0
OnSuccess -> S2 OnError -> S10
SG S2
STR2REAL SL0 -> R0, stop index -> D0
INC D0 // step past the comma
STRSUB SL0 -> SL1 starting at D0
STR2REAL SL1 -> R1
move R0, R1 into table @ table index
increment table index
JMP S1
SG S10
FILECLOSE // no more records
EXIT
SG S99
SET Y99 // bad-file alarm
EXIT
Three things break this loop in the field:
-
The space after the comma.
D0stops on the delimiter; incrementing once clears the comma but not a following blank. IfSTR2REALonSL1returns 0.0 on every line, advance past the whitespace or write the file without it. - The terminator left in the string. Depending on how the read terminates, a trailing CR or LF can ride along on the last field. Trim it before the final conversion.
-
The blank last line. Excel ends the final row with CR/LF, so most parsers see one empty record at the end. Treat a zero-length read as end of file and branch to
S10, not to the alarm.
The read error branch doing double duty as end-of-file is deliberate. Bound the loop anyway: if the table index exceeds 50, jump to S10 and set the alarm, so a runaway file cannot walk past the end of your data block.
Write Jogged Positions Back Without Wrecking the File
Patching one line in place only works when every record occupies the same number of bytes. If you want that, pad every number to a fixed width in STRPRINT so a row number multiplies cleanly into a byte offset. Otherwise, rewrite the whole file: write all 50 records from the table to a new file name, close it, then swap names. A power loss halfway through an in-place rewrite leaves you with half a recipe and no way to tell.
Keep the table in retentive memory as the master copy and write the file on an operator command, not on every jog increment. The controller's file system is flash, and a jog wheel generates a lot of transitions.
Verify Before You Hand It Back
- Upload the written file and hex-dump it. Expect at each separator, ending every record, and no anywhere.
- Double-click the
.CSV. Values land in separate columns with decimals intact, not as text. - Round trip: run
ReadRecordsand compare element 0, one middle row, and the last row against the spreadsheet. - Break it on purpose. Add a blank last line, a row with one field, a row with text where X belongs. The alarm branch must fire and the file must still get closed.
- Confirm
FILECLOSEruns on both the success and the error path. A file left open by a faulted stage blocks the nextFILEOPEN, and the symptom looks nothing like the cause.
Stop Here and Call Support
Stop when the hex dump shows exactly the bytes you intended and the parse still faults, or when FILEOPEN returns an error code you cannot clear after a power cycle and a file system check. At that point you are looking at a controller or firmware issue, not a logic issue, and another pass at the string handling costs you the rest of the shift. Package the uploaded file, the error code and the project, and raise it with AutomationDirect technical support.
FAQ
Why does FILEWRITE output letters and symbols instead of my real numbers?
Because it wrote the raw memory image of the block. Each real is four bytes of IEEE-754 binary; 10.0 is 41 20 00 00, which a text viewer shows as A, a space and two invisible nulls. Build the record with STRPRINT and write the string if you want readable numbers.
Why does Excel show my PLC file as one column of gibberish even with a .CSV extension?
The extension only chooses which application Windows launches. The controller has no concept of file types, so the content is still binary. Renaming a raw dump to .CSV changes nothing about the bytes.
Why does the first value of my CSV read back as zero in Do-more?
EF BB BF) that STR2REAL cannot digest. Re-save as CSV (Comma delimited) or skip the first three bytes on record 1.
How do I read two columns of reals into a data block?
FILEREAD one record terminated on CR/LF into SL0, run STR2REAL into R0 saving the stop index in D0, INC D0 to clear the comma, STRSUB into SL1, then STR2REAL into R1. Move R0 and R1 into the table at the current index, increment it, and loop until the read returns an error.