工业自动化、焊接装备制造、智能制造某精密焊接装备科技公司2025/12/20

氩弧焊机智能控制上位机系统

为某精密焊接装备科技公司开发的氩弧焊机智能控制上位机系统,基于 Qt/C++ 构建,兼容 Windows 与 Linux 双平台。系统通过 RS-485 Modbus RTU 协议对接工业 PLC 与多路环境传感器,采用通信线程与 UI 线程完全隔离的多线程架构,在 20ms 高频轮询设备状态的同时保持界面零卡顿;配合自适应动态采样与环形缓冲区技术,实现焊接电流、电弧电压、气体流量等多路关键参数的实时波形展示与辅助分析,大幅提升了焊接过程的可观测性与质量管控能力。

氩弧焊机智能控制上位机系统
通信轮询频率
20 ms 周期稳定轮询,4 路 Modbus 从站并发响应,零丢帧
UI 帧率
主界面渲染帧率稳定 ≥ 60 FPS,通信繁忙期间无可感知卡顿
传感器接入数量
接入 PLC 寄存器 80+ 个,温湿度、气体流量、弧电压等 6 类传感器
波形刷新延迟
端到端(设备采样→屏幕更新)延迟 ≤ 100 ms
数据存储
本地 SQLite 历史库,支持 30 天滚动存储与一键导出 CSV
跨平台兼容
同一套源码在 Windows 10/11 与 Ubuntu 22.04/银河麒麟 V10 下完整运行
报警响应时间
超限报警从触发到声光提示 ≤ 100 ms
项目交付周期
从需求确认到产线部署验收,历时 11 周
Qt 6 (C++17)
QModbusTcpClient / QSerialPort
RS-485 Modbus RTU
环形缓冲区
自适应动态采样

项目背景

某精密焊接装备科技公司专注于高端 TIG(钨极惰性气体保护焊)设备的研发与制造,产品广泛应用于航空航天零部件、核电管道及精密仪器外壳的自动化焊接场景。随着客户对焊接一致性与可追溯性要求的持续提升,原有的"纯硬件旋钮+数字表头"操作方式已无法满足工艺参数精细调控、过程数据记录及远程运维的需求。

公司决定自研一套跨平台上位机控制软件,要求:

  • 对接现有西门子 S7-1200 PLC(RS-485 Modbus RTU)及 6 路环境传感器
  • 实时采集焊接电流、电弧电压、氩气流量、熔池温度等核心参数并可视化
  • 保持界面流畅不卡顿
  • 兼容 Windows 工厂管理网与 Linux 国产化工控机(银河麒麟 V10)
  • 形成可追溯的焊接工艺档案,支持质量复盘与客户交付文档生成

技术挑战

挑战一:高频通信与 UI 流畅性的天然矛盾

RS-485 Modbus RTU 通信本质上是同步阻塞式:上位机发送请求 → 等待从站应答 → 解析数据,每次事务耗时 10~30 ms(视波特率与寄存器数量而定)。若在 Qt 主线程中直接轮询 4 路从站,每轮累计阻塞可超过 100 ms,导致界面事件循环饥饿,用户感知为"操作迟钝、波形抖动"。

挑战二:高频采样与波形显示的数据量压力

焊接电弧电压和电流信号变化频率可达数百赫兹,若以 10 ms 为采样间隔持续记录,30 分钟焊程将产生逾 18 万个数据点。将全量数据直接推入图表组件不仅造成渲染压力,在趋势分析时也会掩盖有效特征。

挑战三:多协议、多从站的统一管理

系统需同时管理 PLC(Modbus RTU,地址 01~04)和温湿度模块(Modbus RTU,地址 05)、流量计(Modbus RTU,地址 06),各从站寄存器布局、数据类型(INT16、UINT16、FLOAT32)及异常响应行为各不相同,需要一套可扩展的从站抽象层统一调度。

挑战四:跨平台串口与时序一致性

Qt 的 QSerialPort 在 Linux 与 Windows 下的底层驱动行为存在差异:Linux 下 FTDI/CH340 驱动的字节间隔处理与 Windows 下的 COM 口虚拟化策略不同,直接影响 Modbus 帧间隔计算(3.5 个字符时间),需做平台级适配。

系统架构

系统整体分为四层:硬件接入层、协议驱动层、业务逻辑层、UI 呈现层。各层职责清晰,通过 Qt 信号槽机制跨线程传递数据,任意层的故障均不级联影响其他层。

%%{init: {'theme': 'dark', 'themeVariables': {'primaryColor': '#0a1628', 'primaryTextColor': '#c8d8f0', 'primaryBorderColor': '#1a4a8a', 'lineColor': '#2060c0', 'secondaryColor': '#0d2040', 'tertiaryColor': '#081020'}}}%% graph TD subgraph HW["硬件层 Hardware Layer"] PLC["西门子 S7-1200 PLC\nModbus RTU Slave 01~04"] SENS1["温湿度传感器\nSlave 05"] SENS2["气体流量计\nSlave 06"] RS485["RS-485 总线 / USB-RS485 适配器"] PLC --> RS485 SENS1 --> RS485 SENS2 --> RS485 end subgraph COMM["协议驱动层 Protocol Layer(独立通信线程)"] SCHED["从站轮询调度器\nSlaveScheduler"] PARSER["Modbus 帧解析器\nFrameParser"] RETRY["超时重试 & CRC 校验\nRetryHandler"] RS485 -->|QSerialPort 串口读写| SCHED SCHED --> PARSER PARSER --> RETRY end subgraph BIZ["业务逻辑层 Business Layer(工作线程)"] RBUF["环形缓冲区\nRingBuffer × 8 通道"] SAMPLER["自适应动态采样器\nAdaptiveSampler"] ALARM["报警引擎\nAlarmEngine"] HIST["历史数据落库\nSQLite Writer"] RETRY -->|emit rawDataReady| RBUF RBUF --> SAMPLER RBUF --> ALARM RBUF --> HIST end subgraph UI["UI 呈现层 Presentation Layer(主线程)"] WAVE["波形图组件\nQCustomPlot"] DASH["仪表盘 & 数值面板"] ALMPANEL["报警面板"] CTRLPANEL["参数设置 & 指令下发"] SAMPLER -->|emit plotDataReady| WAVE ALARM -->|emit alarmTriggered| ALMPANEL RBUF -->|emit liveValueReady| DASH CTRLPANEL -->|emit writeRequest| SCHED end

核心技术实现

1. 线程分离架构:让通信与 UI 互不干扰

系统运行时共维护以下线程树:

%%{init: {'theme': 'dark'}}%% graph LR subgraph MainThread["主线程 (Qt Event Loop)"] UI_RENDER["UI 渲染 / 事件响应"] SLOT_RECV["槽函数:接收数据信号"] end subgraph CommThread["通信线程 (QThread)"] POLLER["SlavePoller\n20ms 定时轮询"] SERIAL["QSerialPort\n串口 I/O"] end subgraph WorkerThread["数据处理线程 (QThread)"] RBUF2["RingBuffer 写入"] SAMPLER2["AdaptiveSampler"] ALARM2["AlarmEngine"] end subgraph DBThread["落库线程 (QThread)"] DBWRITER["SQLiteWriter\n批量异步写入"] end POLLER -- "QueuedConnection\nemit rawDataReady()" --> RBUF2 RBUF2 -- "emit plotDataReady()" --> SLOT_RECV RBUF2 -- "emit liveValueReady()" --> SLOT_RECV ALARM2 -- "emit alarmTriggered()" --> SLOT_RECV RBUF2 -- "emit dbBatchReady()" --> DBWRITER SLOT_RECV --> UI_RENDER

关键设计决策:

① 通信线程使用 QTimerQt::CoarseTimer)驱动轮询,而非 sleep() 阻塞,保证定时精度在 ±5 ms 内,同时允许线程事件循环正常响应停止信号,实现优雅关闭。

② 所有跨线程数据传递均通过 Qt::QueuedConnection 信号槽,Qt 自动通过事件队列将信号投递至目标线程,无需手动加锁,消除死锁风险。

③ 参数写入指令走反向通道:UI 层发出 writeRequest(slaveId, regAddr, value) 信号,通信线程的槽函数将其压入一个无锁写队列(std::atomic + CAS),在下一个轮询间隙执行写操作,确保读写不互相打断。

// 通信线程核心轮询逻辑(简化示意)
void SlavePoller::onPollTick() {
    for (auto& slave : m_slaves) {
        auto result = slave->readHoldingRegisters(slave->startAddr(), slave->regCount());
        if (result.isValid()) {
            emit rawDataReady(slave->id(), result.values(), QDateTime::currentMSecsSinceEpoch());
        } else {
            slave->incrementErrorCount();
            emit commError(slave->id(), result.errorString());
        }
    }
    // 处理待写队列
    WriteRequest req;
    while (m_writeQueue.tryDequeue(req)) {
        m_modbusClient->writeRegister(req.slaveId, req.address, req.value);
    }
}

2. 环形缓冲区:高吞吐低延迟的数据中枢

每个采集通道(电流、电压、温度、流量等)分配一个容量为 8192 个样本的定长环形缓冲区(Ring Buffer)。写端(通信线程)以 20 ms 间隔持续写入,读端(绘图线程)以帧率为驱动按需消费,两者独立推进,互不阻塞。

缓冲区满时自动覆盖最旧样本,保证内存占用恒定;同时维护一个 readMark 游标供历史回放使用,支持用户拖拽时间轴查看过去 7 分钟的波形而无需重新查数据库。

3. 自适应动态采样:在细节保真与性能之间精准权衡

原始 20 ms 采样率对于波形显示而言数据量适中,但在用户缩放至"查看单次引弧瞬间"时,100 ms 窗口内仅有 2 个点,曲线失真;而在"查看 10 分钟趋势"时,12000 个点的全量渲染又造成显卡压力。

我们实现了基于 LTTB 算法(Largest-Triangle-Three-Buckets) 的自适应降采样器:

  • 根据当前波形控件的像素宽度(如 900 px)动态计算目标点数(通常为像素宽的 2~3 倍)
  • 时间窗口缩小(放大)时,自动提升采样密度,优先保留极值点(引弧峰值、超限点)
  • 时间窗口扩大(缩小)时,以 LTTB 降采样保留视觉形态,抑制锯齿
QVector<QPointF> AdaptiveSampler::resample(
        const RingBuffer& buf, qint64 t0, qint64 t1, int targetPoints) {
    auto raw = buf.rangeQuery(t0, t1);
    if (raw.size() <= targetPoints) return raw;   // 无需降采样
    return lttbDownsample(raw, targetPoints);     // LTTB 保形降采样
}

此外,针对高频暂态事件(如引弧瞬间电流冲击),系统在检测到相邻两次采样差值超过设定阈值时,自动临时切换至 10 ms 高密度采样模式,事件平息后 3 秒内恢复正常频率,实现"平时省资源、关键时刻不遗漏"。

4. Modbus 从站抽象层:可扩展的设备接入模型

每个物理设备(PLC 各轴、传感器模块)被建模为一个 SlaveDevice 子类,封装寄存器映射、数据类型转换和量程换算规则。新增设备类型只需继承 SlaveDevice 并实现 parseRegisters() 接口,无需改动轮询调度器。

%%{init: {'theme': 'dark'}}%% classDiagram class SlaveDevice { +int slaveId +QString name +quint16 startAddr +quint16 regCount +readHoldingRegisters() ModbusResult +parseRegisters(values) ChannelDataMap +isOnline() bool +errorCount() int } class PlcAxisDevice { -float currentScale -float voltageScale +parseRegisters() ChannelDataMap +sendWeldStart() +sendWeldStop() +setCurrentSetpoint(float) } class TempHumidSensor { -float tempOffset +parseRegisters() ChannelDataMap } class GasFlowMeter { -float flowScale +parseRegisters() ChannelDataMap +resetTotalizer() } class SlaveScheduler { -QList~SlaveDevice*~ m_slaves +addSlave(SlaveDevice*) +removeSlave(int slaveId) +onPollTick() -m_writeQueue WriteQueue } SlaveDevice <|-- PlcAxisDevice SlaveDevice <|-- TempHumidSensor SlaveDevice <|-- GasFlowMeter SlaveScheduler "1" --> "0..*" SlaveDevice : manages

5. 跨平台适配:消除 Windows / Linux 串口行为差异

在跨平台测试阶段,我们发现银河麒麟 V10(Linux kernel 5.10)下 USB-RS485 适配器(CH340 驱动)在高波特率(115200 bps)下存在字节接收抖动,导致 Modbus RTU 帧间隔判断失效(误判断帧边界)。

解决方案:放弃依赖操作系统底层的字符间隔超时,改为在应用层实现帧完整性状态机:以接收字节数 + CRC 校验共同判断帧边界,彻底消除平台差异。同时在 Linux 下通过 ioctl(TIOCMSET) 显式控制 RS-485 收发切换方向,避免半双工冲突。

6. 波形辅助分析功能

除实时监控外,系统提供以下辅助分析能力:

  • 引弧检测:基于电流二阶导数阈值自动标记引弧/熄弧时刻,在波形图上叠加事件标注线
  • 稳弧质量评分:在焊接周期结束后计算电弧电压标准差与电流纹波系数,给出 0~100 分的稳弧质量评分并归档
  • 参数超限热图:在时间轴下方渲染热力带,红/黄/绿色直观反映各参数距上下限的距离,方便工艺工程师快速定位问题时段
  • 工艺曲线对比:支持将当前焊程波形与历史"黄金样本"叠加显示,色差高亮偏差区间

部署与工程实践

构建系统

采用 CMake 统一管理跨平台构建,CI/CD 流水线在 GitHub Actions 上同时触发 Windows(MSVC 2022)和 Linux(GCC 12)两套构建任务,确保每次提交均可在双平台编译通过并跑完单元测试。

安装包

  • Windows:使用 windeployqt 收集 Qt 动态库,打包为 NSIS 安装程序(含驱动预装脚本)
  • Linux:打包为 .deb 软件包,通过 systemd 服务实现开机自启与崩溃自恢复

日志与可观测性

生产环境通过 Qt 日志框架输出结构化日志(JSON Lines 格式),关键事件(通信超时、报警触发、指令下发)均带时间戳与线程 ID,便于售后远程排查问题。

项目成果

本系统在客户产线部署后,焊接工艺工程师第一次能够以毫秒级精度"看见"焊接过程的全貌。稳弧质量评分机制发现了原有工艺设定中一个长期存在的电流抖动问题(评分长期低于 70 分),经工艺调整后评分稳定至 92 分以上,对应产品焊缝外观合格率提升约 8 个百分点。跨平台兼容性使客户在推进国产化工控机替换时无需重新采购上位机软件,直接节省了硬件预算。

需要类似项目建议?

您可以把设备协议、现场约束和时间要求告诉我们,我们会先评估可复用部分和交付边界。

联系我们