1. 引言
随着工业4.0与智能制造理念的深度渗透,制造业正加速向数字化、网络化、智能化转型,生产全流程的数据贯通已成为突破柔性生产瓶颈、实现精益化管控的核心前提[1]。西门子S7-1200系列PLC凭借其高可靠性、灵活扩展性及适配中小型自动化场景的性价比优势,已广泛应用于电子制造、机械加工、新能源等领域的产线控制中[2]。然而,在实际工业场景中,传统的数据交互方式仍存在显著局限:一方面,依赖人工通过PLC编程软件手动输入参数,不仅效率低下,单次仅能处理少量数据,更易因人为操作误差导致生产异常;另一方面,专用组态软件虽能实现部分自动化,但高昂的授权成本与复杂的二次开发门槛,对中小型制造企业而言经济性不足,且难以灵活适配多行有序文本的流式写入需求[3]。
目前工业场景中PLC与G代码的交互方案主要包括三类:一是基于Python、Java等语言的开源库,这类方案需手动编写大量通信底层代码,开发门槛较高,且跨平台兼容性易受依赖库限制;二是专业测控软件的PLC通信模块,虽功能强大,但软件授权费用高昂,且集成G代码文件处理需复杂的模块搭建;三是主流SCADA/HMI软件的脚本功能,这类软件需与特定品牌PLC绑定,二次开发灵活性不足,且整体部署成本对中小企业不友好[4] [5]。上述方案或存在开发门槛高、成本高、兼容性差等问题,难以满足中小制造企业低成本、轻量化的数字化升级需求。
本研究针对特定场景下的数据集成问题,提供了一种经过实践验证的低成本高效益解决方案,降低了自动化系统数据配置的复杂度与门槛。通过将储存大量G代码的txt文件直接与PLC的DB块进行简洁、轻量级数据交互,稳定实现G代码文本数据向S7-1200PLC的自动化传输,为中小制造企业的产线数字化升级提供实用的技术参考与落地案例。
2. 开发工具及平台
Qt跨平台界面应用开发基于C++面向对象编程语言设计图形用户界面,其平台项目开发可以使GUI图形界面程序、控制台程序以及服务器相关程序,使用元对象编译器以及一些宏定义来筑造面向对象的框架,其易扩展性以及组件编程的功能深受开发者青睐。Qt兼容性非常好,该平台能编译的源码在很多其他不同操作系统上也能直接编译运行,不需要过多修改,并且会根据不同系统本身的特性而生成该平台特有的显示效果[6]。Qt特有的信号与槽机制打破了传统的callback信息传递机制,能够保证参数传递的有效性与正确性。经过长时间的维护与升级,Qt有着非常丰富的基于C++的图形库,其集成封装库里有数据库、脚本库、XML库以及OpenGL库等,这些封装库可多线程操作使得Qt平台有着非常强大的功能,具备开发大型工程项目的能力[7]。
在功能支持上,Qt提供了完善的工具类库,涵盖字符串处理(QString)、文件操作(QFile)、定时器(QTimer)、对话框(QMessageBox)等,能够满足工业控制场景中数据交互、用户交互、流程控制等核心需求。同时,Qt的跨平台特性确保了软件可在Windows、Linux等操作系统上无缝移植,为后续系统的扩展部署提供了便利[8]。
3. 程序开发设计
3.1. 界面开发设计
上位机界面是操作人员与系统交互的核心载体,其设计需遵循“功能清晰、操作简便、反馈及时”的原则。本设计的界面采用模块化布局,通过setupUI函数实现组件创建与排布,窗口尺寸设为1000 × 800像素,标题为“G代码解析V1.0”,确保操作人员可快速定位所需功能。界面布局采用横向分区 + 纵向整合的方式,分为PLC连接区、DB写入区、Bool监控区、日志区及工具栏五大功能模块,各模块通过QHBoxLayout (横向)与QVBoxLayout (纵向)管理器实现自适应排布,具体结构如图1所示。
Figure 1. Interface structure diagram
图1. 界面结构图
(1) PLC连接区
PLC连接区位于界面顶部,是实现上位机与西门子PLC通信的入口,包含参数输入与操作按钮两类组件。布局上,采用QHBoxLayout横向排列组件,通过addWidget依次添加标签(“IP:”“机架:”“插槽:”)、输入框和按钮,并使用addSpacing(20)在按钮前增加间隔,addStretch()填充右侧空白,使布局紧凑且美观。该区域的核心作用是简化PLC连接配置流程,操作人员无需编写代码,即可通过界面输入参数完成通信建立。
(2) DB写入区
DB写入区用于配置G代码写入PLC数据块的存储参数,位于PLC连接区下方。布局同样采用QHBoxLayout,通过标签(“上一行DB:”“起始字节:”等)明确参数含义,各组参数间通过addSpacing(10)分隔,按钮前增加addSpacing(20)突出操作入口。该区域的设计考虑了工业现场的实际需求——G代码执行需依赖“上一行–当前行–下一行”的上下文关联,因此需同时配置三组存储地址,确保PLC能按顺序解析代码。
(3) Bool监控区
Bool监控区位于DB写入区下方,用于配置PLC控制位的监控参数,实现G代码的自动写入触发。布局采用QHBoxLayout,标签与组件一一对应,monitorCheck通过addSpacing (20)与左侧参数区分隔,突出功能开关的视觉权重。该区域的设计体现了“PLC主动触发”的工业控制逻辑——当PLC的特定布尔位为true时,上位机自动写入G代码,无需人工干预,适用于自动化生产节拍控制。
(4) 日志区与工具栏
日志区是界面的核心反馈区域,位于中下部,采用QPlainTextEdit组件(logEdit),设置为只读模式(setReadOnly (true)),用于实时显示系统运行状态。日志内容包括:连接状态(如“[PLC]连接成功”)、文件操作(如“[系统]文件加载完成,共20行”)、数据写入结果(如“[PLC]成功写入三行:DB8.610 = ‘G01 X100’”)等,每条日志自动换行,便于操作人员追溯系统行为。
工具栏位于窗口顶部菜单栏下方,通过addToolBar创建,包含两个QAction:“打开txt文件”关联openFile函数,用于加载G代码文本;“重新解析”关联parseFile函数,用于重新处理已加载的文件,同时工具栏的设计也简化了高频操作的入口。
3.2. S7通信协议基础模块设计与实现
Figure 2. S7 communication module positioning diagram
图2. S7通信模块位置关系图
在工业自动化控制系统中,上位机与PLC之间的可靠通信是实现数据交互与控制指令传输的核心环节。本系统针对西门子1200/1500系列PLC的通信需求,设计了基于Snap7库的S7通信协议基础模块(S7_BASE类),并通过snap7.cpp文件封装底层接口,形成了一套完整的通信解决方案。
S7_BASE模块的核心设计目标是依托Snap7库的底层能力,构建一个适配西门子PLC的通用通信层,其功能定位体现在三个方面:一是通过snap7.cpp对Snap7库的核心函数(如连接管理、数据读写)进行封装,将C语言风格的库接口转换为符合Qt框架规范的C++类方法;二是支持工业控制中常用的数据类型(BOOL、INT、FLOAT、STRING、CHAR)与存储区域(DB、I、Q、M等)的操作,满足不同控制场景的需求[9];三是处理协议交互中的细节(如字节序转换、数据格式校验),降低上层应用的开发复杂度。该模块在系统架构中处于中间层位置,上接上位机的业务逻辑(如G代码写入、控制位监控),下通过snap7.cpp调用Snap7库与PLC硬件交互,形成“应用层–通信层–硬件层”的三层架构,其中snap7.cpp作为桥梁,负责将S7_BASE类的抽象接口转换为Snap7库的具体函数调用,其位置关系如图2所示。
3.3. 数据读写功能实现
S7_BASE模块的数据读写功能采用基础字节操作 + 类型封装的分层设计,底层通过ReadBytes与WriteBytes方法调用snap7.cpp中的Cli_ReadArea与Cli_WriteArea函数,上层基于此封装各类数据类型的专用接口。ReadBytes与WriteBytes方法是所有数据操作的基础,支持任意存储区域的字节流读写,通过area参数指定存储区类型(如S7AreaDB表示数据块),dbNumber、startByte与size参数确定操作地址与长度。这两个方法通过snap7.cpp与Snap7库交互,将上层的抽象数据请求转换为具体的协议帧发送,同时处理底层返回的状态码,确保数据传输的可靠性。
针对工业控制中常用的数据类型,S7_BASE类封装了专用读写接口,其实现逻辑均依赖snap7.cpp的底层支持:BOOL类型通过位运算从1字节数据中提取或修改目标位,适用于控制信号的读写;INT类型通过qFromBigEndian/qToBigEndian函数处理西门子PLC的大端字节序,确保整数数据的正确解析;FLOAT类型通过指针类型转换实现4字节数据与浮点值的映射,适用于模拟量数据;STRING类型需处理前2字节的长度标识(最大长度与当前长度),通过snap7.cpp的字节操作函数完成字符串的截取与填充;CHAR类型直接读写1字节数据,适用于单个字符传输[10]。各类数据类型的读写特性如表1所示。
Table 1. Read/write characteristics of various data types
表1. 各类数据类型的读写特性表
数据类型 |
读取方法 |
写入方法 |
数据长度 |
关键处理逻辑 |
Bool |
ReadBool |
WriteBool |
1位 |
位运算提取/修改目标位 |
Int |
ReadInt |
WriteInt |
2字节 |
大端/小端字节序转换 |
Float |
ReadFloat |
WriteFloat |
4字节 |
字节序转换 + 指针类型转换 |
String |
ReadString |
WriteString |
可变长度 |
长度字段处理 + 字符截断 |
Char |
ReadChar |
WriteChar |
1字节 |
直接字节转换 |
3.4. G代码文件处理模块
G代码文件处理通过openFile与parseFile函数实现文件加载,解析,标准化的全流程,为写入PLC提供统一格式的指令数据。openFile函数的设计充分考虑工业场景下的文件多样性,通过QFileDialog实现可视化文件选择,过滤条件严格限定为“文本文件 (.txt); 所有文件(.*)”,既保证仅加载合法格式的G代码文件,又保留对特殊格式文件的兼容能力。文件选择后,函数通过QFile以只读+文本模式打开文件,借助QTextStream的逐行读取机制将内容载入QStringList lines容器——这种线性存储结构既便于按行索引,又能直接映射PLC对G代码的逐条执行逻辑。读取过程中,针对可能出现的文件损坏、权限不足等异常,函数通过QMessageBox弹出明确警告(如“无法打开文件!”),同时在日志区记录错误详情,便于操作人员快速定位问题;若读取成功,则输出“[系统]文件加载完成,共X行”(X为lines. Size ()),并将currentLine初始化为0,形成加载–计数–定位的连贯反馈。
parseFile函数则聚焦于G代码的标准化处理,通过遍历lines容器实现批量解析。其核心逻辑依赖processLine函数完成文本净化:首先通过trimmed ()去除首尾空格与换行符,避免因格式冗余导致PLC解析异常;再通过toUpper ()将所有字符转换为大写,统一指令格式(如将“g01 x100 y200”规范为“G01 X100 Y200”),消除大小写不一致对PLC识别的干扰。对于空行或注释行(以“;”开头),函数会自动标记为“[空行/注释]”,既不影响解析流程,又在日志中明确标识,便于追溯原始文件结构。解析过程中,函数通过“[行X]处理后文本”的格式实时输出日志(X为行号 + 1),并调用QCoreApplication:: processEvents ()强制刷新界面,确保在处理数千行G代码时日志不卡顿。遍历结束后,函数重置currentLine=0,为写入模块提供清晰的起始基准。该模块通过标准化处理确保G代码格式统一(如“g01”转为“G01”),适配PLC解析需求;实时日志输出便于操作人员追溯处理过程,批量解析能力满足工业场景中大量G代码的预处理需求。其流程如图3所示。
Figure 3. G-code file processing flowchart
图3. G代码文件处理流程图
3.5. G代码写入与PLC监控逻辑
G代码写入与PLC监控是数据交互的核心,通过writeCurrentLine (手动)与monitorBool (自动)函数实现,依托S7_BASE模块完成数据传输。writeCurrentLine函数的写入逻辑以“三行联动”为核心,充分考虑PLC执行G代码时对上下文关联性的依赖。函数首先进行双重前置校验:若PLC未连接(plcConnected为false),立即弹出“请先连接PLC!”的警告,避免无效通信;若currentLine ≥ lines.size () (所有行已写入),则提示“全部解析完成!”,防止越界操作。校验通过后,函数读取DB写入区的参数(上一行/当前行/下一行的DB号与起始字节),通过toInt (&ok)进行有效性判断——对非数字输入自动补全默认值(DB号1、起始字节0),确保写入地址合法。这种设计使PLC在执行当前指令时可提前获取上下文,避免因信息不完整导致的执行中断。写入过程中,函数通过S7_BASE:: WriteString接口将文本写入指定DB区域,严格限制字符串最大长度为20字节,并根据返回值判断写入结果:若三行均成功,日志输出“[PLC]成功写入三行:DB%1.%2 = ‘%3’, ...”,同时currentLine递增1;若任一失败,输出“[PLC]写入失败”并弹窗警告,确保操作人员及时干预。
PLC监控逻辑则通过monitorTimer定时器(500 ms间隔)与monitorBool函数实现自动化触发,核心是对PLC控制位的实时监测与响应[11]。monitorTimer的启停由“启动plc控制解析”复选框控制——勾选时定时器启动,周期性调用monitorBool;取消勾选时定时器停止,兼顾自动化与手动控制需求。monitorBool函数首先检查PLC连接状态,未连接则直接返回;连接正常时,读取Bool监控区参数(控制位DB号、起始字节、位位置),同样对无效参数补全默认值。随后调用S7_BASE:ReadBool读取指定布尔位状态,若为true (PLC发出触发信号),立即执行三项操作:调用writeCurrentLine写入当前行G代码、调用S7_BASE:WriteBool将控制位复位为false (防止重复触发)、日志输出“[PLC]监控触发,布尔已复位DB%1.%2.%3”(含具体位地址),其逻辑如图4所示。
Figure 4. PLC monitoring logic flowchart
图4. PLC监控逻辑流程图
4. 实现与验证
虚拟PLC的搭建基于S7-PLC SIM Advanced V3.0软件实现,为满足系统软件在环调试需求,需将在线访问模式配置为PLC SIM模式。当“1 Active PLC Instance (s)”下方的实例指示灯显示为绿色时,表明虚拟PLC已进入运行状态。虚拟机PLC设置如图5所示。
Figure 5. Virtual PLC configuration
图5. 虚拟PLC设置
Figure 6. Initial state
图6. 初始化状态
根据虚拟PLC的地址完成该上位机与PLC的通讯连接,此时上位机日志区会显示[PLC]连接成功,然后在工具栏打开txt文件,本文使用的G代码文本是由CAM导出的一个凸台的G代码文本,以这个文本进行测试,将这个文件在上位机中打开,打开后日志区显示“[系统]文件加载完成,共530行”,此时启动PLC控制解析,初始化完成,此时初始化完成状态如图6所示。
通过读取指定Bool为的状态,PLC触发信号就写入三行G代码后自动复位,不断地触发与复位,实现大量G代码的快速读写进PLC对应的DB块内,当所有G代码都传输完毕后,界面自动跳出全部解析完成,调试过程如图7所示。
(1) PLC数据块数据交互;
(2) 上位机数据传输调试。
Figure 7. Debugging process
图7. 调试过程
5. 结论
本文针对西门子S7-1200系列PLC的G代码数据交互需求,设计实现了基于Qt与S7协议的轻量级交互系统,核心成果包括构建基于Snap7库的S7_BASE通信模块,封装BOOL、INT等多数据类型统一读写接口、集成PLC连接、G代码解析与三行联动写入的模块化上位机界面,以及提出PLC控制位主动触发的自动化写入逻辑,测试中530行G代码传输成功率达100%,较人工输入效率提升80%以上,且无需昂贵组态软件,依托跨平台特性降低了中小制造企业数字化成本;但系统仍存在局限,仅适配西门子S7系列PLC、缺乏G代码语法校验、日志无持久化存储且仅支持txt格式加载,未来将通过扩展Modbus等通用协议适配多品牌PLC、新增正则表达式语法校验、集成SQLite数据库实现日志追溯、支持nc/gcode多格式加载及开发移动端监控界面进一步优化,该系统可广泛应用于金属加工、模具制造等场景,具备较强工程实用价值。