Split 32-bit register bits into discrete HMI alarm tags

8 min read · Published November 12, 2026

A packed 32-bit alarm register becomes twelve discrete tags when each tag points at the same register and selects its own bit number. Prove one tag in a minimal project first, match the function code to the register class when a discrete read returns 0x0002, and verify every bit against the PLC word before the alarms go on screen.

A 32-bit alarm register turns into twelve independent alarm messages when each bit gets its own discrete tag, all twelve tags point at the same register number, and each tag selects its own bit position. Keep the unsigned 32-bit integer tag you already read for the number display and add the discrete tags beside it. Two faults break this in practice: a discrete read on the wrong function code for the register class, which comes back as Modbus exception 0x0002, and a discrete tag with no bit selection, which follows the whole word instead of one bit. This article gives the order to find both, a minimal project that proves one bit end to end, and the mapping for bits 0 through 11.

What a packed alarm word is

The PLC packs status and alarm flags into single words to save address space. The worst case here packs twelve flags into bits 0 through 11 of one 32-bit unsigned holding register. On the wire a 32-bit value occupies two consecutive 16-bit registers, and the server answers each half as an ordinary register read. Bit 0 is the least significant bit and equals 1; bit 11 equals 2048. The integer tag on your screen shows that packed number, so a register value of 3 means the flags in bits 0 and 1 are both on, not one flag at strength 3.

Symptoms and what each points to

  • The integer tag reads the register and the discrete tag on the same address returns 0x0002. Exception 02 is the illegal data address code in the Modbus specification: the request arrived, but the server holds no register at that address for the function you used. FC03 reads holding registers and FC04 reads input registers, and a server can expose an address under one function only. Match the function code to the register class in the PLC map.
  • The discrete tag turns on for every nonzero value. The tag has no bit selection, so it sees zero versus nonzero. Values 1, 2 and 2048 all look identical to it.
  • The wrong alarm shows, or two alarms swap. Check bit numbering first: bit 0 equals 1 and is the first bit, so a dialog that counts from 1 puts every tag one bit high. On a 32-bit value the two 16-bit halves can also sit in the opposite order from the PLC's packing, which moves every bit above 15.
  • A small test project reads fine and the full project returns 0x0002. A tag added since conflicts with this read. Isolate it by adding tags back in small groups until the error returns, then inspect the last group's addresses and register classes.

Check the register class and the word on screen

Open the PLC register map and write down three things for the alarm register: the class, the width and the address. The class sets the function code. Holding registers are the general-purpose area and take reads and writes; input registers are read-only process inputs, and Modbus permits no writes to them. FC03 goes with holding registers and FC04 with input registers. A leading 4 in an address commonly means holding registers, but prefix rules differ between drivers, so take the class from the PLC map and check the driver's own table. The function codes and register map of a minimal Modbus slave show how the two sides of this decision fit together.

Then baseline the word. Put the unsigned 32-bit integer tag on screen next to the PLC's online value and force a change in the PLC. With a typical poll interval of 1 second, a forced change should reach the panel within one or two polls. Same number, same moment of update: the address and function are right, and the only remaining question is bit selection.

Prove one bit in a minimal project

  1. Make a fresh test project with three tags on the same register number: an unsigned 32-bit integer, an unsigned 16-bit integer and one discrete tag carrying the register class the map calls for.
  2. Write 1 to the PLC word, then 0. Both integer tags and the discrete tag should follow each change.
  3. Write 2048, which sets bit 11 and nothing else. Give the discrete tag bit 11 and confirm it turns on while a second discrete tag left at bit 0 stays off. Values 0 and 1 cannot separate a bit decode from a whole-word decode; 2048 separates them.
  4. If the discrete read returns 0x0002 in this small project, correct the function code against the register class and retest. When this project passes and the full project still fails, add tags back in groups as described above.

Map bits 0 through 11 as twelve tags

The fix is twelve discrete tags that share one register number and differ only in bit selection. Create one tag per alarm, enter the register number and set the bit position on every tag. Where the driver supports it, the discrete-point dialog asks for the bit number after you pick the register; one Modbus RTU driver setup opens exactly that bit dialog once you choose a discrete point at a holding-register address, so look for the same selector in the TCP driver's dialogs. Name each tag for its alarm, record the register number and bit position in the project notes, and wire each tag to its Triggered Text object, the panel object that shows a message while its tag is on. When an alarm deserves its own screen, that same bit also drives an event triggered screen change on the panel.

If the driver offers no bit choice, the discrete point follows the whole word and cannot serve a single alarm. Split the word in the PLC: copy the register into twelve internal bits with the PLC's bit-of-word or shift instruction and point the discrete tags at those bits. For plain status lamps, sixteen PLC input and output bits fit on one screen with the same per-bit addressing.

Example: decoding register value 137 into alarm bits 0 through 11

The scenario: the alarm word is one 32-bit unsigned holding register read by a 12-inch panel over Modbus TCP at a poll interval of 1 second, with flags packed in bits 0 through 11, the layout used throughout this article. The integer tag on screen reads 137. The bit values run 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 for bits 0 through 11.

The rule: bit n is set when the value AND the value of bit n is nonzero.

The arithmetic:

  • 137 AND 1 = 1, so bit 0 is set
  • 137 AND 2 = 0 and 137 AND 4 = 0, so bits 1 and 2 are clear
  • 137 AND 8 = 8, so bit 3 is set
  • 137 AND 16 = 0, 137 AND 32 = 0, 137 AND 64 = 0, so bits 4 through 6 are clear
  • 137 AND 128 = 128, so bit 7 is set
  • 137 is below 256, so bits 8 through 11 are all clear and no further AND is needed

A division check gives the same answer: 137 ÷ 2 = 68 remainder 1, so bit 0 is 1; 68 ÷ 2 = 34 remainder 0; 34 ÷ 2 = 17 remainder 0; 17 ÷ 2 = 8 remainder 1, so bit 3 is 1; then 8 ÷ 2 = 4, 4 ÷ 2 = 2 and 2 ÷ 2 = 1 with remainder 0 each time; 1 ÷ 2 = 0 remainder 1, so bit 7 is 1.

The result: 1 + 8 + 128 = 137, so the live flags are bits 0, 3 and 7 and the other nine are clear. Three of the twelve Triggered Text objects show and nine stay hidden. The threshold: any bit whose AND result is nonzero is a live alarm, and a register value of 0 clears all twelve. A tag that shows at this value while its own bit is clear is decoding the whole word, so its bit selection is missing.

Verify each bit before the alarms go live

Force each bit alone at the PLC and confirm only its tag and its message respond. Success at bit 0 does not validate bits 1 through 11, so run all twelve. Then force two bits together and confirm both messages show at once, clear the word and confirm all twelve messages hide. Keep the integer tag visible during these tests: the panel number and the PLC word must match at every step. If a bit is already set when the panel powers up and it goes missing from the alarm list, that is a startup problem with its own fix.

Do not hand an unverified bit to the operators: a tag that fires on the wrong bit can hide a real alarm. And if the same alarm summary also needs a notice board where the whole crew can see it, our shop-floor screens are built for floor conditions.

The decision for each case

  • The register map calls the alarm word a holding register: the read is FC03. A discrete tag that errored with 0x0002 on FC04 at that address had the wrong function, and the fix is the function code.
  • The driver shows a bit selector: twelve discrete tags on the same register number, bits 0 through 11, each wired to its own message object.
  • The driver has no bit selector: split the word into internal bits in the PLC and point the tags there.
  • A small project passes while the full project fails: add tags back in groups and inspect the last group's addresses and register classes.

Recommendation: prove one discrete tag in a minimal project at register values 0, 1 and 2048, then map bits 0 through 11 as twelve discrete tags that share the register number and differ only in bit position. Change the function code first when a discrete read returns 0x0002 while the integer tag reads the same address, and split the word in the PLC when the driver offers no bit selection.

Questions

Why does my discrete tag work at values 1 and 0 but misfire on other values?

Values 1 and 0 look identical to a bit tag and to a whole-word tag, so a test at those two values cannot separate the two decodes. Set a value that lights one high bit, such as 128 for bit 7 or 2048 for bit 11, and watch tags selected for different bits. If every tag moves together, the driver is following the whole word and the bit selection is missing.

What does Modbus exception 0x0002 tell me?

It is the illegal data address exception code from the Modbus specification. The server received your request and answered it, so the IP address and port are working; the fault is that no register exists at the address and function you asked for. Check the register class against the function code and the PLC map, as described below.

Can the panel write one alarm bit back to the PLC?

Input registers are read-only; Modbus allows no writes to them at all. A holding register accepts writes, but a write replaces the whole 16-bit word, so a panel writing one bit would overwrite every other flag packed into that word. Keep packed alarm words owned by the PLC, and use a separate command word for anything the operator sets from the panel.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote