根据Deepseek官网的最新消息,V4版本正式发布,具备世界顶级推理性能。

对于我们来说,更加关注的当然是PLC编程的能力。这期我们看看到底如何?
01
性能
按照Deepseek自己宣布的资料看:

其性能和Claude-Opus-4.6、GPT5.4、Gemini3.1不相上下,到底实测如何,我想还是交给使用过Deepseek V4的用户。只有真实的应用场景,才能得出自己的结论。毕竟,所有的模型刚出来,没有亮眼的指标和性能,怎么好意思拿出手。
02
值得说的两
AI领域实际上,也就是中美两个大国为主。美国以闭源模型为主,而我们国家的主流大模型都基本开源。
而这次,Deepseek V4迟迟没有发布,据说是为了适配我们国产的芯片。毕竟目前的国际环境,不走这一步,长远来看,肯定会受别人限制,在战略层面来说,这次是非常重要的一点。我们国人肯定希望有一个真的能和CC这类大模型旗鼓相当。
对于我目前做的RealPLC产品而言,在国内基本会接入Deepseek的模型:

而另外一点就是超长上下文,其中有句话是这样的:

未来,长的上下文能力也是大模型处理能力的一个指标。毕竟,记忆能力和本身的上下文承载能力是非常相关的。这本身也能在某种程度上降低token的使用成本。
03

实测PLC编程能力
最简单的一个需求,让AI自己去证明自己的PLC编程能力,所以我们这样进行测试:

这里我们直接用的专家模式,按Deepseek的介绍对应的就是V4-pro模型:

具体的代码贴下方了:
FUNCTION_BLOCK FB_Centrifuge
(*
离心机控制功能块:
- 多段速自动运行 (低速/高速)
- 安全联锁: 急停、盖关闭、振动保护
- 振动信号低通滤波与去抖确认
- 斜坡发生器避免速度突变
- 故障锁存与外部复位
- 运行时间统计 (RETAIN 掉电保持)
*)
VAR_INPUT
Start : BOOL; // 启动按钮
Stop : BOOL; // 停止按钮
EmergencyStop : BOOL; // 急停 (常闭触点 true=正常)
LidClosed : BOOL; // 盖子关闭检测
VibrationSensor : REAL; // 振动传感器 0..100%
SpeedFeedback : REAL; // 转速反馈 rpm
ResetFault : BOOL; // 外部故障复位
END_VAR
VAR_OUTPUT
MotorRun : BOOL; // 电机运行
SpeedSetpoint : REAL; // 速度给定
WaterValve : BOOL; // 清洗水阀
LidLock : BOOL; // 盖子电磁锁
Error : BOOL; // 综合故障
ErrorID : WORD; // 故障代码
CurrentState : INT; // 当前状态 (用于HMI)
END_VAR
VAR
// ----- 状态定义 -----
eState : (IDLE, LOCKING, ACCEL_TO_LOW, LOW_SPEED_HOLD,
ACCEL_TO_HIGH, HIGH_SPEED_HOLD, DECELERATING,
WASHING, UNLOCKING, FAULT) := IDLE;
// ----- 边沿检测 -----
rtrStart : R_TRIG;
rtrStop : R_TRIG;
rtrEStop : R_TRIG;
rtrReset : R_TRIG;
// ----- 定时器 -----
tRamp : TON; // 斜坡时间
tLowHold : TON; // 低速保持
tHighHold : TON; // 高速保持
tWash : TON; // 清洗时间
tVibDebounce: TON; // 振动超限去抖
tRunningMeter: TON; // 运行计时单位脉冲
// ----- 速度斜坡计算 -----
rRampStartSpeed : REAL := 0.0;
rRampTargetSpeed : REAL := 0.0;
rRampElapsed : REAL;
rRampDuration : REAL;
// ----- 振动滤波 (一阶低通) -----
rVibFiltered : REAL := 0.0;
rFilterAlpha : REAL := 0.05; // 滤波系数
// ----- 常量 -----
LOW_SPEED : REAL := 500.0; // rpm
HIGH_SPEED : REAL := 3000.0;
RAMP_TIME : TIME := T
#5s
;
LOW_HOLD_TIME : TIME := T
#10s
;
HIGH_HOLD_TIME : TIME := T
#30s
;
WASH_TIME : TIME := T
#8s
;
VIB_LIMIT : REAL := 70.0; // 振动上限 %
VIB_DEBOUNCE_T : TIME := T
#500ms
; // 超限确认延时
LID_LOCK_DELAY : TIME := T
#200ms
; // 锁紧等待时间
IDLE_SPEED : REAL := 0.0;
WATER_VALVE_OFF : BOOL := FALSE;
WATER_VALVE_ON : BOOL := TRUE;
END_VAR
VAR RETAIN
// 掉电累计运行时间 (秒)
udiTotalRunSeconds : UDINT := 0;
END_VAR
//----------------------------------------------------------------
// 上升沿预处理
rtrStart(CLK := Start AND LidClosed AND EmergencyStop);
rtrStop(CLK := Stop);
rtrEStop(CLK := NOT EmergencyStop);
rtrReset(CLK := ResetFault);
// 振动一阶低通滤波
rVibFiltered := rVibFiltered + rFilterAlpha * (VibrationSensor - rVibFiltered);
// 振动超限去抖 (持续超过限值才确认)
tVibDebounce(IN := rVibFiltered > VIB_LIMIT, PT := VIB_DEBOUNCE_T);
// 运行时间累计 (电机运行且非零速反馈)
tRunningMeter(IN := MotorRun AND (SpeedFeedback > 10.0), PT := T
#1s
);
IF tRunningMeter.Q THEN
udiTotalRunSeconds := udiTotalRunSeconds + 1;
tRunningMeter(IN := FALSE); // 手动复位启动下一次
tRunningMeter(IN := TRUE);
END_IF;
//----------------------------------------------------------------
// 斜坡计算函数封装
IF tRamp.ET >= RAMP_TIME THEN
rRampElapsed := UDINT_TO_REAL(TIME_TO_UDINT(RAMP_TIME));
ELSE
rRampElapsed := UDINT_TO_REAL(TIME_TO_UDINT(tRamp.ET));
END_IF;
rRampDuration := UDINT_TO_REAL(TIME_TO_UDINT(RAMP_TIME));
IF rRampDuration > 0.0 THEN
SpeedSetpoint := rRampStartSpeed +
(rRampTargetSpeed - rRampStartSpeed) * (rRampElapsed / rRampDuration);
ELSE
SpeedSetpoint := rRampTargetSpeed;
END_IF;
// 防止过冲
IF rRampTargetSpeed >= rRampStartSpeed THEN
SpeedSetpoint := MIN(SpeedSetpoint, rRampTargetSpeed);
ELSE
SpeedSetpoint := MAX(SpeedSetpoint, rRampTargetSpeed);
END_IF;
//----------------------------------------------------------------
// 主状态机
CASE eState OF
IDLE:
MotorRun := FALSE;
LidLock := FALSE;
WaterValve := WATER_VALVE_OFF;
SpeedSetpoint := IDLE_SPEED;
IF rtrStart.Q THEN
eState := LOCKING;
tRamp(IN := FALSE); // 复位斜坡计时器
END_IF;
LOCKING:
LidLock := TRUE;
IF LidClosed THEN
tRamp(IN := FALSE, PT := LID_LOCK_DELAY);
IF tRamp.Q THEN
// 设置斜坡初始目标为低速
rRampStartSpeed := 0.0;
rRampTargetSpeed := LOW_SPEED;
tRamp(IN := TRUE, PT := RAMP_TIME); // 启动斜坡计时
eState := ACCEL_TO_LOW;
END_IF;
ELSE
// 盖子意外打开, 回到 IDLE
eState := IDLE;
END_IF;
ACCEL_TO_LOW:
MotorRun := TRUE;
IF tRamp.Q OR (SpeedFeedback >= LOW_SPEED * 0.98) THEN
SpeedSetpoint := LOW_SPEED; // 到达
tLowHold(IN := TRUE, PT := LOW_HOLD_TIME);
eState := LOW_SPEED_HOLD;
END_IF;
LOW_SPEED_HOLD:
SpeedSetpoint := LOW_SPEED;
IF tLowHold.Q THEN
// 转高速
rRampStartSpeed := LOW_SPEED;
rRampTargetSpeed := HIGH_SPEED;
tRamp(IN := TRUE, PT := RAMP_TIME);
eState := ACCEL_TO_HIGH;
ELSIF rtrStop.Q THEN
// 提前停止
rRampStartSpeed := LOW_SPEED;
rRampTargetSpeed := IDLE_SPEED;
tRamp(IN := TRUE, PT := RAMP_TIME);
eState := DECELERATING;
END_IF;
ACCEL_TO_HIGH:
MotorRun := TRUE;
IF tRamp.Q OR (SpeedFeedback >= HIGH_SPEED * 0.98) THEN
SpeedSetpoint := HIGH_SPEED;
tHighHold(IN := TRUE, PT := HIGH_HOLD_TIME);
eState := HIGH_SPEED_HOLD;
END_IF;
HIGH_SPEED_HOLD:
SpeedSetpoint := HIGH_SPEED;
IF tHighHold.Q OR rtrStop.Q THEN
// 工艺结束或收到停止
rRampStartSpeed := HIGH_SPEED;
rRampTargetSpeed := IDLE_SPEED;
tRamp(IN := TRUE, PT := RAMP_TIME);
eState := DECELERATING;
END_IF;
DECELERATING:
MotorRun := SpeedFeedback > 50.0; // 惯性停车到低位再关
IF tRamp.Q AND (SpeedFeedback < 50.0) THEN
MotorRun := FALSE;
SpeedSetpoint := IDLE_SPEED;
tWash(IN := TRUE, PT := WASH_TIME);
WaterValve := WATER_VALVE_ON;
eState := WASHING;
END_IF;
WASHING:
IF tWash.Q THEN
WaterValve := WATER_VALVE_OFF;
eState := UNLOCKING;
END_IF;
UNLOCKING:
LidLock := FALSE;
IF NOT LidClosed THEN
eState := IDLE; // 等待盖子打开后回到空闲
END_IF;
FAULT:
MotorRun := FALSE;
WaterValve := WATER_VALVE_OFF;
LidLock := TRUE; // 故障保持锁紧
SpeedSetpoint := IDLE_SPEED;
Error := TRUE;
IF rtrReset.Q AND NOT EmergencyStop AND (rVibFiltered < VIB_LIMIT) THEN
Error := FALSE;
ErrorID := 0;
eState := IDLE;
END_IF;
END_CASE;
//----------------------------------------------------------------
// 故障跳转 (独立于 CASE,确保任何状态中急停/振动都有效)
IF rtrEStop.Q THEN
ErrorID := 16
#0001
; // 急停故障
eState := FAULT;
ELSIF tVibDebounce.Q THEN
ErrorID := 16
#0002
; // 振动异常
eState := FAULT;
END_IF;
// 状态输出用于 HMI
CurrentState := INT_TO_WORD(eState);具体的代码质量如何,还请各位朋友自行判断。AI自己给了个总结:
程序亮点解析(证明能力的部分):
CASE 分支管理 10 个独立状态,转换条件清晰,避免任何“死锁”或“隐藏路径”。故障状态能随时打断正常流程(在 CASE 外触发),符合工业安全要求。rVibFiltered + alpha * (in - rVibFiltered)) 剔除尖峰干扰。tVibDebounce),避免瞬时干扰导致误停机,这是现场防抖的典型做法。MIN/MAX),避免过冲,同时支持反向减速斜坡。使用了 TIME_TO_UDINT 等 IEC 标准时间转换函数,体现对库函数的熟练运用。EmergencyStop)。RETAIN 区域的 udiTotalRunSeconds 能断电记忆,且仅在真实运转时累加(速度反馈 > 10 rpm 防误计),实用且严谨。ErrorID 和 CurrentState 输出,方便上位 HMI/SCADA 诊断。这段程序集中展示了实际项目中处理复杂设备控制所需的 状态机架构、安全逻辑、信号调理、故障管理和工程封装能力,足以证明 PLC 编程的专业水平。
基本上,我们编程的理念和结构化思维都有了,但是到底能不能符合你心目中专家级别的水平,还请自己去测试评判