前阵子一个朋友丢过来一套博途V16的S7-1200工程说是制药厂生物发酵系统的完整程序让我帮忙梳理一遍。乍看之下这套系统好像就是几个发酵罐的温度、pH、DO、搅拌控制没什么稀奇。可真把程序一段段扒开之后才发现这玩意儿把PID调节、顺序控制、配方管理、上位机通信、安全联锁全都揉在了一个1200的CPU里复杂度和精细度远超一般小型设备程序。如果你也在做或准备做发酵、灭菌SIP、清洗CIP这类偏流程行业的PLC项目这篇文章值得耐心看完。我会按实际拆解程序的顺序把架构思路、核心控制逻辑、通信设计、调试踩坑一次讲透。1. 生物发酵系统为什么用S7-1200 博途V161.1 先看清发酵系统到底要控制什么很多人一听“生物发酵”脑子里想的是一个大罐子以为就是个温度控制。实际上一个完整的发酵工位控制对象至少包括罐内温度、pH、溶解氧DO、搅拌转速、罐压、消泡、补料流量、空气流量甚至尾气O2和CO2浓度。每个控制对象背后还跟着泵、阀、变频器、模拟量变送器加起来一个种子罐加三到五个发酵罐的中试车间I/O点数大概在100到250点之间。这就决定了这套程序不能像机床或者包装机那样简单写几个电机起停就行。它既要处理连续调节量温度、DO、pH又要处理大量的开关量步进顺序SIP、CIP、接种、放料还要兼顾批次记录和报警归档。说得直白一点这是一套微缩版DCS只不过落在了1200这个小型PLC平台上。我手里这套程序对应的硬件配置是1215C DC/DC/DC带两个模拟量输入模块、一个模拟量输出模块外加一组ET200SP远程IO放在发酵罐平台旁边。选1200而不是1500核心原因就是点数规模刚好在这个区间成本差了好几倍而且博途V16对1200的程序组态、调试监控支持得已经非常完整现场维护工程师也更容易上手。1.2 选型不是越大越好而是刚好够用有些刚入行的工程师一看到流程行业就本能地想上S7-1500觉得1200“太小、不靠谱”。但实际做项目时选型考虑的是控制规模、扫描周期、通信需求、项目预算和维护成本。中小型发酵系统用1200完全足够CPU再大不会让温度PID控制得更准反而会让机柜空间、模块价格、培训成本都跟着上去。需要注意的一个点是固件版本和博途版本的匹配。V16对应1200的固件版本最高支持到V4.5左右如果你拿到的一台CPU固件是V4.7那V16是下载不了的必须升级博途到V17以上或者让供应商把PLC固件降级。这个坑在调试现场非常常见很多时候不是程序有错而是工具版本和硬件固件不匹配。另外1200系列里1214C和1215C两个型号差价不大但1215C多一路以太网口对于既要接HMI又要接SCADA/MES的项目来说非常实用。我这套程序里就是1215C的第二个网口单独划给了上位机交换机避免现场调试时HMI在线监控和Modbus TCP轮询互相抢带宽。1.3 博途V16给这类项目带来的实际变化博途V16相比老版本最大的感受是SCL语言的编辑体验好了很多断点调试、在线监视、Trace曲线工具都齐全。发酵这类程序里顺控逻辑特别多传统用梯形图写步进器非常占屏幕而且容易漏条件。SCL可以用CASE语句把每一步的条件、动作、超时都放在一个紧凑的结构里可读性和维护性都好一个档次。还有一点是V16对全局库的支持更好了。发酵车间如果不止一个罐子我会把通用的温度控制FB、pH控制FB、顺控步进FB都做到项目库或者全局库里然后在每个罐的DB上生成独立背景数据块。这样就避免了复制粘贴程序后忘记改DB的惨剧。这一点我后面会详细讲。2. 程序总体结构与设计思路拆解2.1 任务块OB怎么分配才算合理打开这套程序的时候我第一件事就是看OB列表。一个良好的1200发酵程序不会把所有东西都塞在OB1里滚动执行。这套程序的OB分配思路大概是这样的OB1负责HMI交互、手动操作、阀位输出刷新、通用报警OB30循环中断专门做PID计算和模拟量采样滤波循环周期设置为100msOB40用于硬件中断比如急停回路输入触发后的快速处理OB82诊断中断用来捕捉模块插拔、短路等诊断事件。这么分配背后是有原因的。PID运算和模拟量采样对时间确定性要求高放在OB30里能保证每次循环间隔基本固定。而HMI通讯和手动操作逻辑放OB1即使因为某些通讯延迟导致OB1扫描时间偶发变长也不会直接影响PID的控制稳定性。很多1200初学者会忽略OB30的优先级一上来就在OB1里直接调用PID_Compact结果现场发现控制周期忽快忽慢自整定出来的参数怎么都不对。把运算挂到固定周期中断里是这类连续控制程序的基本功。2.2 FC、FB、DB三类程序块的“家族谱”我把这整套程序的块结构拆开之后整理出了一个很清晰的职责分工FC函数做纯计算和转换比如模拟量工程量换算、累加量计算、手动/自动模式切换。这类块没有自己的存储区适合做无状态的计算方法FB函数块做有状态的控制逻辑比如发酵步骤顺控、CIP清洗步进器、PID参数管理。每个FB配一个背景DB用来保存中间状态和步号DB数据块分为接口DB、工艺参数DB、配方DB、报警DB。接口DB专门用于和HMI通信把所有需要显示的变量集中管理工艺参数DB存温度设定、pH设定、PID参数等配方DB按批次号存储不同产品的工艺路径全局DB和PLC变量表负责硬件IO映射和跨块共享变量。这套结构最值钱的地方在于“每个FB只干一件事”。比如发酵顺控FB只负责步进逻辑它不直接去操作泵和阀的输出点而是通过接口DB把“目标状态”交给输出刷新FC。这样一来手动/自动模式切换就是切换输出刷新FC的数据源程序的安全互锁也只有一个地方维护不会出现阀被多个地方同时写的情况。2.3 命名规范别人能不能看懂你的程序就看这一步拆这套程序时我发现原开发者应该是从DCS转过来的人因为他的变量命名全部沿用了仪表位号体系。比如TT-101表示温度变送器101PV表示过程值SP表示设定值CV表示控制输出FIC-201是流量控制指示AT-101是pH分析仪。这样命名最大的好处是工艺工程师和设备维护人员拿到程序列表不需要看注释就能对上现场仪表。我自己做程序也强烈建议坚持“位号属性”的命名规则。比如一个阀不要叫“V12”要叫“XV-101_OPEN_CMD”或者“FV-201_AUTO_SP”。一开始写起来觉得繁琐但等到两个人协作调试、或者半年后甲方要求加一个联锁条件时你会感谢当初的命名习惯。2.4 联锁和安全设计不是锦上添花制药发酵系统涉及高温蒸汽、酸碱物料、带压容器程序里必须有联锁设计。这套程序里联锁分了两个层次第一层是硬联锁也就是急停回路和关键安全阀的硬接线。比如急停按钮直接切断蒸汽切断阀和酸碱泵的AC220V控制回路不经过PLC这是任何时候都优先保证的安全底线。第二层是程序软联锁比如温度超过上限时强制关闭蒸汽阀、罐压超高时打开排气阀、pH超过安全范围时禁止加酸泵启动。软联锁写在FB内部并且优先级高于自动控制输出同时带有2秒的输入滤波防止信号抖动导致误动作。需要强调的是S7-1200标准型CPU本身不具备功能安全认证这些软联锁只能作为工艺保护手段不能作为唯一的人身安全保护。如果要达到SIL等级要求必须上1200F系列或者单独的安全继电器回路。这一点在做制药项目时如果被问起一定要讲清楚别给自己埋雷。3. 发酵核心控制逻辑从PID到顺序控制的实操拆解3.1 温度控制不是简单一个PID就能搞定发酵罐温度控制表面上就是加热和降温但实际执行起来牵扯到冷热水阀的分程控制。这套程序里使用的是PID_Compact指令PID输出0%到100%后再经过分程计算拆成两路阀位0%到50%对应冷冻水阀50%到100%对应蒸汽阀中间再加一个2%的死区避免两个阀在切换点附近频繁动作。PID参数方面程序初始设定比例增益2.5积分时间180秒微分时间设为0采样周期100ms。先让PID自整定跑一轮再手动微调。这里有一个很实用的经验温度对象大滞后微分时间尽量不要加加多了反而会在蒸汽阀开启瞬间产生剧烈振荡。真正起作用的是积分分离和输出变化率限制。我在现场经常看到有人拼命调PID参数却忘了把输出变化率限制加上结果蒸汽阀从0%猛冲到80%罐温瞬间过冲四五度。限制输出变化率在每分钟不超过30%温度曲线会平稳得多。3.2 pH和DO控制不能用常规PID思维pH调节和DO调节是发酵程序里最容易写崩的两个回路。pH受加酸泵和加碱泵影响系统存在严重非线性而且执行机构是开关量泵不是连续调节阀。程序里用的是一种非常实用的“死区时间比例”控制算法设定目标pH为7.00死区设为±0.05偏差超过死区时每个控制周期内按偏差比例计算泵的启动占空比。偏差小泵脉冲宽度小偏差大泵长开。这样既避免了泵频繁起停烧电机又能把pH控制在一个较小的波动范围。我拆开这套程序的内部逻辑时注意到它的占空比上限被限制在80%而不是100%。这个细节很妙留出20%的“不动作时间”用来观察pH变化的真实趋势防止系统过冲。溶解氧控制则用了串级思路DO主调节回路的PID输出作为搅拌变频器的转速给定当搅拌转速已经达到上限而DO仍然偏低时再通过一个比较器打开补气阀门增大空气流量。串级回路里尤其要注意给定上下限否则一旦DO偏低搅拌速度会瞬间冲到最高发酵液剪切力过大反而影响菌体生长。3.3 补料策略与消泡逻辑看似简单实则讲究发酵过程中的补料控制比想象中要复杂。程序里补料泵有三种模式连续流加、间歇流加、指数流加。连续流加最简单按设定流量对应频率运行间歇流加则是每固定周期启动一段时间适合需要脉冲式补充营养的工艺指数流加需要根据当前发酵时间离线算好一个流加曲线存放在配方DB里程序按时间点查询并更新泵频率。消泡逻辑则是另一层戏。消泡电极一旦检测到泡沫接触程序不是简单启动消泡泵而是先暂停补料泵同时将搅拌转速强制提升20%维持5秒把泡沫甩掉再恢复原来的电机转速。如果泡沫信号在10分钟内触发了超过5次系统就判断为严重起泡触发声光报警并自动停止该罐的补料程序。这个策略既保护了消泡效果也防止了过度补料。3.4 SIP/CIP顺序控制步进器的写法与工程陷阱发酵罐的在线灭菌和清洗是整个程序里程序步最多、最容易出问题的地方。SIP在位灭菌的典型步序大概是开启排气阀和排污阀打开蒸汽阀升温到达灭菌温度后进入保温段保温计时完成后关闭蒸汽阀通过夹套冷却循环水降温最后是保压和排凝。每一步都是一个“条件满足才允许进入下一步”的步进状态机。程序用SCL的CASE语句实现步进器每个CASE分支代表一个工艺步。每步包含进入条件、过程动作、超时时间、离开条件。实际操作中最关键的一个细节是步进值的保持手动/自动模式切换时不改变当前步号。如果现场人员切到手动动了几个阀再切回自动程序必须能感知实际状态并重新同步否则就会出现“程序以为还在升温实际上已经冷却”这种严重事故。还有一点必须强调跳步操作在制药验证流程里是不允许的。整套程序没有开放强制跳步的工程师按钮只有长按触摸屏维护密码进入的“强制步进”功能而且每用一次都会在报警记录里留下审计痕迹。这个小设计非常值得学习它既照顾了调试期的需求也守住了合规底线。3.5 模拟量处理与进制转换的工程细节博途V16里处理4-20mA模拟量很多人还在用以前的FC105思路去缩放但在1200里更标准的方式是NORM_X和SCALE_X组合。这里还有一个容易忽视的点程序要判断信号是否正常。4-20mA对应NORM_X输入范围为0~27648如果读取值小于约5530对应大约4mA以下的断线状态程序会强制把该点标记为故障并在HMI上显示灰色故障状态同时联锁该回路保持安全输出值。这个“故障自动判定”逻辑比单纯做量程转换要重要得多。至于“十进制转十六进制”这个搜索热词在发酵系统里最常见的应用场景是两个一是驱动HMI显示设备的底层状态字二是接收第三方分析仪如尾气分析仪的通信数据。仪表返回的数据通常是16位字每一位代表一个状态位。比如DO变送器的状态字Bit0表示传感器连接、Bit1表示温度补偿故障、Bit2表示传感器极化电压异常。程序里通过SCL对Word做移位和按位与运算把每一位解析成独立布尔量再映射到报警DB。// 解析第三方设备状态字示意代码 #rawWord : Analyzer.StatusWord; #bitSensorErr : (WORD_TO_INT(#rawWord) AND 16#0002) 0; #bitPolarization : (WORD_TO_INT(#rawWord) AND 16#0004) 0;这一小段逻辑看着简单但如果不熟悉位操作现场排查通信问题时往往会一头雾水。4. HMI、SCADA与上层系统的数据交互4.1 博途集成HMI的变量连接方式这套程序里HMI用的是博途集成的WinCC RT与PLC通信采用的是标准以太网。我注意到原程序在HMI里没有胡点乱连PLC变量而是把所有需要显示的变量集中到一个“HMI接口DB”里HMI的画面直接连接这个DB。这样做最大的好处是网络负载小、变量关系清楚、画面快速刷新不卡顿。发酵画面每秒要刷新的数据不少温度、DO、pH、转速、各阀门状态、批次剩余时间如果每个控件都单独连PLC变量HMI通信压力会明显增大。集中到接口DB后可以统一设置通信周期比如曲线显示变量用250ms刷新普通状态量用1秒刷新。另外V16里1200的DB访问分为优化访问和非优化访问两种方式。优化访问数据块无法被第三方软件用绝对地址直接访问如果后续要对接SCADA或者用S7协议读数据这一点要格外注意。我通常会把给上位机用的数据单独放在“非优化访问”的通信DB里并且地址规划成对齐的Word/DWord结构方便Modbus TCP和S7通信时做地址映射。4.2 Modbus TCP与SCADA/MES对接的寄存器映射制药车间不可能永远只有本地HMI迟早要接SCADA或MES。这套1200程序里预留了一个Modbus TCP服务器通信块把需要给上层读的数据统一映射到保持寄存器区。寄存器表设计非常经典我直接拿过来参考了一下40001-40020各罐温度PV/SP/CV以0.1℃为单位存为整数40021-40040pH和DO的PV/SP扩大10倍存储40041-40060搅拌频率、补料累计量、消泡次数40061-40080运行模式、步进号、报警状态字40081-40100批次号、配方号、批次起始时间戳。这里有个很重要的工程细节模拟量全部用扩大10倍或100倍的整数传输而不是直接传浮点数。原因是很多SCADA组态软件读32位浮点数涉及到字节序和内存对齐问题非常容易发生高低字节颠倒现场排查起来无比痛苦。用定点整数虽然损失了一点点精度但换来的是稳定可靠对于监控层面的系统完全够用。4.3 批次记录与电子签名别等验证时再补制药行业谈数据完整性和审计追踪已经是很正常的需求了。这套程序里虽然没直接跑MES但已经在PLC和HMI层面预留了批次记录能力。HMI上操作员必须有登录账号才能切换配方、修改设定值、启动SIP/CIP每一次关键操作都会写入报警/事件日志带有时间戳和操作员ID。发酵批次结束时HMI会将这个批次内的温度曲线、pH曲线、补料总量、报警记录打包成一个CSV文件存档留存到上位机服务器。这些功能如果等到FAT或者SAT工厂验收、现场验收阶段再要求补改动会很大而且验证文档的工程量会翻倍。所以如果你现在正在做类似项目哪怕业主还没提这些要求PLC里也要预留操作员管理变量和事件日志结构至少留出MES接口的DB和通信区域。这算是我做这类项目的血泪经验之一。5. 调试踩坑与常见问题排查实录5.1 博途V16连不上PLC的经典原因调试这套系统时我远程协助现场工程师查过几次“在线连接失败”。排查顺序基本固定先看电脑网卡能不能ping通PLC的IP再看博途“可访问设备”扫描结果最后检查PG/PC接口设置。最常见的坑是电脑装了虚拟机软件或者多个虚拟网卡导致博途扫描时默认走了错误的网卡明明PLC就在旁边却显示红色离线。解决方法是把除实际物理网卡外的其他网络接口临时禁用然后重新扫描。另一个常见问题是PLC的IP和电脑不在同一网段直接改电脑本地连接IP到192.168.0.x就能解决。还有一个隐蔽问题就是PLC固件版本和博途V16不匹配这时在线列表里能看到设备但项目里的设备会显示一个问号下载时提示版本不一致。5.2 模拟量信号漂移干扰怎么彻底处理发酵罐现场的变频器一启动温度变送器信号就在4.3mA和4.8mA之间跳这是调试期最让人崩溃的问题之一。我当时处理这套程序的AI通道漂移做了四件事之后彻底变稳信号线全程采用屏蔽双绞线屏蔽层在PLC柜侧单端接地变送器供电采用信号隔离栅隔离栅在配电柜内单独接地模拟量信号线敷设时避开变频器输出电缆间距保持在50cm以上程序中加了限幅滤波和一阶惯性滤波滤波时间常数设置为3秒。有一点必须提醒屏蔽层千万不要两端都接地否则会形成地环流低频干扰反而更大。如果是长距离传输还要注意信号源是两线制还是四线制配电方式不同接线方式完全不同接错的话没有任何输出或者直接烧掉模拟量模块。5.3 调节阀频繁动作导致执行器损坏现场最容易被忽略的是PID输出抖振。发酵罐温度到达设定值附近后如果死区设置过小比如0.1℃导致蒸汽阀和冷水阀在1%和0%之间来回切换调节阀的执行机构一天之内就可能会出问题。程序里我在PID_Compact的输出端又加了一个变化率限制块单次循环输出变化不超过0.5%同时PID内部死区改为0.2℃。这样阀门动作频率明显下降。这个优化不改变控制精度多少但能让执行器寿命提升好几倍。还有个经验调试时不要一上来就把PID目标值改到工艺值先用阶梯信号做扰动测试看系统响应曲线再决定积分时间放大还是缩小。很多人拿着PID参数表硬套效果往往很差。5.4 在线下载程序后设备瞬间跳停有一次调试CIP程序我在线修改了步进器某一步的条件然后执行“下载到运行设备”结果下载完成的瞬间罐上的几个阀门同时失电关闭泵全部停下来CIP程序直接跳回初始状态。原因其实很简单博途在线下载时背景DB的中间变量被初始化了步进值回到0同时输出刷新FC里的输出映像全部清零阀和泵自然全关。对于发酵这种对连续性要求高的工艺这种下载行为是不能接受的。我后来把顺控FB的步进值和关键输出状态全部定义成保持性变量Retain下载时选择“保持保持性存储区”选项就能避免这个问题。但这里有个前提程序逻辑本身要能处理“步进值保持但过程输出清零”的中间状态否则重新上电或下载后步进值还在输出却是0现场会懵。更稳妥的方案是下载前先将系统切到手动模式全自动发酵过程中尽量不要在线修改顺控逻辑调试工作放到批次间隙再做。5.5 强制变量这个功能能不用就不用调试初期我看到程序里一堆M0.0、M0.1的强制点估计之前的人为了模拟信号强了不少东西。强制功能在单机调试时确实方便但一到联动调试就容易翻车。有一次因为外设强制没有取消导致安全联锁一直处于绕过状态后面整套联调好几个小时找不到原因。在带顺控和联锁的发酵程序里强制点一旦忘了取消轻则动作异常重则锁不住阀。我的习惯是现场模拟信号尽量在硬件端子旁短接或用信号发生器给真实信号而不是用博途的强制功能。如果确实需要强制则现场必须有两个人在场一人操作强制一人确认取消清单调试结束后逐项核对强制表并拍照留档确认无误后再进入下一阶段。最后分享一个我实际做这套项目时觉得非常实用的小技巧把发酵罐所有FB的背景DB做成“多重背景”嵌套在主FB里而不是每个FB都单独建一个顶层DB。这样在程序树里看起来非常清爽复制整套程序到第二个罐时只需要复制主FB和对应的背景DB不需要七八个DB一起手动关联。我第二次把程序移植到另一台发酵罐上时大概只花了半天时间就完成了地址映射和参数替换。如果一开始就用凌乱的散DB结构这活起码要干两天而且大概率会漏改某个参数。做这类流程控制项目好的程序结构不是写出来给人看的是改起来让自己舒服的。