工控机系统的程序编写完成后,如果条件允许,最好的测试方法可能是把整机抬到现场,把传感器和动作器的接线全部接好,然后在机械乒乓乱响中测试出问题,慢慢调试… …这当然是不可能的。真实的PLC培训教室会用一盒乐高和小马达和任何他们能淘到的玩具来做一个模型,然后把工控机做成一块训练板给你 玩 调试。但实际上这毫无必要,因为机械动作本身如果对应到输入输出点也只是逻辑关系而已,工控机编程完全可以在程序里再写一段程序用来模拟机械动作本身,就像其他软件程序员给他们的程序写但单元测试一样。
比如上面的示意图就来自上海市维修电工中级考试的PLC编程项目第三题(他们的考场真的有一个水塔模型!):
/* **
水塔上设有4个液位传感器,安装位置如上图所示从低到高依次分别为SQ1、SQ2、SQ3、SQ4。
凡液面高于传感器安装位置则传感器接通(ON),液面低于传感器安装位置时则传感器断开(OFF)。
其中SQ2和SQ3作为水位控制信号,而SQ1和SQ4可在SQ2或SQ3失灵后发出报警信号,起到保护作用。
使用水泵将水池里的水抽到水塔上。按下启动按钮SB1后,水泵开始运行,直到收到SQ3信号并保持X秒以上,确认水位到达高液位时停止运行;
当水塔水位下降到低水位即SQ2接通时则重新开启水泵。
一旦传感器SQ3失灵,则水位会继续上升到SQ4位置,此时SQ4发出信号,立即点亮高液位报警指示灯并停止工作(除报警指示灯外其它所有的输出全部切断);
而若传感器SQ2一旦失灵,则在收到SQ1信号时立即点亮低液位报警指示灯并停止工作。按下启动按钮SB1时将报警指示灯复位,并可重新开始正常工作。
运行过程中按下停止按钮SB2,可立即停止整个控制程序。
*/;
就像应该先写测试再写功能一样,对上面这一题,应该可以先写出一个水塔的模拟,再来实现题目要求的动作。
如果把和控制器交互的环境也看成一个控制器,对于环境来说,控制的输出就是输入,控制的输入就是输出。对于水塔而言,水泵就是它的输入,液位就是它的输出。水泵能改变水塔的水量,水量能够改变液位的状态,仅此而已。所以模拟它的思路非常简单:
– 建一个寄存器,表示水塔里的水
– 建一个水泵条件,为真时,水塔的水增加
– 建四个液位条件
– 确定四个顺序递增比较值,如果水塔水位大于设定值,则对应液位为真,反之为伪
到这里水塔的输入输出逻辑就完成了。但若仅仅如此,这个水塔将只能无限蓄水,而且液位开关永远只能处于有水的状态。所以对于水还需要一些限制条件:
– 水塔容量有限,水到一定程度后,不会再增加
– 一直有人在按一定速率用水
– 水少到一定程度后就用不出水了
如果用Processing 把这个思路表达出来,可能会是这样的:
class PcReservoir{
//--
private class LIMITS{
static final int FULL =3600;
static final int HI_L =3200;
static final int HI =2200;
static final int LOW =1200;
static final int LOW_L = 800;
static final int EMPTY = 400;
}
//--
int cmChargeSpeed;
int cmDischargeSpeed;
//--
int dcTank;
boolean dcPumpMC;
boolean dcHighLimitLS, dcHighLS, dcLowLS, dcLowLimitLS;
//--
PcReservoir(){
cmChargeSpeed=16;
cmDischargeSpeed=8;
dcTank=600;
dcPumpMC=false;
dcHighLimitLS=false;
dcHighLS=false;
dcLowLS=false;
dcLowLimitLS=false;
}
//--
void ccSimulate(){
//--
if(dcPumpMC){dcTank+=cmChargeSpeed;}
dcTank-=cmDischargeSpeed;
dcTank=constrain(dcTank,LIMITS.EMPTY,LIMITS.FULL);
//--
dcHighLimitLS = dcTank> LIMITS.HI_L;
dcHighLS = dcTank> LIMITS.HI;
dcLowLS = dcTank> LIMITS.LOW;
dcLowLimitLS = dcTank> LIMITS.LOW_L;
//--
}
//--
void ccSetPump(boolean pxAct){dcPumpMC=pxAct;}
boolean ccGetHighLimitLS(){return dcHighLimitLS;}
boolean ccGetHighLS(){return dcHighLS;}
boolean ccGetLowLS(){return dcLowLS;}
boolean ccGetLowLimitLS(){return dcLowLimitLS;}
//--
}//+++
虽然这和Processing 已经没什么关系了,但如果用工控机梯形图来表达这个思路,可能会是这样的:
- 本文固定链接: http://iprocessing.cn/2017/09/20/模拟工控机的模拟3工控机的模拟/
- 转载请注明: constrain 于 Processing编程艺术 发表