An Equipment Constant Is a Recipe Change With a Different Name
The host wrote the EC, the tool returned EAC = 0, and nine lots ran on the old value. SEMI E5 EAC codes, a real S2F13 readback on the wire, the S2F29 namelist, and the SAT matrix.
Nine lots ran on the old threshold
An integration engineer pushed an inspection threshold change to a metrology tool at 06:40 on a Tuesday. S2F15, one ECID, new value. The tool came back with S2F16 and EAC = 0 — accepted. The MES logged the change against the request ID, marked the constant updated, and released the queue.
The tool applied the new value at the start of the next recipe load, not on receipt. There was already a carrier in process, and the scheduler kept feeding it for the rest of the shift without a recipe reload. Nine lots went through against the previous threshold while every system of record said the new one was active.
Nothing was misconfigured. The host asked, the tool said yes, and "yes" meant something narrower than anyone had checked. That gap — between acknowledged and effective — is where most EC incidents live, and it is not something the acknowledge code can tell you.
EAC = 0 means "I accepted it", not "it is in effect"
Worth being precise about what SEMI E5 actually promises you. EAC in S2F16 is a single binary byte, and E5 defines exactly four of its 256 values:
| EAC | Meaning |
|---|---|
| 0 | Acknowledge |
| 1 | Denied — at least one constant does not exist |
| 2 | Denied — busy, try later |
| 3 | Denied — at least one constant out of range |
| 4–63 | Reserved by E5 — no defined meaning |
The row people get wrong is the last one. 4 is not "denied, other" — E5 defines nothing there at all, and reserved is not the same as available. I have still met tools that answer 7, so whether your particular vendor uses that range is a manual question, not a spec question; I have not been able to confirm that E5 sanctions it, so treat any documented vendor code above 3 as that tool's private extension.
Either way the host parser is the same shape: a byte compare with a real default branch. Anything non-zero is a denial, log the raw number, and do not let it fall through the way an unrecognised enum usually does. I have seen a host treat an unmapped EAC as success because the switch had no default.
That is the whole contract. Nothing in it commits the tool to a moment of application, and nothing in it says the write was atomic across a multi-ECID message. Vendors differ on both, and I have met a tool that accepted a three-ECID S2F15, applied two, rejected the third internally, and still returned EAC = 0.
So the host has to close the loop itself:
- Read back with
S2F13after the write and compare the returnedECV— value and format — against what was sent. - Wait for the tool's change event on
S6F11and correlate it with the request ID. - Record, per ECID, when the value becomes effective: immediately, next recipe load, next carrier, after PPSELECT, or only after a software restart.
Item 3 is the one people skip because the manual usually just says "takes effect immediately." Confirm it during integration by writing a constant whose behavior you can see, and watching when the behavior changes — not when the ack arrives. Split writes one ECID per message unless you have specifically tested batch atomicity on that tool; the failure diagnosis is worth more than the round trips.
What the readback actually looks like on the wire
Step 1 above is the one people implement from a vendor PDF and never inspect. Here it is as bytes. Host side is a Python socket client; the equipment side is the SECS/GEM simulator HSMS passive listener on 127.0.0.1:5501, SessionID 11, no fault modes set. Every frame below was logged as RX by the equipment side, so these are wire bytes and not a rendering of a message object.
Select first, so the session is in SELECTED and the data messages are legal:
TX 00 00 00 0A 00 0B 00 00 00 01 00 00 00 01 Select.req
RX 00 00 00 0A 00 0B 00 00 00 02 00 00 00 01 Select.rsp, Select Status 0
Then S2F13 with an empty list, which SEMI E5 reads as give me every equipment constant:
TX 00 00 00 0C 00 0B 82 0D 00 00 00 00 00 02 01 00
| Bytes | Field | Value |
|---|---|---|
00 00 00 0C | Length | 12 — the 10-byte header plus a 2-byte body |
00 0B | SessionID | 11 |
82 | Header byte 2 | W-bit 0x80 set, Stream 2 |
0D | Header byte 3 | Function 13 |
00 | PType | 0, SECS-II |
00 | SType | 0, data message |
00 00 00 02 | SystemBytes | 2 |
01 00 | Body | L,0 — list of zero items |
The same request naming two ECIDs as U4, then naming them as ASCII — E5 allows both, which is the point:
TX 00 00 00 18 00 0B 82 0D 00 00 00 00 00 03
01 02 B1 04 00 00 01 2C B1 04 00 00 01 2D
TX 00 00 00 3B 00 0B 82 0D 00 00 00 00 00 04
01 02 41 17 45 43 33 30 30 5F 54 61 72 67 65 74 54 65 6D 70 65 72 61 74 75 72 65
41 14 45 43 33 30 31 5F 54 61 72 67 65 74 50 72 65 73 73 75 72 65
01 02 is a list of two items — for a list, E5's length field counts elements, not bytes. I got that wrong the first time I wrote this capture and the listener happily logged the malformed frame, which is a fair warning about how much a clean RX log proves. B1 is format code 54 octal (U4) with one length byte, so B1 04 00 00 01 2C is ECID 300. 41 is format code 20 octal (A); 41 17 is a 23-character string, 45 43 33 30 30 5F = EC300_. A host that hardcodes U4 ECIDs does not fail on this message — it fails on the tool that ships ASCII ones, months later.
None of the three drew an S2F14. That is a property of this listener, which implements HSMS control messages only and has no SECS-II responder — do not read it as equipment behaviour. What is worth taking from it is the shape: a Linktest.req sent immediately after the three silent readbacks came back with its Linktest.rsp in under a millisecond.
TX 00 00 00 0A 00 0B 00 00 00 05 00 00 00 05 Linktest.req
RX 00 00 00 0A 00 0B 00 00 00 06 00 00 00 05 Linktest.rsp
HSMS said the link was perfect while the application layer said nothing at all. A host that judges tool health from Linktest will report a green interface through an entire shift of unanswered EC readbacks; the clock that should be running there is E37's T3 reply timeout, default 45 s. My client waited 2 s per message and moved on, so the waits in the capture are the client's, not a T-timer's.
Ask the tool for its own list: S2F29
Before writing any of this into the MES, pull S2F29 (Equipment Constant Namelist Request) with an empty list and let the equipment return everything it has in S2F30: ECID, ECNAME, ECMIN, ECMAX, ECDEF, and UNITS. That reply is generated by the running software, which is more than you can say for the PDF the vendor emailed during FAT.
E5 leaves those fields loosely typed on purpose: ECID may arrive as any of U1/U2/U4/U8, the signed I equivalents, or A, and ECMIN/ECMAX/ECDEF may come back as any numeric type, A, B or BOOLEAN. ECNAME and UNITS are always A. So a parser that assumes U4 ECIDs works until the tool that numbers its constants as ASCII strings shows up, and then it fails on connect rather than on write.
Diff it against the interface spec. What tends to fall out:
- ECIDs present on the tool that never appeared in any document, including the interesting ones.
- Ranges that widened or narrowed in a firmware update, so the MES range check now rejects values the tool would accept, or worse, passes values it will clamp.
UNITSthat disagree with the plant's assumption — seconds versus milliseconds is the classic, and a T3 timeout entered in the wrong unit fails in a way that looks like a network problem.- Constants that are read-only in practice and deny every write with a vendor-range
EAC, despite appearing in the namelist.
Snapshot the S2F30 reply after every equipment software update and diff against the previous one. This is about ten lines of script and it has caught more silent behavior changes for me than any release note.
Classify first, or you will approve display preferences
Not every constant needs a change request. Route them by what they can actually break:
| Class | Example | Control |
|---|---|---|
| Informational | UI language, screen blank timeout | Local change, no approval |
| Communication | T3 reply timeout, event report enable | Engineering review, integration retest |
| Automation behavior | Auto-start enable, carrier verification mode | Host-visible, audited, idle-state only |
| Process-critical | Inspection threshold, temperature offset | Process owner approval, rollback value required |
| Maintenance bypass | Sensor ignore, dry-run mode | Time-limited authorization, mandatory expiry |
The class belongs to the ECID on that tool, not to the name. The same vendor parameter can be cosmetic on the older platform and a real sequence condition on the new one. Decide during interface design; retrofitting a classification onto a live tool means someone has to guess, and they guess low.
Maintenance bypasses are the ones I would put a hard expiry on even when nobody asks for it. A bypass with no reset event does not get turned off — it gets forgotten, and then it gets discovered during a deviation investigation six months later.
One ECID table, and the host range check is generated from it
Most EC mismatches trace back to the same shape: the rule exists in three places. MES says 0–10, the tool's ECMAX says 100, and an engineer's spreadsheet has a fourth number that predates both.
Keep one table, and make the host's validation read from it rather than reimplement it. Minimum columns:
- ECID, vendor ECNAME, and the plant-language description of what it does.
- Format code (
U4,I2,F4,A), unit, min, max, enumeration list. ECDEFfrom the namelist, and the approved production value — these are usually not the same, which is the point.- Host write allowed, local operator edit allowed.
- When the value takes effect.
- The event or report used to audit changes to it.
- Approval owner and documented rollback value.
Format matters more than it looks. Send a U1 where the tool expects U4 and some implementations coerce silently, some truncate, some deny with a vendor-range EAC, and exactly one will store a value you did not send. Assert the format on readback, not just the number.
Local panel changes are the ones that bite
Host-initiated changes are the easy half — you have the request, the ack, the readback, and the event. The dangerous path is the operator or the vendor service engineer changing a constant from the tool's own screen at 03:00.
GEM's control state model (ON-LINE/REMOTE versus LOCAL) governs who may command the equipment, but it does not guarantee that a local edit produces a host-visible event. Some tools emit a collection event with old and new value; some emit a generic "parameter changed" CEID with nothing useful attached; some emit nothing at all.
Find out which one you have, then build for it:
- If a change event exists, define the report with ECID, previous value, new value, and change source, link it to a CEID, and enable it with
S2F33/S2F35/S2F37. Verify it fires for local edits, not only for host writes. - If no event exists, run a periodic baseline sweep —
S2F13over the controlled ECID list on a schedule and at every lot start — and raise an exception on any drift from the approved value.
The sweep is not elegant and it is the difference between finding a drifted constant in minutes and finding it in a scrap investigation. On tools with no local-change event I run it every 15 minutes plus on every carrier arrival.
If the equipment's change event gives you a new value but no old value, read the constant before sending the write and store that as the previous value. An audit trail assembled from host application logs alone falls apart the first time someone asks whether the tool actually held that value.
Failure modes worth writing test cases for
Every one of these has cost someone a shift:
- The tool accepts a write while busy and applies it after the current lot. Next shift inherits a changed tool with a change record timestamped hours earlier.
- Enumerations disagree — MES sends
AUTOas ASCII, the tool wants1asU1, and there is no error, just a constant that never changes. - After a software restart the tool reloads
ECDEFinstead of the host-approved values. Every constant silently reverts. - The tool is multi-module and each chamber carries its own ECID. The host writes chamber 1 and reports success for the tool.
- A range check passes on the MES but the tool clamps to
ECMAXand reports the clamped value only if you read it back. - A maintenance bypass enabled for a two-hour PM is still enabled a month later.
Fold these into a scripted EC test matrix and run it at SAT, not just FAT — the equipment software on the floor is rarely the version you tested at the vendor. Cover: valid write and readback, out-of-range write (expect EAC = 3), nonexistent ECID (expect EAC = 1), write while processing (expect EAC = 2 or documented deferral), wrong format code, local panel edit, and power-cycle persistence.
Before you hand EC control to production
- The controlled ECID list was generated from
S2F30on the installed software version, not from the manual. - Every controlled constant has an owner, a range, a unit, an allowed change state, and a rollback value.
- Host write permission was confirmed on the real tool.
- Invalid writes are rejected cleanly and do not partially apply — verified with a multi-ECID message.
- Readback compares value and format.
- Local changes are detected, by event or by sweep.
- Audit records are searchable by lot, equipment, ECID, and time window.
The one people leave until after go-live is restart persistence, and it is the one that reverts every constant at once. Test it before the tool has product on it: write the approved values, power-cycle the equipment controller, then read the whole list back with S2F13 and diff. If the tool comes back holding ECDEF, you need a host-side restore step on the ON-LINE transition, and you need it before the first PM.
If you want to practise the transport half of this before you have a tool, the SECS/GEM simulator will take the same S2F13 bytes on a real socket and show you what the equipment side logged.