2、使用PyQt6部署西门子PLC上位机-软件编写

本文详细描述了如何通过Python和PyQt6开发一个机器人上位机,监测PLC的IO状态,并解决线程同步问题,以实时显示油漆输送状态,包括画面设计、逻辑实现和全局变量管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、目的

       生产现场机器人上位机软件很多IO都无法监测,同时厂家有封锁软件,故想通过自己设计上位机读取上位机信息并监测 

        在机器人电脑显示调漆间油漆输送状态,下图是连接前后状态

二、设计

1、画面设计

打开工具-外部工具-QTdesigner,这些是上一篇文章设置后的结果

画面根据自己喜好绘制,默认颜色可从样式修改

链接:https://pan.baidu.com/s/189cG53Rej27219qo5PFf1Q?pwd=1010 
提取码:1010 
视频连接如上,讲的精炼有效

画面生成后,转到pycharm点击pyUIC可生成对应的python文件

该文件会显示各个部件名称,方便对应操作

2、逻辑设计

(1)main,用于调用程序

import sys

from PyQt6.QtWidgets import QApplication

from ui.mainwindow import MainWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_widget = MainWidget()
    main_widget.show()
    sys.exit(app.exec())

(2)线程程序,主要存在两个问题

1、不要再线程里直接赋值标签颜色,会导致标签颜色加载闪烁,因为线程和主线程同时运行发生了冲突,花了我3天时间才搞定,用信号方式传递到主线程显示

2、Qthread程序要命名run,否则不会运行,纯恶心人的,找了半天原因

from PyQt6.QtCore import QThread, pyqtSignal
from PyQt6.QtWidgets import QApplication
import ui.var
import time
import snap7
import sys


class WorkThread(QThread):
    paint_sig1 = pyqtSignal(bool)
    paint_sig2 = pyqtSignal(bool)
    paint_sig3 = pyqtSignal(bool)
    paint_sig4 = pyqtSignal(bool)
    paint_sig5 = pyqtSignal(bool)

    solvent_sig1 = pyqtSignal(bool)
    solvent_sig2 = pyqtSignal(bool)

    def __init__(self, plc, paint1_label, paint2_label, paint3_label, paint4_label, paint5_label, parent=None):
        super(WorkThread, self).__init__(parent)
        self.plc = plc
        self.paint1_label = paint1_label
        self.paint2_label = paint2_label
        self.paint3_label = paint3_label
        self.paint4_label = paint4_label
        self.paint5_label = paint5_label

    def run(self):
        while True:
            if not ui.var.stop:
                ui.var.disconnect1 = False
                return
            else:
                prime_paint = self.plc.read_area(snap7.client.Areas.PE, 0, 3914, 1)
                prime_solvent = self.plc.read_area(snap7.client.Areas.PE, 0, 3930, 1)
                print(prime_paint)
                print("prime")
                print(prime_solvent)
                print("solvent")

                paint1 = bool.__bool__((prime_paint.__getitem__(0) >> 0) & 0b1)
                paint2 = bool.__bool__((prime_paint.__getitem__(0) >> 1) & 0b1)
                paint3 = bool.__bool__((prime_paint.__getitem__(0) >> 2) & 0b1)
                paint4 = bool.__bool__((prime_paint.__getitem__(0) >> 3) & 0b1)
                paint5 = bool.__bool__((prime_paint.__getitem__(0) >> 4) & 0b1)

                solvent1 = bool.__bool__((prime_solvent.__getitem__(0) >> 0) & 0b1)
                solvent2 = bool.__bool__((prime_solvent.__getitem__(0) >> 1) & 0b1)

                self.paint_sig1.emit(paint1)
                self.paint_sig2.emit(paint2)
                self.paint_sig3.emit(paint3)
                self.paint_sig4.emit(paint4)
                self.paint_sig5.emit(paint5)

                self.solvent_sig1.emit(solvent1)
                self.solvent_sig2.emit(solvent2)

                time.sleep(1)

(3)窗口程序,用于窗口显示内容和绑定槽和信号

import time

from PyQt6.QtWidgets import QWidget
import PyQt5
from ui.untitled import *
from ui.thread import WorkThread
import snap7
from PyQt6.QtWidgets import QApplication
import ui.var


class MainWidget(QWidget, Ui_widget):
    def __init__(self, parent=None):
        super(MainWidget, self).__init__(parent)
        self.setupUi(self)
        self.plc = snap7.client.Client()

        self.conn_butt.clicked.connect(self.conn_PLC)
        self.pushButton.clicked.connect(self.plc_disconnect)

    def conn_PLC(self):
        ui.var.stop = True
        ui.var.disconnect1 = True
        self.plc = snap7.client.Client()
        net = str(self.net_addr.text())
        rack1 = int(self.rack_combo.currentText())
        slot1 = int(self.slot_combo.currentText())
        self.plc.connect(net, rack1, slot1)
        plc_status = self.plc.get_connected()

        print(f"connect:{self.plc.get_connected()}")
        if plc_status:
            self.con_status.setText("已连接")
            self.con_status.setStyleSheet("background-color: rgb(2,247,2) ")

        self.thread1 = WorkThread(self.plc, self.paint1, self.paint2, self.paint3, self.paint4, self.paint5, )
        self.thread1.paint_sig1.connect(self.paint1_back)
        self.thread1.paint_sig2.connect(self.paint2_back)
        self.thread1.paint_sig3.connect(self.paint3_back)
        self.thread1.paint_sig4.connect(self.paint4_back)
        self.thread1.paint_sig5.connect(self.paint5_back)
        self.thread1.solvent_sig1.connect(self.solvent1_back)
        self.thread1.solvent_sig2.connect(self.solvent2_back)
        self.thread1.start()
        print("dff")

    def paint1_back(self, msg):
        if msg:
            self.paint1.setText("工作")
            self.paint1.setStyleSheet("background-color: rgb(2,247,2)")
        else:
            self.paint1.setText("停泵")
            self.paint1.setStyleSheet("background-color: rgb(243,69,19) ")
        QApplication.processEvents()

    def paint2_back(self, msg):
        if msg:
            self.paint2.setText("工作")
            self.paint2.setStyleSheet("background-color: rgb(2,247,2)")
        else:
            self.paint2.setText("停泵")
            self.paint2.setStyleSheet("background-color: rgb(243,69,19) ")
        QApplication.processEvents()

    def paint3_back(self, msg):
        if msg:
            self.paint3.setText("工作")
            self.paint3.setStyleSheet("background-color: rgb(2,247,2)")
        else:
            self.paint3.setText("停泵")
            self.paint3.setStyleSheet("background-color: rgb(243,69,19) ")
        QApplication.processEvents()

    def paint4_back(self, msg):
        if msg:
            self.paint4.setText("工作")
            self.paint4.setStyleSheet("background-color: rgb(2,247,2)")
        else:
            self.paint4.setText("停泵")
            self.paint4.setStyleSheet("background-color: rgb(243,69,19) ")
        QApplication.processEvents()

    def paint5_back(self, msg):
        if msg:
            self.paint5.setText("工作")
            self.paint5.setStyleSheet("background-color: rgb(2,247,2)")
        else:
            self.paint5.setText("停泵")
            self.paint5.setStyleSheet("background-color: rgb(243,69,19) ")
        QApplication.processEvents()

    def solvent1_back(self, msg):
        if msg:
            self.solvent1.setText("工作")
            self.solvent1.setStyleSheet("background-color: rgb(2,247,2)")
        else:
            self.solvent1.setText("停泵")
            self.solvent1.setStyleSheet("background-color: rgb(243,69,19) ")
        QApplication.processEvents()

    def solvent2_back(self, msg):
        if msg:
            self.solvent2.setText("工作")
            self.solvent2.setStyleSheet("background-color: rgb(2,247,2)")
        else:
            self.solvent2.setText("停泵")
            self.solvent2.setStyleSheet("background-color: rgb(243,69,19) ")
        QApplication.processEvents()

    def plc_disconnect(self):
        ui.var.stop = False
        if not ui.var.disconnect1:
            self.paint1.setText("失联")
            self.paint2.setText("失联")
            self.paint3.setText("失联")
            self.paint4.setText("失联")
            self.paint5.setText("失联")

            self.solvent1.setText("失联")
            self.solvent2.setText("失联")

            self.con_status.setText("失联")
            self.con_status.setStyleSheet("background-color: rgb(243,69,19) ")

            QApplication.processEvents()

        # self.plc.disconnect()

(4)变量,用于存放各文件间的调用全局变量

stop = None
disconnect1 = None

3、测试和打包exe

可运行后,输入正确的IP地址测试

在终端下运行pyinstaller --noconsole main.py

不要用-F,会产生终端后台,用这个指令可以屏蔽终端后台

三、连接

将程序拷贝到上位机上,输入正确网址即可,最好全部复制粘贴,之前出现ui不显示的问题

<think>好的,用户想了解上位机开发使用的语言,我需要详细介绍一下。首先,上位机通常指与硬件设备通信的计算机端软件,负责控制、数据采集和处理。那常用的语言有哪些呢? 首先想到的是C#,因为它在工业领域应用广泛,特别是Windows平台。C#有.NET框架,配合WinForms或WPF做界面,加上串口、网络通信库,开发效率高。可能用户对跨平台有需求,所以得提一下Python,语法简单,库丰富,适合快速开发,但性能可能不如C++。 然后是C++,性能关键时常用,比如高频数据采集或实时处理。Qt框架支持跨平台,适合需要Linux或macOS的情况。LabVIEW图形化编程,在测试测量领域常见,但用户可能需要编程语言,所以LabVIEW作为补充。 Java也有应用,尤其是跨平台需求强的企业环境,但生态可能不如C#和Python活跃。新兴语言如Go和Rust,Go适合高并发,Rust内存安全,可能在特定场景有用,但相对较少。 选择语言要考虑平台、性能、开发效率、团队熟悉度。比如,Windows下C#合适,跨平台或快速开发用Python,高性能需求选C++。用户可能需要实际例子,比如C#和Python的简单代码示例,这样更直观。 需要确保语言特点覆盖全面,没有遗漏重要选项,同时建议结合具体场景,帮助用户做决策。可能用户是初学者,所以语言的学习曲线也是考虑因素。另外,工具和框架的推荐也很重要,比如QtPyQt、.NET MAUI等。 最后总结各语言优缺点,给出建议,确保用户能根据自身情况选择。检查是否有错误,比如C#的跨平台能力通过.NET Core现在确实支持,Python的性能问题可以通过C扩展缓解,但可能需要额外工作。确认信息准确,结构清晰,分点明确,用户容易理解。</think>上位机开发是指开发用于与下位机(如PLC、传感器、嵌入式设备等)进行通信和数据交互的计算机端软件系统。以下是关于上位机开发语言的系统介绍及选型建议: --- ### 一、常用开发语言及特点 #### 1. **C#** - **优势**: - 生态完善:.NET框架提供丰富的库(如`SerialPort`类、`Socket`通信)。 - 界面友好:通过WinForms/WPF快速开发图形化界面。 - 工业主流:广泛用于工业自动化(如与西门子PLC通信)。 - **典型工具**:Visual Studio + .NET Framework/.NET Core - **代码片段**: ```csharp // 串口通信示例 SerialPort port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One); port.DataReceived += (sender, e) => { string data = port.ReadLine(); Console.WriteLine($"接收数据: {data}"); }; port.Open(); ``` #### 2. **Python** - **优势**: - 开发效率高:语法简洁,适合快速原型开发。 - 库丰富:`PySerial`(串口)、`PyQt/PySide`(GUI)、`NumPy`(数据分析)。 - 跨平台:支持Windows/Linux/macOS。 - **局限**:性能低于编译型语言,适合中低频数据场景。 - **代码片段**: ```python import serial ser = serial.Serial('COM3', 9600) while True: data = ser.readline().decode('utf-8').strip() print(f"接收数据: {data}") ``` #### 3. **C++** - **优势**: - 高性能:适用于高频数据采集(如1MHz采样率)。 - 跨平台:通过Qt框架实现GUI和通信。 - 底层控制:直接操作硬件或调用DLL。 - **典型工具**:Qt Creator + Qt Framework - **代码片段**: ```cpp // Qt串口示例 QSerialPort port; port.setPortName("COM3"); port.setBaudRate(QSerialPort::Baud9600); if (port.open(QIODevice::ReadWrite)) { QObject::connect(&port, &QSerialPort::readyRead, [&]() { QByteArray data = port.readAll(); qDebug() << "接收数据:" << data; }); } ``` #### 4. **LabVIEW** - **优势**: - 图形化编程:适合非专业开发者快速搭建测控系统。 - 硬件集成:原生支持NI数据采集卡、PLC等设备。 - **局限**:闭源生态,定制化能力较弱。 --- ### 二、选型核心因素 1. **平台兼容性**: - Windows首选C#,跨平台需求选Python/Qt(C++)。 2. **性能要求**: - 高频/实时处理:C++ > C# > Python - 中低频数据处理:Python/C#更高效 3. **开发周期**: - 快速验证:Python/LabVIEW - 长期维护:C#/C++ 4. **团队技能**: - 熟悉.NET生态选C# - 熟悉开源工具链选Python/C++ --- ### 三、新兴技术补充 - **Go/Rust**:适合需要高并发通信的场景(如千级设备并发连接)。 - **Web技术栈**:通过Electron(Node.js + HTML/CSS)开发跨平台桌面应用,结合WebSocket与硬件通信。 --- ### 四、典型应用场景 | 场景 | 推荐语言 | 工具/框架 | |--------------------|-------------|---------------------| | 工业PLC控制 | C# | WinForms + OPC UA | | 实验室数据采集 | Python | PyQt + Matplotlib | | 嵌入式设备调试 | C++ | Qt + libusb | | 快速原型验证 | LabVIEW | NI DAQmx | --- ### 五、学习建议 1. **从C#/Python入门**:掌握基础通信协议(如Modbus、TCP/IP)。 2. **深入硬件交互**:学习串口/网络通信协议、数据解析(二进制/JSON)。 3. **实践项目**:尝试开发一个完整的上下位机系统(如温度监控系统)。 如果需要进一步了解具体技术细节或项目案例,可提供更具体的需求方向。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值