第二章:PLC基础回顾——工作原理、编程语言、数据类型与寻址方式

各位工程师朋友,大家好。这一章我们聊聊PLC的基础。我知道很多朋友觉得PLC基础太简单,直接上手干就完了。但说实话,我在现场调试伺服驱动时,遇到的大部分坑,根源都出在对PLC基础的理解不够扎实。你想想看,伺服跑飞了、位置对不上了,最后查出来往往是数据类型搞错了,或者寻址方式没搞对。所以,咱们还是踏踏实实把地基打牢。

2.1 PLC的工作原理:扫描周期与执行机制

PLC说白了就是一个循环执行的计算机。它不像我们写C语言那样顺序执行完就结束,而是周而复始地扫描。这个扫描周期,是理解一切PLC行为的基础。

一个完整的扫描周期包含三个阶段:

  1. 输入采样:PLC先把所有物理输入点的状态(比如按钮按没按、传感器通没通)一次性读入到内存的“输入映像区”。
  2. 程序执行:CPU从上到下、从左到右执行用户程序。注意,它只从输入映像区读数据,结果写到“输出映像区”。
  3. 输出刷新:程序执行完后,把输出映像区的数据一次性全部送到物理输出点(比如继电器、伺服使能信号)。

核心要点:PLC在一个扫描周期内,输入信号只在开始时采样一次,输出信号只在结束时刷新一次。程序执行过程中,即使外部输入变了,PLC也“视而不见”,直到下一个周期。

我在项目中遇到过这样一个问题:一个急停按钮,我用它来切断伺服使能。程序里我直接读急停的物理点,结果伺服有时能停,有时停不了。查了半天,发现是因为急停信号在程序中间被改变了,但PLC要到下一个周期才处理。后来我改成用立即刷新指令,问题才解决。嗯,这里要注意,立即刷新会延长扫描周期,别滥用。

为什么会这样?因为PLC的设计初衷是可靠性优先。它要保证在一个周期内,程序看到的输入状态是“一致”的,输出状态也是“一致”的。这和我们伺服驱动的实时性要求有时是矛盾的,联调时一定要心里有数。

2.2 常用编程语言:梯形图与结构化文本(ST)

PLC的编程语言有很多种,但咱们做伺服驱动联调,最常用的就两种:梯形图(LD)结构化文本(ST)

2.2.1 梯形图(LD)—— 电气工程师的“母语”

梯形图,说白了就是把继电器电路图“翻译”成PLC能懂的语言。它直观、易读,适合做逻辑控制和顺序控制。

我个人习惯,凡是涉及互锁、使能、报警这类逻辑,都用梯形图。因为一眼就能看出逻辑关系,现场调试时拿万用表一量,心里踏实。

举个例子,伺服驱动的“使能”逻辑:

// 梯形图示例:伺服使能控制
// 条件:急停未按下 & 无报警 & 启动按钮按下
// 输出:伺服使能线圈

| 急停常闭 | 报警常闭 | 启动按钮 | 伺服使能 |
|----|----|----|----|
|--||--+--||--+--||--+--( )--|
|    |    |    | 自锁触点 |
|    |    |    |--||--|

你看,这个逻辑用梯形图画出来,谁都能看懂。但梯形图有个缺点:处理复杂数学运算和数组时,非常痛苦。比如你要算一个S型速度曲线,用梯形图写,那代码量能让你怀疑人生。

2.2.2 结构化文本(ST)—— 高级语言的“降维打击”

ST语言,长得像Pascal或C语言。它适合做数据处理、算法实现、通讯解析。我个人建议,凡是涉及位置计算、速度规划、PID调节,都用ST写。

比如,计算伺服的目标位置:

// ST语言示例:计算绝对位置
IF bStart THEN
    // 目标位置 = 当前位置 + 脉冲增量
    lTargetPos := lCurrentPos + lPulseIncrement;
    
    // 限位保护
    IF lTargetPos > lMaxPos THEN
        lTargetPos := lMaxPos;
        bLimitAlarm := TRUE;
    END_IF;
    
    // 写入伺服驱动器
    uaSetPosition(lTargetPos);
END_IF;

你看,用ST写,逻辑清晰,变量名一看就懂。而且ST支持数组、结构体、函数,写复杂控制逻辑非常方便。

我的建议:梯形图做“壳”,ST做“核”。外壳逻辑(使能、报警、模式切换)用梯形图,核心算法(位置计算、速度规划)用ST。这样既好读,又高效。

2.3 数据类型:别让“整型”和“浮点”坑了你

数据类型,是PLC编程里最容易出问题的地方。我在现场见过太多因为数据类型不匹配导致的“灵异事件”。

PLC常用的数据类型有:

类型 关键字 位数 范围 典型用途
布尔 BOOL 1位 TRUE / FALSE 开关信号、使能位
字节 BYTE 8位 0~255 状态字、小数据
整型 INT 16位 -32768~32767 计数器、小范围位置
双整型 DINT 32位 -2^31~2^31-1 编码器位置、大范围计数
浮点 REAL 32位 ±1.18e-38 ~ ±3.4e38 速度、加速度、PID参数

避坑指南:我曾经在调试一个电子凸轮项目时,用INT类型存储编码器位置。结果运行到一半,位置突然跳变。查了一下午,才发现是编码器位置超过了32767,INT溢出了。从那以后,凡是涉及位置、脉冲数,一律用DINT。记住,伺服编码器动不动就是几百万脉冲,INT根本不够用。

还有一个常见坑:浮点数的精度问题。REAL类型只有32位,精度约7位有效数字。如果你要计算高精度的位置,比如0.0001mm级别,REAL可能会丢精度。这时候,我建议用LREAL(64位浮点),或者干脆用DINT做定点数运算。

2.4 寻址方式:找到你想要的“那个”数据

寻址,就是告诉PLC“你要操作哪个数据”。PLC的寻址方式比计算机简单,但也有一些细节需要注意。

2.4.1 直接寻址

最常用的方式。直接指定地址,比如:

  • %I0.0:输入点,第0个模块的第0个通道
  • %Q1.2:输出点,第1个模块的第2个通道
  • %MW100:内存字,地址100

直接寻址简单粗暴,但可读性差。我一般只在简单的逻辑里用,复杂程序里还是用符号寻址。

2.4.2 符号寻址(推荐)

给变量起个名字,比如 bServoEnablelActualPosition。程序里直接用名字,PLC自动映射到物理地址。

这样做的好处是:程序可读性强,移植方便。你想想看,如果程序里全是 %MW100,三个月后你自己都看不懂。

2.4.3 间接寻址(指针)

这个在伺服联调里用得不多,但处理数组时很有用。比如你要批量读取10个轴的位置:

// 间接寻址示例:循环读取轴位置
FOR i := 0 TO 9 DO
    // 通过指针访问数组元素
    lPosArray[i] := uaReadPosition(pAxisBase + i * 4);
END_FOR;

注意,不同PLC的间接寻址语法差别很大,用之前一定要看手册。

2.5 知识体系总览

为了让你对本章内容有个整体印象,我画了一张图。这张图把PLC基础的核心知识点串了起来,你一看就明白它们之间的关系。

PLC基础回顾 工作原理 输入采样 程序执行 输出刷新 编程语言 梯形图(LD) 结构化文本(ST) 数据类型 BOOL INT/DINT REAL 寻址方式 直接/符号/间接

这张图把PLC基础的四个核心模块串起来了。你记住:工作原理是“骨架”,编程语言是“血肉”,数据类型是“细胞”,寻址方式是“神经”。四者缺一不可。

个人经验:每次开始一个新项目,我都会花半小时把PLC的数据类型和寻址方式先规划好。变量命名规范、数据类型选对、地址分配合理,后面写程序就像搭积木一样顺畅。如果这一步偷懒,后面调试时你会花十倍的时间来填坑。

好了,这一章的内容就到这里。PLC基础看似简单,但它是伺服驱动联调的基石。下一章,我们会正式进入伺服驱动的世界,聊聊它的内部结构和控制模式。到时候你会发现,今天讲的这些基础,全都会用上。


公众号:蓝海资料掘金营,微信deep3321