工业通用 PLC 分拣模板!传感器去抖 + 气缸互锁 + 状态机 + 超时报警全套

摘要

可编程逻辑控制器(PLC)是工业自动化领域的核心控制设备,广泛应用于制造业、能源、交通等行业。本文从PLC的基本原理出发,深入讲解IEC 61131-3标准下的结构化文本(ST)编程语言,通过一个完整的物料分拣控制系统案例,展示从需求分析、程序架构设计到代码实现的全流程。文章提供可直接运行的Codesys环境代码,并针对工程实践中的常见问题给出解决方案,帮助读者建立从理论到落地的完整知识体系。

应用场景

PLC控制系统在以下工业场景中具有不可替代的作用:

  1. 离散制造:汽车焊装线、电子装配线、包装机械的顺序控制与联锁保护
  2. 过程控制:化工反应釜温度PID调节、水处理厂流量比例控制
  3. 运动控制:伺服电机定位、传送带同步、机器人轨迹插补
  4. 能源管理:变电站自动切换、楼宇空调能效优化、光伏逆变器并网控制

本文以"三色物料分拣系统"为案例,模拟实际产线中根据物料颜色(红/绿/蓝)进行分拣的典型场景,涵盖传感器输入、逻辑判断、执行器输出、故障处理等完整控制链。

核心原理

1. PLC扫描周期

PLC采用循环扫描工作方式,每个扫描周期分为三个阶段:

  • 输入采样:将物理输入信号(传感器、按钮)读入输入映像区
  • 程序执行:CPU逐行执行用户程序,结果存入输出映像区
  • 输出刷新:将输出映像区数据一次性写入物理输出点(电磁阀、电机)

理解扫描周期对程序实时性至关重要:同一周期内,输入状态在程序执行过程中保持不变,输出状态在周期结束时统一更新。

2. 结构化文本(ST)语言特性

ST语言基于Pascal语法,具有以下核心要素:

  • 变量声明:VAR/END_VAR块定义局部变量,VAR_INPUT/END_VAR定义输入参数
  • 数据类型:BOOL、INT、REAL、TIME、ARRAY、STRUCT
  • 控制结构:IF-THEN-ELSIF-ELSE、CASE、FOR、WHILE、REPEAT
  • 函数与功能块:可重用代码模块,支持输入输出参数

3. 状态机设计模式

工业控制中推荐使用有限状态机(FSM)实现逻辑清晰、易于维护的程序架构。本文采用三状态模型:

  • IDLE:待机状态,等待启动信号
  • RUNNING:运行状态,执行分拣逻辑
  • ERROR:错误状态,触发报警并保持安全状态

详细步骤

步骤1:系统硬件配置

假设硬件配置如下:

  • CPU:Codesys Control Win V3(仿真环境)
  • 数字量输入:3个颜色传感器(DI0=红,DI1=绿,DI2=蓝),1个启动按钮(DI3),1个急停按钮(DI4)
  • 数字量输出:3个推杆气缸(DO0=红料仓,DO1=绿料仓,DO2=蓝料仓),1个传送带电机(DO3),1个报警灯(DO4)

步骤2:程序架构设计

采用分层架构:

  1. 主程序(Main):循环调用各功能块
  2. 状态机管理(FSM_Manager):处理系统状态切换
  3. 传感器处理(Sensor_Handler):去抖滤波与信号确认
  4. 执行器控制(Actuator_Control):输出逻辑与互锁保护
  5. 故障诊断(Fault_Diagnosis):超时监控与错误处理

步骤3:变量定义

在全局变量列表中定义:

objectivec 复制代码
VAR_GLOBAL
    // 系统状态枚举
    eSystemState : INT := 0; // 0=IDLE, 1=RUNNING, 2=ERROR
    
    // 输入映射(实际项目中会通过IO映射)
    Sensor_Red : BOOL := FALSE;
    Sensor_Green : BOOL := FALSE;
    Sensor_Blue : BOOL := FALSE;
    Start_Button : BOOL := FALSE;
    Emergency_Stop : BOOL := FALSE;
    
    // 输出映射
    Cylinder_Red : BOOL := FALSE;
    Cylinder_Green : BOOL := FALSE;
    Cylinder_Blue : BOOL := FALSE;
    Conveyor_Motor : BOOL := FALSE;
    Alarm_Lamp : BOOL := FALSE;
    
    // 内部变量
    Conveyor_Timer : TON; // 传送带运行计时
    Sensor_Debounce : TON; // 传感器去抖
    Fault_Code : INT := 0; // 故障代码
END_VAR

步骤4:主程序编写

主程序采用结构化文本,实现状态机循环:

ini 复制代码
PROGRAM Main
VAR
    // 功能块实例化
    fsm : FSM_Manager;
    sensor : Sensor_Handler;
    actuator : Actuator_Control;
    fault : Fault_Diagnosis;
    
    // 临时变量
    currentState : INT;
    sensorValue : ARRAY[0..2] OF BOOL;
    cmdCylinder : ARRAY[0..2] OF BOOL;
    cmdConveyor : BOOL;
    cmdAlarm : BOOL;
END_VAR

// 主扫描周期逻辑
// 第一步:读取物理输入(仿真环境直接读取全局变量)
sensorValue[0] := Sensor_Red;
sensorValue[1] := Sensor_Green;
sensorValue[2] := Sensor_Blue;

// 第二步:传感器去抖处理
sensor(
    rawInputs := sensorValue,
    debounceTime := T#50MS,
    filteredOutputs => sensorValue
);

// 第三步:状态机管理
fsm(
    startSignal := Start_Button,
    emergencyStop := Emergency_Stop,
    faultCode := Fault_Code,
    currentState => currentState
);

// 第四步:根据当前状态执行控制逻辑
CASE currentState OF
    0: // IDLE状态
        cmdConveyor := FALSE;
        cmdCylinder[0] := FALSE;
        cmdCylinder[1] := FALSE;
        cmdCylinder[2] := FALSE;
        cmdAlarm := FALSE;
        
    1: // RUNNING状态
        // 传送带持续运行
        cmdConveyor := TRUE;
        
        // 颜色判断与推杆控制
        IF sensorValue[0] THEN
            cmdCylinder[0] := TRUE;
        ELSIF sensorValue[1] THEN
            cmdCylinder[1] := TRUE;
        ELSIF sensorValue[2] THEN
            cmdCylinder[2] := TRUE;
        ELSE
            // 无物料时所有推杆复位
            cmdCylinder[0] := FALSE;
            cmdCylinder[1] := FALSE;
            cmdCylinder[2] := FALSE;
        END_IF
        
        // 故障检测:如果多个传感器同时触发,视为异常
        IF (sensorValue[0] AND sensorValue[1]) OR
           (sensorValue[0] AND sensorValue[2]) OR
           (sensorValue[1] AND sensorValue[2]) THEN
            Fault_Code := 1; // 传感器冲突故障
        END_IF
        
    2: // ERROR状态
        cmdConveyor := FALSE;
        cmdCylinder[0] := FALSE;
        cmdCylinder[1] := FALSE;
        cmdCylinder[2] := FALSE;
        cmdAlarm := TRUE; // 报警灯常亮
END_CASE

// 第五步:执行器输出(含互锁保护)
actuator(
    cmdConveyor := cmdConveyor,
    cmdCylinders := cmdCylinder,
    emergencyStop := Emergency_Stop,
    conveyorOut => Conveyor_Motor,
    cylinderOuts => [Cylinder_Red, Cylinder_Green, Cylinder_Blue],
    alarmOut => Alarm_Lamp
);

// 第六步:故障诊断(超时监控等)
fault(
    conveyorRunning := Conveyor_Motor,
    timeout := T#10S,
    faultCode => Fault_Code
);

步骤5:功能块实现

FSM_Manager功能块:

go 复制代码
FUNCTION_BLOCK FSM_Manager
VAR_INPUT
    startSignal : BOOL;
    emergencyStop : BOOL;
    faultCode : INT;
END_VAR
VAR_OUTPUT
    currentState : INT;
END_VAR
VAR
    prevStart : BOOL := FALSE;
    stateTimer : TON;
END_VAR

// 状态切换逻辑
IF emergencyStop THEN
    // 急停直接进入ERROR状态
    currentState := 2;
ELSIF faultCode > 0 THEN
    // 故障进入ERROR状态
    currentState := 2;
ELSE
    CASE currentState OF
        0: // IDLE
            // 检测到启动信号的上升沿
            IF startSignal AND NOT prevStart THEN
                currentState := 1;
                stateTimer(IN := TRUE, PT := T#0S);
            END_IF
            
        1: // RUNNING
            // 运行中检测到停止信号或故障
            IF NOT startSignal THEN
                currentState := 0;
            END_IF
            
        2: // ERROR
            // 故障复位条件:急停释放且故障代码清零
            IF NOT emergencyStop AND faultCode = 0 THEN
                currentState := 0;
            END_IF
    END_CASE
END_IF

// 保存上次启动信号状态用于上升沿检测
prevStart := startSignal;

Sensor_Handler功能块:

ini 复制代码
FUNCTION_BLOCK Sensor_Handler
VAR_INPUT
    rawInputs : ARRAY[0..2] OF BOOL;
    debounceTime : TIME;
END_VAR
VAR_OUTPUT
    filteredOutputs : ARRAY[0..2] OF BOOL;
END_VAR
VAR
    debounceTimers : ARRAY[0..2] OF TON;
    stableStates : ARRAY[0..2] OF BOOL := [FALSE, FALSE, FALSE];
END_VAR

// 对每个传感器进行去抖处理
FOR idx := 0 TO 2 DO
    // 当输入为TRUE时启动计时器
    IF rawInputs[idx] THEN
        debounceTimers[idx](IN := TRUE, PT := debounceTime);
        // 计时到达后输出稳定状态
        IF debounceTimers[idx].Q THEN
            stableStates[idx] := TRUE;
        END_IF
    ELSE
        // 输入为FALSE时立即复位
        debounceTimers[idx](IN := FALSE);
        stableStates[idx] := FALSE;
    END_IF
    
    filteredOutputs[idx] := stableStates[idx];
END_FOR

Actuator_Control功能块:

ini 复制代码
FUNCTION_BLOCK Actuator_Control
VAR_INPUT
    cmdConveyor : BOOL;
    cmdCylinders : ARRAY[0..2] OF BOOL;
    emergencyStop : BOOL;
END_VAR
VAR_OUTPUT
    conveyorOut : BOOL;
    cylinderOuts : ARRAY[0..2] OF BOOL;
    alarmOut : BOOL;
END_VAR

// 急停状态下所有输出强制关闭
IF emergencyStop THEN
    conveyorOut := FALSE;
    cylinderOuts[0] := FALSE;
    cylinderOuts[1] := FALSE;
    cylinderOuts[2] := FALSE;
    alarmOut := TRUE; // 急停时报警
ELSE
    // 正常输出
    conveyorOut := cmdConveyor;
    cylinderOuts[0] := cmdCylinders[0];
    cylinderOuts[1] := cmdCylinders[1];
    cylinderOuts[2] := cmdCylinders[2];
    alarmOut := FALSE;
END_IF

// 互锁保护:防止两个气缸同时动作(物理干涉)
IF cylinderOuts[0] AND cylinderOuts[1] THEN
    cylinderOuts[0] := FALSE;
    cylinderOuts[1] := FALSE;
END_IF
IF cylinderOuts[0] AND cylinderOuts[2] THEN
    cylinderOuts[0] := FALSE;
    cylinderOuts[2] := FALSE;
END_IF
IF cylinderOuts[1] AND cylinderOuts[2] THEN
    cylinderOuts[1] := FALSE;
    cylinderOuts[2] := FALSE;
END_IF

Fault_Diagnosis功能块:

ini 复制代码
FUNCTION_BLOCK Fault_Diagnosis
VAR_INPUT
    conveyorRunning : BOOL;
    timeout : TIME;
END_VAR
VAR_OUTPUT
    faultCode : INT;
END_VAR
VAR
    runTimer : TON;
END_VAR

// 传送带运行超时监控
IF conveyorRunning THEN
    runTimer(IN := TRUE, PT := timeout);
    IF runTimer.Q THEN
        // 传送带运行超过设定时间未停止,视为异常
        faultCode := 2; // 运行超时故障
    END_IF
ELSE
    runTimer(IN := FALSE);
    // 传送带停止后清除超时故障(如果只有此故障)
    IF faultCode = 2 THEN
        faultCode := 0;
    END_IF
END_IF

完整可运行代码

以下为Codesys环境下的完整项目代码(含注释),可直接复制到Codesys中创建新项目运行。

全局变量列表(GVL):

objectivec 复制代码
VAR_GLOBAL
    // 系统状态枚举
    eSystemState : INT := 0; // 0=IDLE, 1=RUNNING, 2=ERROR
    
    // 输入映射(仿真时手动赋值)
    Sensor_Red : BOOL := FALSE;
    Sensor_Green : BOOL := FALSE;
    Sensor_Blue : BOOL := FALSE;
    Start_Button : BOOL := FALSE;
    Emergency_Stop : BOOL := FALSE;
    
    // 输出映射
    Cylinder_Red : BOOL := FALSE;
    Cylinder_Green : BOOL := FALSE;
    Cylinder_Blue : BOOL := FALSE;
    Conveyor_Motor : BOOL := FALSE;
    Alarm_Lamp : BOOL := FALSE;
    
    // 内部变量
    Conveyor_Timer : TON; // 传送带运行计时
    Sensor_Debounce : TON; // 传感器去抖
    Fault_Code : INT := 0; // 故障代码
END_VAR

主程序(Main):

ini 复制代码
PROGRAM Main
VAR
    // 功能块实例化
    fsm : FSM_Manager;
    sensor : Sensor_Handler;
    actuator : Actuator_Control;
    fault : Fault_Diagnosis;
    
    // 临时变量
    currentState : INT;
    sensorValue : ARRAY[0..2] OF BOOL;
    cmdCylinder : ARRAY[0..2] OF BOOL;
    cmdConveyor : BOOL;
    cmdAlarm : BOOL;
END_VAR

// 主扫描周期逻辑
// 第一步:读取物理输入(仿真环境直接读取全局变量)
sensorValue[0] := Sensor_Red;
sensorValue[1] := Sensor_Green;
sensorValue[2] := Sensor_Blue;

// 第二步:传感器去抖处理
sensor(
    rawInputs := sensorValue,
    debounceTime := T#50MS,
    filteredOutputs => sensorValue
);

// 第三步:状态机管理
fsm(
    startSignal := Start_Button,
    emergencyStop := Emergency_Stop,
    faultCode := Fault_Code,
    currentState => currentState
);

// 第四步:根据当前状态执行控制逻辑
CASE currentState OF
    0: // IDLE状态
        cmdConveyor := FALSE;
        cmdCylinder[0] := FALSE;
        cmdCylinder[1] := FALSE;
        cmdCylinder[2] := FALSE;
        cmdAlarm := FALSE;
        
    1: // RUNNING状态
        // 传送带持续运行
        cmdConveyor := TRUE;
        
        // 颜色判断与推杆控制
        IF sensorValue[0] THEN
            cmdCylinder[0] := TRUE;
        ELSIF sensorValue[1] THEN
            cmdCylinder[1] := TRUE;
        ELSIF sensorValue[2] THEN
            cmdCylinder[2] := TRUE;
        ELSE
            // 无物料时所有推杆复位
            cmdCylinder[0] := FALSE;
            cmdCylinder[1] := FALSE;
            cmdCylinder[2] := FALSE;
        END_IF
        
        // 故障检测:如果多个传感器同时触发,视为异常
        IF (sensorValue[0] AND sensorValue[1]) OR
           (sensorValue[0] AND sensorValue[2]) OR
           (sensorValue[1] AND sensorValue[2]) THEN
            Fault_Code := 1; // 传感器冲突故障
        END_IF
        
    2: // ERROR状态
        cmdConveyor := FALSE;
        cmdCylinder[0] := FALSE;
        cmdCylinder[1] := FALSE;
        cmdCylinder[2] := FALSE;
        cmdAlarm := TRUE; // 报警灯常亮
END_CASE

// 第五步:执行器输出(含互锁保护)
actuator(
    cmdConveyor := cmdConveyor,
    cmdCylinders := cmdCylinder,
    emergencyStop := Emergency_Stop,
    conveyorOut => Conveyor_Motor,
    cylinderOuts => [Cylinder_Red, Cylinder_Green, Cylinder_Blue],
    alarmOut => Alarm_Lamp
);

// 第六步:故障诊断(超时监控等)
fault(
    conveyorRunning := Conveyor_Motor,
    timeout := T#10S,
    faultCode => Fault_Code
);

FSM_Manager功能块:

go 复制代码
FUNCTION_BLOCK FSM_Manager
VAR_INPUT
    startSignal : BOOL;
    emergencyStop : BOOL;
    faultCode : INT;
END_VAR
VAR_OUTPUT
    currentState : INT;
END_VAR
VAR
    prevStart : BOOL := FALSE;
    stateTimer : TON;
END_VAR

// 状态切换逻辑
IF emergencyStop THEN
    // 急停直接进入ERROR状态
    currentState := 2;
ELSIF faultCode > 0 THEN
    // 故障进入ERROR状态
    currentState := 2;
ELSE
    CASE currentState OF
        0: // IDLE
            // 检测到启动信号的上升沿
            IF startSignal AND NOT prevStart THEN
                currentState := 1;
                stateTimer(IN := TRUE, PT := T#0S);
            END_IF
            
        1: // RUNNING
            // 运行中检测到停止信号或故障
            IF NOT startSignal THEN
                currentState := 0;
            END_IF
            
        2: // ERROR
            // 故障复位条件:急停释放且故障代码清零
            IF NOT emergencyStop AND faultCode = 0 THEN
                currentState := 0;
            END_IF
    END_CASE
END_IF

// 保存上次启动信号状态用于上升沿检测
prevStart := startSignal;

Sensor_Handler功能块:

ini 复制代码
FUNCTION_BLOCK Sensor_Handler
VAR_INPUT
    rawInputs : ARRAY[0..2] OF BOOL;
    debounceTime : TIME;
END_VAR
VAR_OUTPUT
    filteredOutputs : ARRAY[0..2] OF BOOL;
END_VAR
VAR
    debounceTimers : ARRAY[0..2] OF TON;
    stableStates : ARRAY[0..2] OF BOOL := [FALSE, FALSE, FALSE];
END_VAR

// 对每个传感器进行去抖处理
FOR idx := 0 TO 2 DO
    // 当输入为TRUE时启动计时器
    IF rawInputs[idx] THEN
        debounceTimers[idx](IN := TRUE, PT := debounceTime);
        // 计时到达后输出稳定状态
        IF debounceTimers[idx].Q THEN
            stableStates[idx] := TRUE;
        END_IF
    ELSE
        // 输入为FALSE时立即复位
        debounceTimers[idx](IN := FALSE);
        stableStates[idx] := FALSE;
    END_IF
    
    filteredOutputs[idx] := stableStates[idx];
END_FOR

Actuator_Control功能块:

ini 复制代码
FUNCTION_BLOCK Actuator_Control
VAR_INPUT
    cmdConveyor : BOOL;
    cmdCylinders : ARRAY[0..2] OF BOOL;
    emergencyStop : BOOL;
END_VAR
VAR_OUTPUT
    conveyorOut : BOOL;
    cylinderOuts : ARRAY[0..2] OF BOOL;
    alarmOut : BOOL;
END_VAR

// 急停状态下所有输出强制关闭
IF emergencyStop THEN
    conveyorOut := FALSE;
    cylinderOuts[0] := FALSE;
    cylinderOuts[1] := FALSE;
    cylinderOuts[2] := FALSE;
    alarmOut := TRUE; // 急停时报警
ELSE
    // 正常输出
    conveyorOut := cmdConveyor;
    cylinderOuts[0] := cmdCylinders[0];
    cylinderOuts[1] := cmdCylinders[1];
    cylinderOuts[2] := cmdCylinders[2];
    alarmOut := FALSE;
END_IF

// 互锁保护:防止两个气缸同时动作(物理干涉)
IF cylinderOuts[0] AND cylinderOuts[1] THEN
    cylinderOuts[0] := FALSE;
    cylinderOuts[1] := FALSE;
END_IF
IF cylinderOuts[0] AND cylinderOuts[2] THEN
    cylinderOuts[0] := FALSE;
    cylinderOuts[2] := FALSE;
END_IF
IF cylinderOuts[1] AND cylinderOuts[2] THEN
    cylinderOuts[1] := FALSE;
    cylinderOuts[2] := FALSE;
END_IF

Fault_Diagnosis功能块:

ini 复制代码
FUNCTION_BLOCK Fault_Diagnosis
VAR_INPUT
    conveyorRunning : BOOL;
    timeout : TIME;
END_VAR
VAR_OUTPUT
    faultCode : INT;
END_VAR
VAR
    runTimer : TON;
END_VAR

// 传送带运行超时监控
IF conveyorRunning THEN
    runTimer(IN := TRUE, PT := timeout);
    IF runTimer.Q THEN
        // 传送带运行超过设定时间未停止,视为异常
        faultCode := 2; // 运行超时故障
    END_IF
ELSE
    runTimer(IN := FALSE);
    // 传送带停止后清除超时故障(如果只有此故障)
    IF faultCode = 2 THEN
        faultCode := 0;
    END_IF
END_IF

运行结果说明

在Codesys仿真环境中运行上述程序,通过手动修改全局变量模拟输入,可观察到以下行为:

  1. 初始状态:系统处于IDLE状态(eSystemState=0),所有输出为FALSE
  2. 启动操作:将Start_Button设为TRUE,系统切换至RUNNING状态,Conveyor_Motor变为TRUE
  3. 物料分拣
    • 将Sensor_Red设为TRUE,Cylinder_Red在50ms去抖后变为TRUE,其余气缸保持FALSE
    • 将Sensor_Red复位,Sensor_Green设为TRUE,Cylinder_Red复位,Cylinder_Green激活
  4. 故障模拟:同时将Sensor_Red和Sensor_Green设为TRUE,Fault_Code变为1,系统进入ERROR状态,所有输出复位,Alarm_Lamp点亮
  5. 故障恢复:将Fault_Code手动清零,Emergency_Stop设为FALSE,系统返回IDLE状态
  6. 超时测试:在RUNNING状态下持续运行超过10秒,Fault_Code变为2,系统进入ERROR状态

常见问题与避坑

1. 扫描周期导致的逻辑错误

问题:在同一个扫描周期内同时读取和修改同一变量,可能导致预期外的行为。

解决方案

  • 采用"读-计算-写"三段式结构,避免在计算过程中修改输入
  • 使用中间变量暂存计算结果,周期结束时统一输出
  • 对于需要跨周期保持的状态,使用功能块内部变量

2. 传感器信号抖动

问题:机械触点或光电传感器在切换瞬间会产生多次跳变,导致误判。

解决方案

  • 本文已实现50ms去抖滤波器,可根据现场噪声特性调整时间常数
  • 对于高速场景,使用硬件滤波(如RC电路)配合软件滤波
  • 避免在去抖时间内进行关键逻辑判断

3. 输出互锁缺失

问题:两个物理上不能同时动作的执行器(如正反转接触器)同时得电,导致短路或机械损坏。

解决方案

  • 在Actuator_Control功能块中实现了三重互锁逻辑
  • 互锁应在输出刷新前的最后环节执行,确保不被后续逻辑覆盖
  • 对于关键设备(如电机正反转),建议在硬件电路层面增加互锁

4. 状态机死锁

问题:状态切换条件不满足,导致系统卡在某个状态无法退出。

解决方案

  • 每个状态必须定义明确的进入和退出条件
  • 设置看门狗定时器,在超时后强制切换到安全状态
  • 本文的Fault_Diagnosis功能块实现了运行超时监控,可防止传送带无限运行

5. 变量初始化遗漏

问题:PLC上电后,未初始化的变量可能包含随机值,导致程序异常启动。

解决方案

  • 所有全局变量和功能块内部变量必须显式初始化
  • 在程序启动的第一个扫描周期执行初始化逻辑
  • 使用RETAIN变量保存断电保持数据时,注意区分初始值和保持值

6. 数组边界越界

问题:在FOR循环中访问数组时,索引超出声明范围。

解决方案

  • 使用LOWER_BOUND和UPPER_BOUND函数获取数组边界
  • 循环变量使用与数组索引一致的数据类型(如INT)
  • 在Codesys中启用运行时边界检查功能

7. 功能块实例化数量

问题:每个功能块实例独立占用内存,过多实例可能导致内存溢出。

解决方案

  • 根据实际需求合理规划实例数量
  • 对于重复逻辑,考虑使用函数(FUNCTION)而非功能块
  • 使用ARRAY OF功能块管理同类设备
相关推荐
SelectDB6 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
小林ixn6 天前
别再手写Prompt了!用AI Loop实现自动化自我迭代,效率提升10倍
人工智能·自动化运维
用户556918817536 天前
#从脚本到独立程序:Python + Playwright 批量抓取的完整踩坑记录
python·自动化运维
怕浪猫7 天前
Playwright 的 CDP Session 机制详解
浏览器·ai编程·自动化运维
kyriewen13 天前
从本地到生产:迁移到 GitHub Actions 自动化 CI/CD,总结了这 5 个坑
前端·github·自动化运维
凤炎忻19 天前
【GitHub】GitHub Actions 快速入门
github·自动化运维
SelectDB19 天前
Agentic Analytics 时代,AI Agent 真正需要怎样的数据基座?
大数据·agent·自动化运维
淼淼爱喝水25 天前
ansible 自动化部署多主机差异化服务(httpd + vsftpd)
自动化运维