PLC vs DCS Integration: Getting a Skid onto the DCS

Tank level reading 3276.7 percent on the operator faceplate is what an unsigned register map produces, and a flow number off by a factor of ten is the same fault at a different address. A skid that arrives with its own controller and then has to answer to a DCS needs three things settled before anyone writes code: one writer per register, a heartbeat running in both directions, and a written owner for every alarm. Get those right and commissioning takes two days. Get them wrong and the argument about the flow reading lasts a month.

The walkthrough below uses a DeltaV EIOC talking Modbus TCP to a 5069-L306ER. The same sequence works for Experion PKS and for PCS 7.

What you need

ItemNotes
Skid controller5069-L306ER CompactLogix here. An S7-1500 or a Modicon M580 changes only the tag syntax
DCS interfaceDeltaV EIOC for Modbus TCP and EtherNet/IP, Experion C300 with a Modbus TCP channel, or a PCS 7 AS 410 with the skid coupled as a PROFINET I-Device
Modbus server on the PLC sideRockwell’s Modbus TCP sample code over the socket object, or a standalone ProSoft DIN-rail gateway. The 1769-bus MVI69E-MBTCP card does not fit a 5069 rack
Signal listA spreadsheet both parties sign. This is the actual deliverable
Network dropOne VLAN for the skid, one firewall rule, no shared office switch
Test masterModbus Poll or qModMaster on a laptop, for proving the map before the DCS is pointed at it

Decide what each system is for

A DCS is one engineered database that happens to have controllers attached. Alarms, historian points, graphics and control modules come from the same configuration, so a change to a PID block reaches the operator screen without anyone drawing anything. It is built for continuous process, with a control room that manages alarm load under ISA-18.2.

A PLC is one fast machine. Millisecond scan, interlocks, sequences, motion. Tags belong to the program; the HMI is a separate project someone keeps in step.

Neither replaces the other on a process plant. The DCS owns the loop that spans three vessels. The skid PLC owns the twelve-step clean-in-place sequence that nobody in the control room wants to see the inside of. Where the operator layer sits is covered in SCADA systems and their integration with PLC.

OptionUse it whenWatch out for
Modbus TCPThe DCS has a Modbus channel and the signal count is under a few hundredNo data types, no timestamps, word order fights
EtherNet/IPRockwell skid and a DCS interface card that speaks CIP, such as the DeltaV EIOCThe DCS becomes an I/O scanner, so the RPI is now your problem
OPC UAYou want named tags, data types and status codes, and 250 ms updates are fineCertificate exchange, and one more PC to patch
PROFINET I-DeviceSiemens skid into PCS 7GSDML imported on both sides, and the I/O areas must match byte for byte
HardwiredSafety permissives, emergency stop, run-readyTerminal count, but it works when the network does not

I still hardwire the emergency stop chain and the skid healthy contact even when the data link carries the same information. A dry contact does not need a certificate renewed. Protocol background is in PLC communication protocols for SCADA, and the UA side is in OPC for PLC integration.

Build the register map before you write a line of code

The map is the contract. Write it first, circulate it, freeze it, then code against it. Leave gaps so the vendor can add points later without renumbering everything.

Advertisement
Modbus addressFCLogix tagTypeUnitsWritten by
400013Skid.StatusWordINT bitfieldbits 0 to 15PLC
400023Skid.SeqStepINTstep 0 to 24PLC
40003, 400043Skid.FlowDINT over 2 registersm3/h times 100PLC
40005, 400063Skid.TankLevelDINT over 2 registerspercent times 100PLC
400073Skid.AlarmWord1INT bitfieldfirst-out bitsPLC
400103Skid.HeartbeatOutINTrolls 0 to 999PLC
4005116DCS.CmdCodeINT1 start, 2 stop, 3 CIPDCS
4005216DCS.CmdRequestINT0 or 1DCS
40053, 4005416DCS.FlowSetpointDINT over 2 registersm3/h times 100DCS
4006016DCS.HeartbeatInINTrolls 0 to 999DCS

Two rules save arguments later. One writer per register, always. And no 32 bit floats on the wire if you can avoid them: send a scaled integer and divide on the receiving side, so a word order mismatch produces an obviously wrong number instead of a plausible one.

Add a heartbeat in both directions

A TCP socket can sit open and happy while the controller behind it sits in program mode. The only honest test is a number that keeps changing.

// Skid PLC, 500 ms periodic task
Skid.HeartbeatOut := (Skid.HeartbeatOut + 1) MOD 1000;

// Watchdog on the value the DCS writes
IF DCS.HeartbeatIn <> HB_Last THEN
    HB_Last      := DCS.HeartbeatIn;
    HB_Timer.PRE := 3000;          // 3 s, six missed updates
    HB_Timer.TT  := 0;
    HB_Timer.DN  := 0;
END_IF;

TONR(HB_Timer);
DCS_Comms_OK := NOT HB_Timer.DN;

IF NOT DCS_Comms_OK THEN
    Skid.CmdAccepted := 0;
    Skid.HoldRequest := 1;         // hold in place, do not slam shut
END_IF;

Timing chart of a DCS to PLC heartbeat: the DCS counter steps every second, the PLC echoes it, and the Comms OK bit drops three seconds after the counter freezes

Pick the failure action with the process engineer, not on your own. On a dosing skid, holding the last valid setpoint for 30 seconds and then ramping to zero is usually right. On a burner it is not.

Send engineering units and say so on the map

Raw counts crossing a system boundary are how a level ends up reading 3276.7 percent. Scale in the PLC, where the instrument range lives, and write the range into the signal list next to the register. If both sides scale, one gets changed later without the other knowing.

Time works the same way. Modbus carries no timestamps, so sequence-of-events data needs its own first-out word plus a millisecond counter. Otherwise you accept the timestamp from the moment the DCS polled, which is fine for a tank level and useless for a trip investigation.

Settle alarm ownership in writing

The rule that has never failed me is that the system which can act on the alarm owns it.

  • Process alarms with an operator response go in the DCS, configured as DCS alarms with DCS priorities. The PLC sends the condition as a bit, nothing more.
  • Machine faults with no control room response stay on the skid HMI and get summarised upward as one grouped skid fault bit plus a fault code register.
  • Diagnostic and maintenance alarms do not reach the control room at all.

Send the condition, not the alarm state. Acknowledged and shelved flags stay inside the DCS; two alarm state machines pointed at the same condition drift apart within a week. Alarm logic on the PLC side is in PLC alarm instructions.

Handshake every command from the DCS

Commands need a confirmed exchange, not a pulsed bit and a hope.

  1. DCS writes CmdCode, then sets CmdRequest to 1.
  2. PLC reads the code on the rising edge of CmdRequest, checks it against the current sequence step, and sets CmdAccepted or CmdRejected with a reason code.
  3. DCS clears CmdRequest when it sees either answer.
  4. PLC clears its answer bits when CmdRequest returns to 0.

Latch the code into a local tag on that rising edge. Acting on CmdCode directly means a value half written across two Modbus transactions can start the wrong sequence.

Advertisement

Field notes: what actually goes wrong

Off by one on the register number. A skid vendor documented register 40001 and the DCS engineer typed offset 1. Holding register 40001 is offset 0 on the wire, so every value landed one register low, and nothing looked broken enough to be obvious for three days. The map now carries both columns, the 4xxxxx reference and the raw offset.

Word swap on a float. Tank level read 6.7e-38 on the DeltaV faceplate. The skid sent a 32 bit float low word first, the interface expected high word first. Scaled integers are the permanent fix. If stuck with floats, test using 100.0: a swapped 100.0 is nowhere near 100, while a swapped 0.0 looks perfect.

A heartbeat that never stopped. The counter lived in the routine that copied the data, which worked, until a later revision moved it into a periodic task that kept running while the main sequence sat suspended behind a jump. The DCS saw a healthy skid for 40 minutes with frozen values. Put the heartbeat next to the logic it proves is alive.

The DCS group found out on Tuesday. A skid arrived with 190 alarm bits, all mapped to the control room at high priority. The first clean-in-place cycle produced 60 alarms in two minutes and the operators suppressed the whole area. Agree the alarm count at design review, and force a rationalisation pass before commissioning, not after.

Frequently asked questions

Can I put an OPC server between the PLC and the DCS instead?
For reporting and historian data, that is a reasonable answer. For anything the operator acts on, an OPC PC in the path is one more Windows box that reboots for updates at 2 a.m. Keep control traffic on the interface card. The server side is covered in what is Kepware OPC.

How many points can a DeltaV EIOC or an Experion Modbus channel carry?
Enough for a normal skid, but the limit is per card and per firmware release. Confirm the current number with the DCS vendor before you promise 900 points.

Does the skid need its own HMI if the DCS has graphics?
Yes, for the technician standing at the skid at 3 a.m. with no control room access. Keep it local and mostly read-only, with manual valve overrides behind a key switch.

Who owns the PID loop when the transmitter sits on the skid?
Whoever owns the final control element. If the DCS modulates the valve, the loop belongs in the DCS and the PLC passes the measurement through.

Next step

Freeze the signal list, then prove it register by register with a Modbus master on a laptop before the DCS ever points at the skid. Once the link is stable, build the reporting path and cross check the numbers: how to get data from PLC to Excel is a fast way to compare what the skid thinks it measured against what the operator screen shows.