关于用C#写电机起保停控制

假期间隙,可以回顾下C#的知识,这里依旧对比西门子博图来进行

用C#的控制台程序写一个基本的电机起保停控制如下

using System;

namespace AutoEquipment

{

// ==========================================

// 一、定义类(相当于你在博途里建了一个 FB块)

// ==========================================

public class FB_ConveyorMotor

{

// 1. 属性(Property)------ 就是FB块上面的引脚

public string DeviceName { get; set; } // 设备名字,比如"3号流水线"

// 输入引脚(IN)

public bool StartButton { get; set; } // 启动按钮

public bool StopButton { get; set; } // 停止按钮

// 输出引脚(OUT),private set 表示外部只能看,不能强行改写

public bool IsRunning { get; private set; }

// 内部状态(相当于FB块里的Static静态变量,用于自锁)

private bool _internalLatch = false;

// ==========================================

// 2. 事件(Event)------ 就是上下游的连锁接线

// ==========================================

public event Action<string> OnEmergencyStop;

public event Action<string, bool> OnStatusChanged;

// ==========================================

// 3. 方法(Method)------ 就是FB块里面的逻辑

// ==========================================

// 这个方法就相当于OB1里的扫描周期,每个扫描周期调用一次

public void ExecuteLogic()

{

// 【起保停逻辑】

// 按下停止按钮,自锁断开

if (StopButton == true)

{

_internalLatch = false;

}

// 按下启动按钮,或者已经处于自锁状态,则电机运行

else if (StartButton == true || _internalLatch == true)

{

_internalLatch = true;

}

// 记录上一个扫描周期的状态,用于判断是否发生变化

bool lastState = IsRunning;

IsRunning = _internalLatch;

// 如果状态变了,触发事件通知上下游

if (lastState != IsRunning)

{

OnStatusChanged?.Invoke(DeviceName, IsRunning);

}

}

// 专门用来模拟"急停"的方法

public void TriggerEmergencyStop()

{

_internalLatch = false;

IsRunning = false;

Console.WriteLine($"\n【急停触发】{DeviceName} 急停!");

// 触发事件,通知所有订阅了的上下游设备

OnEmergencyStop?.Invoke(DeviceName);

}

}

// ==========================================

// 二、主程序(相当于你的 OB1)

// ==========================================

class Program

{

static void Main(string\[\] args)

{

Console.WriteLine("--- 开始模拟PLC扫描周期 ---");

// 1. 实例化(在OB1里调用FB,生成背景DB,命名为 motor3)

var motor3 = new FB_ConveyorMotor { DeviceName = "3号流水线" };

// 2. 上下游"接线"(订阅事件)------ 就是你在博途里连的连锁线

motor3.OnEmergencyStop += (deviceName) =>

{

Console.WriteLine($" -> 上游1号、2号收到通知:{deviceName} 急停了,我马上停送料!");

Console.WriteLine($" -> 下游4号收到通知:{deviceName} 急停了,我马上停止接收!");

};

motor3.OnStatusChanged += (deviceName, isRunning) =>

{

string status = isRunning ? "启动" : "停止";

Console.WriteLine($"监控 {deviceName} 状态改变:{status}");

};

// ===== 开始模拟运行 =====

Console.WriteLine("\n--- 模拟1:按下启动按钮 ---");

motor3.StartButton = true;

motor3.ExecuteLogic(); // 扫描周期1:按钮按下

motor3.StartButton = false; // 模拟物理按钮回弹

motor3.ExecuteLogic(); // 扫描周期2:自锁生效,电机保持运行

Console.WriteLine("\n--- 模拟2:按下停止按钮 ---");

motor3.StopButton = true;

motor3.ExecuteLogic(); // 扫描周期1:停止按钮按下

motor3.StopButton = false;

motor3.ExecuteLogic(); // 扫描周期2:确认停机

Console.WriteLine("\n--- 模拟3:按下启动后,突发急停 ---");

// 先快速启动一下

motor3.StartButton = true; motor3.ExecuteLogic(); motor3.StartButton = false; motor3.ExecuteLogic();

// 触发急停

motor3.TriggerEmergencyStop();

// 防止黑框一闪而过,停在这里等你敲回车

Console.WriteLine("\n--- 按回车键退出 ---");

Console.ReadLine();

}

}

}

1. static(静态)

  • 博途类比 :不需要分配背景DB块就能调用的系统常驻块(类似OB1,或者无需背景DB的FC)。

  • 解释 :普通的方法(比如写的 ExecuteLogic())必须先 new 一个实例(分配背景DB)才能调用。但加了 static,说明它是"全局唯一、直接就能跑"的。C#的 Main 是整个程序启动的入口,不需要提前去"实例化"它,系统一启动就自动找它。

2. void(无返回值)

  • 博途类比 :没有 OUT 引脚的 FC 块 / 只执行逻辑,不输出返回值的动作。

  • 解释 :PLC里有些块执行完要把结果传给别的块(有返回值)。但 Main 主程序是程序的起点,它执行完,程序就结束了,不需要向"谁"汇报一个结果 ,所以用 void(空)。

3. Main(主方法)

  • 博途类比 :OB1(主程序循环)。

  • 解释 :C#的编译器规定,整个程序必须有且只有一个 Main。按下F5,系统就从这个 Main 开始逐行往下扫描,跟PLC的扫描周期一模一样。

4. string[] args(字符串数组参数)

  • 博途类比 :OB1的启动参数(IN 引脚)。

  • 解释 :string[] 代表"字符串数组",args 是名字。

  • 在博途里,如果上位机(HMI)想在下发启动指令时顺便传个"配方号"给OB1,OB1的接口上就得建一个 IN 引脚。args 就是这个引脚。

  • 它的作用是:你在电脑命令行里输入 MyApp.exe "3号流水线" "启动",args[0] 就接住了 "3号流水线",args[1] 接住了 "启动"。

  • 注意 :C#强制规定,主程序的参数必须写成 string[](字符串数组)。如果不传参数,它就是空的,完全不用管它。


📝 总结对照表:

C# 单词 博途里的对应 详细含义
static 系统级全局块 不用建背景DB,系统启动就自动执行
void 无返回值的FC 执行完逻辑就结束,不需要把结果输出给调用者
Main OB1 整个程序扫描的起点和入口
string\[\] args OB1的启动参数(IN引脚) 外部启动程序时塞进来的初始字符串,不写就是空

所以,这句话在博途里的完美翻译是:

"这是一个全局系统级、不需要外部分配背景DB(static)、执行完不返回任何数据(void)、系统上电就自动从上往下扫描(Main)、并且预留了一个外部启动参数(string[] args)的主程序块。"

相关推荐
geovindu2 小时前
rust: Abstract Factory pattern
开发语言·后端·设计模式·rust·抽象工厂模式
“AI国潮设计-小江”2 小时前
《Python+SDXL实战:用ControlNet批量生成“英歌舞麻将糕”IP,附自动化脚本与商用思路》
开发语言·人工智能·python·prompt·aigc
Cc.Y2 小时前
Java零基础入门:封装与继承 —— 从“裸奔“到“穿衣服“,从“重复造轮子“到“站在巨人肩膀上“
java·开发语言
Escalating_xu2 小时前
【C 语言】深入理解指针(4):回调函数、qsort、void * 与泛型排序的模拟实现
java·c语言·开发语言
吠品3 小时前
GitHub 周榜拆解:决策小模型扎堆上位
c语言·开发语言·算法
见叶之秋3 小时前
C++ 泛型世界的两块拼图:容器适配器与仿函数
java·开发语言
逗脑IDE4 小时前
零基础学ESP32:RFID无线射频卡——让ESP32拥有“刷卡“能力!
开发语言·网络·人工智能·python·esp32·硬件开发
小师兄吃牛肉4 小时前
C语言篇:内联函数
c语言·开发语言
yuniko-n4 小时前
【Java】字符串相关坑点
java·开发语言·python