Problem Details
A momentary or maintained pushbutton (illuminated selector) placed on an SP310 operator panel screen must set a boolean in the PR200 relay-PLC program — for example to acknowledge an alarm and silence a siren. The panel tag is declared in the panel project script as:
<Tag Name="Button" Type="DI" Adr="0x0150" DataType="11" Func="1" Descr="Manual control"/>
In the logic editor the corresponding network variable is created as an input and wired to the ladder/FBD scheme. Symptom: the variable never changes state, regardless of button presses. No communication fault is necessarily reported — other tags on the same link may update normally.
The second, related complaint is architectural: the PR200 program has no service variable exposing the currently displayed screen number or the state of the front-panel keys (OK, arrows). All operator interaction is limited to variable-edit fields on screens, so building a menu, a password entry, or an "on ALARM screen press OK → kill siren" interlock inside the program is not directly possible.
DataType="11" in particular) must be confirmed against the panel configuration software's tag reference for your firmware before you copy them.Root Cause
Three independent failure modes produce exactly the same symptom — a frozen boolean. Check them in this order.
1. Tag direction is read-only
Type="DI" with Func="1" defines a discrete input the panel reads from the slave. Modbus function 01 is Read Coils; the panel is the initiator and the data flows slave → panel. A button whose value must reach the PLC needs a tag the panel writes: a coil object driven by function 05 (Write Single Coil) or 15 (Write Multiple Coils), or a register written with function 06/16 if you pack bits into a word.
Consequence: with the tag as written, pressing the button changes only the local panel object; nothing is ever transmitted. The PR200 variable stays at its power-up value.
2. Master/slave role mismatch
Only one device on an RS-485 segment may poll. If the PR200 is configured as Modbus master and the panel as slave, the panel's own tag polling never runs and its script tags are irrelevant — the PR200 must read the panel's holding registers/coils. If the panel is master, the PR200 must expose the target boolean as a slave variable with an assigned Modbus address and write permission. A boolean declared purely as a program "input" without a slave-side Modbus binding is not addressable by the master.
3. Address base and object-space mismatch
Adr="0x0150" is 336 decimal. Modbus data-model documentation frequently uses 1-based reference numbers (coil 00337) while the PDU carries the 0-based value 336. If one side of the link applies the +1 offset and the other does not, you read or write a neighbouring bit. Also verify object space: coil 336 and discrete-input 336 and bit 0 of holding register 336 are three different data items, selected by function code, not by address.
| Function | Code | Direction | Object | Use for panel button? |
|---|---|---|---|---|
| Read Coils | 01 | Slave → Master | Coil | No — read only |
| Read Discrete Inputs | 02 | Slave → Master | Discrete input | No — read only |
| Read Holding Registers | 03 | Slave → Master | 16-bit word | Yes, if PLC polls a packed status word in the panel |
| Write Single Coil | 05 | Master → Slave | Coil | Yes — panel as master |
| Write Single Register | 06 | Master → Slave | 16-bit word | Yes — bit-packed command word |
| Write Multiple Coils / Registers | 15 / 16 | Master → Slave | Coils / words | Yes — block writes |
Solution
Case A — Panel is Modbus master, PLC is slave
- In the PLC project, create a network variable of type BOOL and mark it as a slave variable with write access. Note the Modbus address the tool assigns; do not assume it matches your panel script.
- Change the panel tag from a read object to a write object. Declare it as a coil written with function 05 (or a register bit with function 06), not
Func="1". - Set the tag address to match the PLC slave address, applying or removing the +1 reference offset as the two tools require. Test both 336 and 337 if the documentation is ambiguous.
- Bind the screen button object to the tag with an explicit action: for a maintained switch use Toggle/Set-Reset; for a momentary acknowledge use Set on press / Reset on release. A button that only "displays" a tag never writes.
- In the PLC program treat the variable as a command bit and reset it in logic after acting on it, so a communication dropout cannot latch the command.
Case B — PLC is Modbus master, panel is slave
- Assign the button object in the panel project to an internal panel register/coil at a fixed address.
- In the PLC, add a master read request: function 01 for a coil, or function 03 for a status word containing several buttons.
- Set the poll period fast enough for the shortest expected press. For momentary acknowledge buttons, prefer latching the press in the panel (set-on-press, PLC clears it via a write) instead of relying on catching a short pulse in a poll cycle.
Recommended pattern: latched handshake
Polling a momentary contact over a serial link is unreliable — the bit is FALSE almost all the time and TRUE only for the poll windows that happen to overlap the press. Use a two-bit handshake instead:
Panel button press -> SET cmd_bit (panel writes 1, function 05)
PLC scan -> IF cmd_bit AND NOT cmd_done THEN
siren := FALSE; (* execute action *)
cmd_done := TRUE;
END_IF
PLC -> writes/holds cmd_ack for panel display
Panel or PLC -> clears cmd_bit; cmd_done follows cmd_bit
This removes any dependency on poll timing and gives the operator visual confirmation.
Working Around the Missing Screen and Key State
The PR200 program has no built-in "current screen number" or "OK key pressed" service variable comparable to the service time variable. Two practical approaches:
-
Mirror the screen manager into the program. Maintain an INT variable
scr_idin the program. On every screen-transition condition you already define in the screen manager, drive the same condition intoscr_idwith a MOVE/selector block. The program then evaluates "IF scr_id = ALARM_SCREEN AND ack_cmd THEN siren := FALSE". The weakness is duplication: any change in the screen manager must be repeated in the logic, and complex transition trees are easy to get out of sync. -
Invert the ownership. Drive screen selection from the program: let the logic own
scr_idand let the screen manager transitions be simple comparisons of that variable. Now the program always knows the active screen by construction, and there is a single source of truth.
For arrow-key adjustments (for example dimming a lighting output from a BRIGHTNESS screen) without entering variable-edit mode, the workable substitute is an editable variable on the screen bound to the setpoint, with the program clamping and rate-limiting the value. Where true event-driven behaviour is required — run a macro on key press, open a window on an event, latch a password entry — use an external HMI that supports event scripts and bind it to the PR200 over Modbus, exactly as in Cases A/B above.
Verification
- Physical layer: confirm identical baud rate, data bits, parity, stop bits and slave address on both devices, and that A/B lines are not swapped. Termination and bias resistors on the RS-485 segment ends.
- Traffic: put a serial sniffer or protocol analyser on the line. Confirm you actually see a frame with the expected function code when the button is pressed. If no frame appears on press, the fault is the tag/button binding, not addressing.
- Exception codes: a response with the function code + 0x80 identifies the problem directly — 0x02 (Illegal Data Address) means the address or offset is wrong; 0x01 (Illegal Function) means the object type is unsupported; 0x03 (Illegal Data Value) means the write payload is malformed (coil writes must be 0xFF00 or 0x0000).
- Address sweep: if 0x02 is returned, test the adjacent reference (336 vs 337) to confirm the base offset convention.
- End-to-end: force the PLC-side variable from the programming tool and confirm the panel object follows (proves the link and address), then press the panel button and confirm the PLC variable follows (proves the write direction).
- Timing: log the command bit with a timestamp; verify every press produces exactly one action, with no double-fire and no missed press over 50 consecutive presses.
FAQ
Why does my SP310 button tag with Func="1" never update the PLC variable?
Modbus function 01 is Read Coils — the panel only reads that object and never transmits the button state. Redefine the tag as a write object using function 05 (Write Single Coil) or 06/16 into a register, and bind the button with a Set/Toggle action rather than display-only.
Is Adr="0x0150" the same as coil 337 in the PLC?
0x0150 is 336 decimal. Many tools display 1-based reference numbers (00337) while the PDU carries the 0-based 336. If you get exception code 0x02 (Illegal Data Address), test the adjacent address to determine which convention each side applies.
How do I know the current screen number inside the PR200 program?
There is no service variable for it. Either mirror every screen-manager transition condition into an INT variable in the program, or better, drive screen selection from a program-owned variable and make the screen manager transitions simple comparisons of it.
Why does the PLC sometimes miss a momentary button press over Modbus?
The bit is TRUE only for the press duration; if no poll or write lands in that window, the event is lost. Latch the press into a command bit that stays set until the PLC executes the action and clears it — a two-bit handshake removes all poll-timing dependency.
Can I use panel buttons to increment a setpoint without opening an edit field?
Bind each button to its own command bit (up/down), then implement increment, clamping and rate limiting in the PLC program on the rising edge of each bit. Always clear the command bits in logic so a lost link cannot leave one latched.