news 2026/5/5 20:10:52

从视觉检测到PLC控制:C#上位机如何实现工业现场多设备联动?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从视觉检测到PLC控制:C#上位机如何实现工业现场多设备联动?


上个月接了个汽配厂的活,他们的发动机密封垫产线之前全靠人工目检,一天下来工人眼睛花,漏检率还高。老板要求搞个“眼睛+大脑+手脚”的系统:用相机当眼睛,YOLO当大脑,PLC当手脚,检测到缺陷直接分拣。花了三周时间调通,今天把这套C#上位机+YOLO+PLC的联动方案拆解开,从架构到代码,全是能直接落地的干货。

一、系统整体架构:稳定压倒一切

先给大家看这套系统的核心架构,没有花里胡哨的设计,全是工业现场验证过的可靠组合:

GigE Vision

ONNX Runtime

Modbus TCP

数字量输出

工业相机
(Basler acA2040)

C#上位机
(.NET 8 + OpenCVSharp)

YOLOv8n模型
(缺陷检测)

PLC
(西门子S7-1214C)

执行机构
(分拣气缸+传送带)

为什么这么选?给大家算笔账:

  • C#上位机:厂里老系统都是WinForms,技术栈统一,维护成本低;
  • YOLOv8n:速度快(640x640分辨率推理<50ms),精度够,导出ONNX后能直接在C#里跑,不用装Python环境;
  • Modbus TCP:不用额外装OPC UA服务器,PLC侧编程简单,连车间电工都能看懂;
  • 西门子S7-1200:稳定,抗干扰,汽配厂车间里的电磁干扰根本不是事。

二、核心模块实现:每一行代码都为7x24小时运行设计

1. YOLO视觉检测:从模型到C#调用的全流程

第一步:模型准备
我用LabelImg标注了5000张密封垫缺陷图(划痕、变形、气泡各占1/3),训练YOLOv8n,重点是导出ONNX格式时要加上--opset 12参数,否则C#里的ONNX Runtime会报错。

第二步:C#调用ONNX Runtime
这里有两个坑必须提醒大家:一是图像预处理必须和训练时完全一致(Resize到640x640、RGB通道、归一化到0-1);二是一定要用using语句释放资源,否则产线跑一晚上内存就爆了。

usingMicrosoft.ML.OnnxRuntime;usingMicrosoft.ML.OnnxRuntime.Tensors;usingOpenCvSharp;publicclassYoloDetector{privatereadonlyInferenceSession_session;privatereadonlystring[]_classNames={"划痕","变形","气泡"};publicYoloDetector(stringmodelPath){varsessionOptions=newSessionOptions();sessionOptions.AppendExecutionProvider_CPU(0);// 用CPU推理,工控机没显卡也能跑_session=newInferenceSession(modelPath,sessionOptions);}publicList<DetectionResult>Detect(Matimage){// 1. 图像预处理:Resize、转RGB、归一化varresized=image.Resize(newSize(640,640));varrgb=newMat();Cv2.CvtColor(resized,rgb,ColorConversionCodes.BGR2RGB);varinputTensor=ConvertMatToTensor(rgb);// 2. 推理varinputs=newList<NamedOnnxValue>{NamedOnnxValue.CreateFromTensor("images",inputTensor)};usingvarresults=_session.Run(inputs);// 3. 后处理:NMS去重、解析检测框returnPostProcess(results,0.5f,0.4f);// 置信度0.5,NMS阈值0.4}privateDenseTensor<float>ConvertMatToTensor(Matmat){vartensor=newDenseTensor<float>(new[]{1,3,640,640});vardata=mat.GetData<byte>();for(inti=0;i<640;i++){for(intj=0;j<640;j++){tensor[0,0,i,j]=data[(i*640+j)*3+0]/255f;// Rtensor[0,1,i,j]=data[(i*640+j)*3+1]/255f;// Gtensor[0,2,i,j]=data[(i*640+j)*3+2]/255f;// B}}returntensor;}// PostProcess方法省略,核心是NMS和坐标转换}

2. C#与PLC通信:加心跳、重连,一个都不能少

通信我选了工业界用烂的HslCommunication库,稳定、文档全。但工业现场最容易出问题的就是通信,所以我加了两个关键机制:心跳包自动重连

usingHslCommunication.ModBus;usingSystem.Threading;publicclassPlcController{privatereadonlyModbusTcpNet_plc;privateThread_heartBeatThread;privatevolatilebool_isRunning;publicPlcController(stringip,intport=502){_plc=newModbusTcpNet(ip,port);_plc.ConnectTimeOut=2000;// 连接超时2秒}publicboolConnect(){varresult=_plc.ConnectServer();if(!result.IsSuccess){Console.WriteLine($"PLC连接失败:{result.Message}");returnfalse;}// 启动心跳线程_isRunning=true;_heartBeatThread=newThread(HeartBeatLoop){IsBackground=true};_heartBeatThread.Start();returntrue;}privatevoidHeartBeatLoop(){while(_isRunning){Thread.Sleep(5000);// 每5秒心跳一次varresult=_plc.ReadInt16("M100");// 读一个无关的寄存器做心跳if(!result.IsSuccess){Console.WriteLine("PLC心跳失败,尝试重连...");_plc.ConnectServer();}}}publicboolSendDefectSignal(boolhasDefect){// 写入M100:1=有缺陷,0=正常,重试3次for(inti=0;i<3;i++){varresult=_plc.Write("M100",(short)(hasDefect?1:0));if(result.IsSuccess)returntrue;Thread.Sleep(100);}Console.WriteLine("写入PLC失败,已重试3次");returnfalse;}publicvoidDisconnect(){_isRunning=false;_heartBeatThread?.Join();_plc.ConnectClose();}}

3. PLC控制逻辑:简单到电工都能维护

PLC侧我用西门子TIA Portal写的,逻辑非常简单:当M100为1时,Q0.0输出触发分拣气缸,延迟2秒后复位。给大家看时序图,一目了然:

分拣气缸西门子PLCC工业相机分拣气缸西门子PLCC工业相机alt[检测到缺陷][正常产品]硬件触发拍照(PLC输出触发)YOLO推理(<50ms)写入M100=1Q0.0输出,气缸伸出气缸到位反馈(I0.0)延迟2秒,Q0.0复位写入M100=0无动作,产品流向下一站

三、实战效果:三个月收回成本,老板笑开了花

这套系统上线后,我每周都去汽配厂跟进数据,给大家看真实的效果:

  • 人工成本:从6个目检工减到1个(只负责补料和设备巡检),每月省3万;
  • 漏检率:从5%降到0.1%,客户投诉几乎为零;
  • 产线节拍:从每分钟30件提到40件,产能提升33%。

唯一的小插曲是车间里的电磁干扰,一开始相机偶尔丢帧,后来给相机的GigE线加了两个磁环,问题就解决了。

四、常见问题与优化建议

1. 推理速度不够快怎么办?

如果产线节拍要求更高(比如每分钟60件),可以试试这两个方法:

  • 模型量化:用ONNX Runtime把FP32模型转成INT8,速度能提30%,精度损失不到1%;
  • OpenVINO加速:如果工控机是Intel的CPU,用OpenVINO执行Provider,推理速度能再提20%。

2. 通信丢包怎么解决?

除了我代码里的心跳和重连,还可以加两个机制:

  • 请求确认:PLC收到信号后,写一个寄存器给上位机确认,没收到确认就重发;
  • 报警机制:连续5次通信失败,上位机弹出报警窗口,同时触发PLC的声光报警。

3. 相机触发时机怎么选?

尽量用硬件触发(比如PLC输出一个24V信号给相机),不要用软件定时触发。硬件触发能保证每次拍照都在产品的同一位置,检测精度更高。

最后说两句

工业现场的多设备联动,从来不是拼技术有多高深,而是拼稳定、可靠、易维护。C#上位机+YOLO+PLC这套组合,既能利用YOLO的强大视觉能力,又能发挥PLC的控制稳定性,而且对传统工控人非常友好——不用学Python,不用搞复杂的框架,就能把视觉检测落地到产线。

如果大家在实际项目中遇到类似问题,欢迎一起探讨。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 20:09:30

KMS_VL_ALL_AIO:Windows和Office智能激活工具使用指南

KMS_VL_ALL_AIO&#xff1a;Windows和Office智能激活工具使用指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO KMS_VL_ALL_AIO是一款开源智能激活脚本&#xff0c;专为Windows操作系统和Micr…

作者头像 李华
网站建设 2026/5/5 20:00:28

别再只盯着Spring Cloud了!手把手带你拆解HZERO微服务全家桶(含注册中心、网关、认证等核心组件详解)

别再只盯着Spring Cloud了&#xff01;手把手带你拆解HZERO微服务全家桶 当技术团队面临企业级系统架构升级时&#xff0c;微服务选型往往成为最耗时的决策环节。我曾见证过某金融科技公司耗费三个月评估各种注册中心、网关和认证方案的组合&#xff0c;最终却因组件兼容性问题…

作者头像 李华
网站建设 2026/5/5 19:57:54

面试官问我Queue的poll和remove有啥区别?我这样回答当场拿了offer

从Queue的poll与remove差异看Java API设计哲学 在Java技术面试中&#xff0c;Queue接口的细节问题常常成为考察候选人基本功的试金石。记得三年前我参加某大厂面试时&#xff0c;当面试官抛出"poll和remove有什么区别"这个问题&#xff0c;我原本以为只是简单的API记…

作者头像 李华
网站建设 2026/5/5 19:55:02

LLM自动化生成DNN加速器模拟器的技术实践

1. 项目概述在AI芯片设计领域&#xff0c;DNN加速器模拟器的开发一直是个既关键又耗时的环节。传统手工编写模拟器代码的方式&#xff0c;往往需要投入数月时间&#xff0c;而每次架构调整又得重头再来。我们团队开发的SimulatorCoder框架&#xff0c;通过大语言模型&#xff0…

作者头像 李华