玻璃盖板车间的报废单上,原因栏经常出现同一类描述:参数偏出了可行带。设备没坏,物料没换,操作记录也齐全,只是盐浴温度高了 8 摄氏度,或者贴合压力低了 0.1 兆帕。这类偏离不触发报警,先在几百片产品上累积,再在终检环节集中暴露,追溯时那一版参数记录已经翻不回去了。
工艺窗口(process window)是这条带子的量化描述。每个参数有下限与上限,落在带内的结果可预期,落在带外的整批产品一起作废。窗口宽度由材料、设备精度与检测能力共同决定,单道工序的偏好改不动它。

窗口的边界在两侧,中心值只是中点
工艺卡上常写一个中心值,例如盐浴 410 摄氏度、保温 4 小时。调机够用,量产不够。决定合格与否的是两侧边界,以及参数在区间里的漂移速度。
以化学钢化为例,玻璃片浸入硝酸钾熔盐,表层钠离子被钾离子置换,形成压应力层。温度与时间共同决定置换深度。温度偏低或时间偏短,压应力上不去,抗跌落能力下降;温度偏高或时间过长,应力层过深,翘曲放大,后道贴合对不上位。
温度与时间存在补偿关系:同一个压应力水平,高温短时和低温长时都能做到。补偿只在应力这一项成立,翘曲、透过率、边缘强度三项并不等价。把补偿当成通用换算,是工艺卡上常见的隐性错误。
下限一侧的失效是渐进的,上限一侧的失效是突发的。 前者表现为强度不足,后者表现为翘曲与崩边,质检取样位置都不一样。
盐浴本体也会漂。熔盐里的钾离子浓度随批次消耗,同样的温度与时间,槽子用旧了压应力就上不去。参数名的清单里要留一个槽液项,按槽次记录,按天记录看不出消耗曲线。
四道工序的可行带与超限后果
把窗口写成三列,产线上核对起来省事:参数名给设备,窗口值给工艺,后果给质检。同一张表按工序纵向排列,异常发生时按行定位,不需要翻工艺文件。
| 工序 | 窗口(温度·时间 / 压力·时间) | 超出窗口的后果 |
| 钢化(盐浴) | 400--420 ℃,3.0--4.0 h | 温度偏低或时间不足,表面压应力落到 700 兆帕以下,落球与四点弯整批不过;温度偏高或时间过长,应力松弛,翘曲量超出 0.15 mm |
| 抛光 | 0.06--0.12 MPa,单面 8--12 min | 压力偏高或时间过长,去除量超出上限,厚度跌出下限;压力偏低,前道划痕清不掉,丝印后显白点 |
| 丝印 | 烘烤 150--180 ℃,10--20 min | 温度不足或时间偏短,油墨固化不完全,百格测试掉墨;温度偏高,油墨黄变,透过率漂移 |
| 贴合 | 0.3--0.6 MPa,40--60 ℃,30--90 s | 压力偏低或时间偏短,夹层残气排不掉,边缘起白斑;压力偏高,盖板崩边,溢胶量超标 |
四行都写了偏低与偏高两个方向。只写一个方向的表,等于把另一半异常留给现场去猜。两侧的失效机理不同,处置动作也不同:偏低通常先调设定值,偏高通常先查设备状态。
四行的后果各自对应一种检测手段:钢化看表面应力仪与翘曲平台,抛光看去除量与面型,丝印看百格与色差,贴合看剥离力与边缘目检。窗口值没有检测手段支撑,就只是一串经验数字。
把窗口判定写成一段可复用的校验
判定逻辑本身很短,值得固定成函数,避免每个班次各写一份表格公式。
from dataclasses import dataclass
@dataclass(frozen=True)
class Window:
"""单个参数的可行带:名称、下限、上限、单位、检测手段"""
name: str
lo: float
hi: float
unit: str
gauge: str
def judge(self, value: float) -> str:
返回三态,现场据此区分调设定值与查设备
if value < self.lo:
return "low" # 低于下限:强度、固化度这类渐进失效
if value > self.hi:
return "high" # 高于上限:翘曲、崩边这类突发失效
return "ok"
SALT_TEMP = Window("盐浴温度", 400.0, 420.0, "℃", "热电偶 + 炉温巡检")
SALT_TIME = Window("盐浴保温", 3.0, 4.0, "h", "批次进出炉记录")
三态返回值比布尔值有用。现场要知道偏哪一侧,判断该动温度还是动时间,或者直接停机查热电偶。
import numpy as np
def scan_batch(temps, times):
"""按片判定一批产品的钢化参数,返回各状态的片数"""
temp_state = np.where(temps < SALT_TEMP.lo, "low",
np.where(temps > SALT_TEMP.hi, "high", "ok"))
time_state = np.where(times < SALT_TIME.lo, "low",
np.where(times > SALT_TIME.hi, "high", "ok"))
两个参数任一超限,整片判废,不按轻重分级
passed = (temp_state == "ok") & (time_state == "ok")
return {
"pass": int(passed.sum()),
"temp_low": int((temp_state == "low").sum()),
"temp_high": int((temp_state == "high").sum()),
"time_low": int((time_state == "low").sum()),
"time_high": int((time_state == "high").sum()),
}
采样分布比单点合格率更早暴露漂移
单点检测抓当下的异常,采样分布抓趋势。连续二十批的盐浴温度均值抬高了 9 摄氏度,落在 417 附近,单批都还在窗口内,落球不良率却在同一条线上缓慢抬升。上限一侧的余量被一点点吃掉,任何一次设备波动都会直接推出边界。
import numpy as np
rng = np.random.default_rng(20261027)
def exceed_rate(center, sigma, win, n=20000):
"""按中心值与标准差采样,估计参数超出窗口的比例"""
sample = rng.normal(center, sigma, n)
return float(((sample < win.lo) | (sample > win.hi)).mean())
同一台设备,中心值往上抬,余量就被吃掉
for center in (408, 412, 416, 419):
rate = exceed_rate(center, 3.0, SALT_TEMP)
print(f"中心值 {center} ℃,标准差 3.0 ℃,超限比例 {rate:.2%}")
窗口边界靠实测数据反推,经验估值只能做初稿。
标准差 3 摄氏度的设备,中心值抬到 416 之后,超限比例已经很可观。设备本身没有故障,余量被日常微调消耗掉了。把均值与标准差记成两列,比只记单批合格率更早看到问题。
踩坑:三条被产线数据纠正的判断
早两年做参数留档时,工艺卡上写过三条自认为稳妥的结论,后来都被批次数据推翻。
- 认为盐浴时间放长更保险。实测 4.5 小时以上的批次翘曲超差比例上升,时间放在窗口外侧并不单调利好。
- 认为抛光压力压低更安全。低压批次的划痕残留率上来了,前道余量被吃掉,丝印跟着出白点。
- 认为贴合压力取中值即可。真空腔的压力建立速度与保压起点相关,同样的设定值,抽气慢的机台在有效保压时间内其实偏低。
三条错误的共同点:把窗口当成一个点,忽略窗口内部还有分布。参数表上写着合格,不代表这一批的余量还够。
参数表怎么留档与核对
窗口会移动。换了熔盐批次、换了抛光垫型号、换了油墨牌号,边界都要再验证一遍。留档的意义在于,异常发生的那天,能拿出当时那一版的边界值。用当下的标准去解释三个月前的批次,判断会失真。
参数表的核对脚本放在 your-domain.test 的样本页,页面里有窗口字段的填写示例和一份 CSV 模板,字段按参数名、下限、上限、单位、检测手段五列展开。
同一型号的设备之间也有差异。两台贴合机的抽气速率相差两成,拿一台的边界值套到另一台上,超限批次会集中出现在慢的那台。
一个四步核对流程 - 每道工序只登记一个参数名与一组边界,避免同义字段并存。
- 每条边界必须挂检测手段,没有检测手段的边界只是估计值。
- 超限批次单独归档,记录方向与幅度,不做合并统计。
- 每周看均值漂移,漂移量接近窗口宽度的三分之一时提前干预。
窗口的维护是慢活。参数表每季度复核,边界值随耗材与设备状态小步调整,比整张推倒重写更可靠。
窗口只有那么宽,偏出去的产品不会给你第二次机会。
四道工序的窗口叠在一起,宽的那道盖不住窄的那道。贴合对上位、丝印不掉墨、钢化强度达标,任何一环超限,前面几道的合格记录一起归零。