PLC data converter
Registers to values and back for INT16 to INT64, FLOAT32, FLOAT64, BCD and strings in every byte and word order (ABCD, CDAB, BADC, DCBA), with bit fields, the IEEE 754 breakdown and a batch mode. It only converts numbers you type or paste; it does not connect to any device.
Registers
Decimal (16840, −1), hex (0x41C8, 41C8h, 16#41C8) or binary (0b…); a longer hex number is split into registers as written (0x41C80000). An address before “:” or “=” is skipped (40001: 16840). More registers than one value needs give several values.
Runs in this browser. Data is not uploaded or stored.
Value in every order
The tool does not pick an order for you: compare with one value you know (a setpoint, a temperature on the display). Notes only mark values that are seldom real readings: NaN, infinity, subnormal, negative zero, |x| ≥ 1e9 or below 1e-6, invalid BCD digits.
Value
Numbers with a decimal point or comma, an exponent (1.5e-3), NaN or Infinity. Integers must fit the type. A bit pattern can be typed as 0x… or 0b… (0x41C80000 for FLOAT32, 0xFFFF for INT16 = −1). Text uses the encoding above; it is padded to the register count with NUL bytes or spaces.
Runs in this browser. Data is not uploaded or stored.
Registers in every order
Bits
One field per line, columns separated by “;” or tabs (from Excel). Bit 0 is the least significant bit of the value. Types: flag (1 bit), unsigned, signed (two’s complement), enum with names as 0=Off, 1=Manual. Length defaults to 1 bit. A first line with names (Name;Start…) is skipped.
Runs in this browser. Data is not uploaded or stored.
Bits of the value
Register sets
CSV, TSV or TXT up to 20 MB, opened or dropped on the field; read in this browser only. Excel: copy the cells and paste them.
Cells are split at tabs, “;” or “,” (else at spaces). A first line without registers is a header. Use “Always the first column” when the label is a number (a row number, a time in seconds). A line with several values’ worth of registers gives several values.
Runs in this browser. Data is not uploaded or stored.
Batch results
How the registers are converted
PLCs and field devices exchange numbers as 16-bit registers. A 32-bit or 64-bit value, a float or a text spans several registers, and devices disagree on the order of the words and of the bytes inside them. The converter shows every order side by side, so the right one can be recognised from a value you know. It does not connect to any device.
Byte and word orders
- The bytes of the value are named A, B, C … from the most significant one. An order lists them as they arrive: register 0 high byte, register 0 low byte, register 1 high byte … Each register is read high byte first, as Modbus sends it.
- 32 bits (2 registers): ABCD big-endian, high word first; CDAB word swap, low word first (also called “Modicon” order); BADC byte swap, high word first with the bytes of each register swapped; DCBA little-endian.
- 64 bits (4 registers), the same four families: ABCDEFGH big-endian; GHEFCDAB word swap (the four registers in reverse order); BADCFEHG byte swap; HGFEDCBA little-endian.
- 16 bits and STRING: AB (high byte first) or BA (bytes swapped in each register); the registers of a text are always in their own order.
- Names vary between vendors and tools (“swapped”, “Motorola”, “Intel”, “float inverse”); the letters are unambiguous. The tool never picks an order for you.
Data types
- INT16 / UINT16, INT32 / UINT32, INT64 / UINT64: two’s complement for the signed ones (INT32 = r0 × 65536 + r1 in ABCD, minus 2³² when that is 2³¹ or more). 64-bit integers are exact (BigInt): INT64 −9223372036854775808 … 9223372036854775807, UINT64 up to 18446744073709551615.
- FLOAT32 / FLOAT64: IEEE 754 binary32 and binary64. Value = (−1)^sign × 1.fraction × 2^(exponent − 127) for FLOAT32 (1023 and 52 fraction bits for FLOAT64). Exponent field 0: zero or a subnormal number, (−1)^sign × 0.fraction × 2^−126. All exponent bits set: infinity (fraction 0) or NaN, quiet when the top fraction bit is set, signalling otherwise; the rest of the fraction is the payload, shown as it is.
- BCD16 / BCD32: packed BCD, one decimal digit per 4 bits (0x1234 = 1234). A nibble A–F is not a BCD digit and is flagged; the tool does not read a sign nibble (some PLCs use one).
- STRING: two characters per register, Latin-1 (every byte is one character), ASCII (bytes above 127 flagged) or UTF-8 (invalid sequences shown as �). NUL bytes: stop at the first (C strings), drop the trailing ones, or keep all. Control characters are shown as \xNN, NUL as \0. Writing a text pads it to the register count with NUL bytes or spaces (an odd length always gets one).
Exact floats
- Value → registers rounds the typed decimal to the nearest float, ties to even, in one step from the exact decimal (integer arithmetic). Converting through a double first can round twice and give the neighbouring FLOAT32; the tool does not do that. A value that would round to infinity is refused as out of range; one below the smallest subnormal is stored as 0 with a note.
- The shortest decimal that reads back to the same float is shown as the value (0.1, 25, 3.4028235e+38); of several equally short ones the nearest, ties to even. The exact value of every float is a finite decimal and is shown in full (the table cuts very long ones; the CSV and the Bits part have them complete). The rounding error is stored − typed, exactly.
- Plausibility notes are neutral: NaN, infinity, subnormal, negative zero, |x| ≥ 1e9 and 0 < |x| < 1e-6. A real value can be any of these; they only help to rule out an order.
Bits and bit fields
- Bit 0 is the least significant bit of the value, bit 31 (or 15, 63) the most significant. Under every bit the register and bit that carry it are written register.bit (with a first address: 40001.3), which depends on the order: in ABCD value bit 0 is bit 0 of the second register, in BADC it is bit 8 of the second.
- Bit fields: start bit, length, type flag (1 bit), unsigned, signed (two’s complement over the field’s length) or enum with names. Field = (value shifted right by the start bit) AND (2^length − 1).
- For 32 and 64 bits the same bits are also split as an IEEE 754 float: sign, exponent field and unbiased exponent, fraction field, significand, class, shortest and exact value.
Worked examples (the tool’s examples)
- Registers 0x41C8 0x0000 as FLOAT32, ABCD: bits 0 10000011 10010000…0, so sign +, exponent 131 − 127 = 4, significand 1.5625, value 1.5625 × 2⁴ = 25. In CDAB the same registers are 0x000041C8, the subnormal 2.3598e-41; a device that sends 0x0000 0x41C8 uses CDAB.
- INT32 −123456 is 2³² − 123456 = 4294843840 = 0xFFFE1DC0: registers 65534 7616 in ABCD, 7616 65534 in CDAB.
- 0.1 as FLOAT32 is 0x3DCCCCCD (registers 0x3DCC 0xCCCD in ABCD), exactly 0.100000001490116119384765625: the rounding error is +1.490116119384765625e-9. As FLOAT64 it is 0x3FB999999999999A, exactly 0.1000000000000000055511151231257827021181583404541015625.
- BCD16 0x1234 = 1234 (read with swapped bytes, BA, it is 3412); 0x12F4 is not BCD: digit 3 is F.
- STRING “FactoKit” in Latin-1: F = 0x46, a = 0x61 …, so the registers are 0x4661 0x6374 0x6F4B 0x6974 in order AB.
- The status word 0x00FB 0x9623 (ABCD, an illustrative example): bits 0 and 1 set (Ready, Running), bit 3 clear (no Fault), bits 4–6 = 010 = 2 (Mode Auto), bits 8–15 = 0x96 = 150 (Speed step), bits 16–23 = 0xFB = −5 as a signed 8-bit field (Temperature offset).
- The batch example decodes seven FLOAT32 tags sent low word first (CDAB): TT-101 25, TT-102 25.4 (stored 25.3999996185302734375), LT-401 NaN with a note, TT-103 −20.6.
Common mistakes
- Mixing up register numbers and addresses: 40001 is the first holding register, address 0 on the wire. The tool skips an address written before “:” or “=”, but it cannot tell which register is the first of a value: start at the right one.
- Reading a FLOAT32 as two INT16 values and scaling them: the two halves of a float mean nothing on their own.
- Trusting one order because the value “looks plausible”: check with a value you know, and keep the result (the settings JSON stores the order).
- Comparing floats for equality after a round trip through a different precision: 0.1 typed as FLOAT32 does not equal 0.1 as FLOAT64.
Input and files
- Registers: decimal (−32768 … 65535), hex (0x41C8, 41C8h, 16#41C8, or plain digits with “Hex”), binary (0b…, 2#…), separated by spaces, commas, semicolons, tabs or new lines; a longer hex or binary number is split into registers as written.
- Batch: CSV, TSV or TXT files (UTF-8, UTF-16 or Windows-1257) up to 20 MB are read in this browser only. Excel workbooks are not opened here: copy the cells and paste them. Up to 500 lines are shown on the page; the CSV holds all.
- Results CSV (UTF-8, “;” between columns with a decimal comma) and settings JSON for every part; nothing is stored by this file.
Questions
- Why do I get 2.3598e-41 instead of 25 from my two registers?
- The registers are read in the wrong word order. 25.0 as a FLOAT32 is 0x41C80000: a device that sends the high word first gives 0x41C8 0x0000 (ABCD), one that sends the low word first gives 0x0000 0x41C8 (CDAB). Read in the other order the same registers become a tiny subnormal number or a large one. The table shows every order at once; pick the one that gives a value you know.
- Which byte order does Modbus use?
- The Modbus protocol sends each 16-bit register with its high byte first (big-endian). It does not say how a 32-bit or 64-bit value is split over several registers, so devices differ: high word first (ABCD) and low word first (CDAB) are the most common, byte-swapped orders occur too. The device manual should say; otherwise compare with a known value.
- Why is 0.1 stored as 0.100000001490116…?
- A FLOAT32 has 24 significant bits, and 0.1 has no finite binary expansion, so the nearest FLOAT32 is stored: 0x3DCCCCCD, exactly 0.100000001490116119384765625. The tool shows the exact stored value and the rounding error. A FLOAT64 is closer (0.1000000000000000055511151231257827…) but still not exact.
- What does a NaN or an infinity in a register mean?
- They are valid IEEE 754 bit patterns: all exponent bits set. Devices use NaN for a missing or failed measurement, and a wrong word order can produce one by accident. The tool marks NaN (quiet or signalling, with its payload), infinity, subnormal numbers and very large or very small values as notes; it never decides which order is right.
- Does the converter connect to my PLC?
- No. It only converts the numbers you type or paste, for example from a Modbus poll tool, a PLC watch table or a log file. Nothing is sent anywhere and no device is read or written; the offline file works without a network.