尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于Python的EPICS通讯LED实时刷新软件开发

基于Python的EPICS通讯LED实时刷新软件开发 目录一、Windows EPICS 环境部署1. EPICS Base安装2. Python环境配置3. 网络配置二、Python代码编写1. 代码结构设计2. 核心功能实现1LEDControl类 - LED硬件控制层2EPICSMonitor类 - 数据监控层3PVLEDControlSystem类 - 应用控制层4核心业务逻辑5日志系统四、功能测试发布五、开发流程总结1. 技术架构2. 注意事项End软件说明10通道PV实时监控同时监控10个EPICS过程变量5区域LED显示每2个PV对应1个LED显示区域触发机制支持上升沿、下降沿、双边沿触发文本格式支持多行文本、开头空格、特殊字符配置保存所有设置自动保存和加载日志记录完整的操作记录和故障诊断环境依赖软件库PyQt5、pyepics、winshell硬件依赖lv_led_MBCS_64.dll技术框架PyQt5构建图形界面EPICS实时数据采集LED屏幕硬件控制配置管理和日志系统开发流程步骤一、Windows EPICS 环境部署1. EPICS Base安装下载EPICS Base for WindowsEPICSWindowsTools1.44-x64 CA-3.15.6-windows-x64.zipa. 新建系统环境变量 EPICS_CA_ADDR_LISTb. 添加Path环境变量 C:\Program Files\EPICS Windows Toolsc. 配置完成后所有窗口点「确定」保存必须重启 CMD 窗口环境变量才会生效d. 验证caget -h2. Python环境配置安装Python 3.7配置项目虚拟环境Venv推荐python -m venv venv创建虚拟环境venv\scripts\activate激活pip install PyQt5 pyepics /pip install -r requirements.txt安装必要的Python包安装依赖pip freeze requirements.txt导出安装包3. 网络配置与EPICS IOC服务器的网络连通LED屏幕参数IP10.0.21.50卡类型T8屏幕参数宽1792 、高64二、Python代码编写1. 代码结构设计PVLEDControlSystem/├── LedControl_20251119.py # 主程序文件├── config/ # 配置目录自动生成│ └── pv_led_config.json # 配置文件├── logs/ # 日志目录自动生成│ └── pv_led.log # 日志文件└── lv_led_MBCS_64.dll # LED控制库厂家二开SDK面向对象的设计模式整体架构PVLEDControlSystem (主窗口类)├── EPICSMonitor (PV监控类)├── LEDControl (LED控制类)└── 各种UI组件和配置管理2. 核心功能实现1LEDControl类 - LED硬件控制层多路径DLL加载网络路径、当前目录、程序目录三种DLL加载方式硬件参数封装将LED屏幕的技术参数封装在类内部结构体映射使用ctypes将C结构体映射到PythonclassLEDControl:LED屏幕控制核心类负责与硬件DLL交互def__init__(self):# DLL路径配置 - 支持多个备选路径self.dll_paths[r\\10.0.21.30\Project\13报警\LED\Debug\lv_led_MBCS_64.dll,lv_led_MBCS_64.dll,os.path.join(os.path.dirname(__file__),lv_led_MBCS_64.dll)]# 硬件参数配置self.led_type4# T8卡类型self.led_width1792# 屏幕宽度self.led_height64# 屏幕高度self.led_ip10.0.21.50# LED屏幕IP地址defdefine_structures(self):定义与DLL交互的数据结构classCOMMUNICATIONINFO(Structure):_fields_[(LEDType,c_int),# LED类型(SendType,c_int),# 发送类型TCP/UDP(IpStr,c_char*16),# IP地址字符串(Commport,c_int),# 通信端口(Baud,c_int),# 波特率(LedNumber,c_int),# LED编号(OutputDir,c_char*260),# 输出目录(networkIdStr,c_char*19)# 网络ID]defrefresh_single_area(self,area_number,text):刷新独立LED区域的方法# 1. 格式化文本保留所有空格和换行formatted_textself.format_text_for_led(text)# 2. 内码指令字符串# 格式: %disp{区域号-1}:1{文本内容}refresh_stringf%disp{area_number-1}:1{formatted_text}# 3. 调用DLL函数发送指令comm_infoself.get_communication_info()resultself.led_dll.LV_RefreshNeiMaArea(byref(comm_info),refresh_string.encode(gbk)# 使用GBK编码)LED控制模块 (LEDControl类)DLL动态加载和结构体定义内码字符串格式化处理TCP/IP通信协议实现错误处理和连接测试2EPICSMonitor类 - 数据监控层观察者模式通过信号机制通知观察者主窗口状态变化状态模式管理10个通道的不同状态适配器模式将EPICS回调接口适配到PyQt信号系统classEPICSMonitor(QObject):EPICS PV实时监控器采用观察者模式# 定义信号 - PyQt的信号槽机制pv_changedpyqtSignal(int,bool,object)# PV值变化信号pv_connection_changedpyqtSignal(int,bool,str)# 连接状态变化信号pv_value_updatedpyqtSignal(int,object)# 值更新信号def__init__(self):super().__init__()# 10个通道的状态管理数组self.pv_connections[None]*10# PV连接对象self.pv_states[False]*10# PV状态值self.pv_values[None]*10# PV当前数值self.pv_connection_status[False]*10# 连接状态self.pv_last_change[None]*10# 最后变化时间defconnect_pv(self,index,pv_name):连接EPICS PV的核心方法try:# 创建EPICS PV对象设置自动监控和回调pvepics.PV(pv_name,auto_monitorTrue,# 自动监控值变化connection_callbackself._create_connection_callback(index))pv.add_callback(self._create_callback(index))# 状态初始化self.pv_connections[index]pv self.pv_states[index]pv.get()# ... 其他状态初始化def_create_callback(self,index):创建PV值变化回调函数 - 工厂方法defcallback(pvnameNone,valueNone,**kw):old_valueself.pv_states[index]self.pv_values[index]value# 发送值更新信号用于界面显示self.pv_value_updated.emit(index,value)# 如果值发生变化发送变化信号用于触发LEDifvalue!old_value:self.pv_states[index]value self.pv_last_change[index]datetime.now()self.pv_changed.emit(index,value,self.pv_values[index])returncallbackEPICS监控模块 (EPICSMonitor类)PV连接管理和状态监控回调函数机制实现数据更新和事件触发3PVLEDControlSystem类 - 应用控制层MVC模式界面(View)、数据(Model)、控制(Controller)分离组合模式集成多个功能模块单例模式配置管理和日志系统命令模式按钮操作封装classPVLEDControlSystem(QMainWindow):主控制系统集成监控、显示、配置所有功能def__init__(self):# 组合模式包含其他功能类self.epics_monitorEPICSMonitor()self.led_controlLEDControl()# 配置数据管理self.pv_configs[{name:,display_text:,auto_connect:False,trigger_edge:上升沿}for_inrange(10)]# 业务逻辑映射self.area_mapping{0:1,1:1,# PV1, PV2 - LED区域12:2,3:2,# PV3, PV4 - LED区域2# ... 其他映射}definit_ui(self):界面初始化# 1. 主窗口设置self.setWindowTitle(EPICS PV监控与LED内码刷新系统)self.setGeometry(100,100,1400,900)# 宽1400, 高900# 2. CSS样式表 - 专业美观的界面self.setStyleSheet( QMainWindow { background-color: #f0f0f0; } QGroupBox { font-weight: bold; border: 1px solid #cccccc; border-radius: 5px; } QPushButton { background-color: #e0e0e0; border: 1px solid #aaaaaa; border-radius: 3px; padding: 5px 10px; font-weight: bold; } QPlainTextEdit { background-color: white; # 白色背景输入框 border: 1px solid #cccccc; border-radius: 3px; font-family: Courier New; # 等宽字体显示空格 } )# 3. 标签页布局tab_widgetQTabWidget()pv_tabself.create_pv_monitor_tab()# PV监控标签页led_tabself.create_led_config_tab()# LED配置标签页tab_widget.addTab(pv_tab,PV监控)tab_widget.addTab(led_tab,LED配置)defsave_config(self):配置保存 - 使用JSON格式持久化config_data{pv_configs:[],led_config:{ip:self.led_ip_edit.text(),type:self.led_type_combo.currentText(),width:self.led_width_spin.value(),height:self.led_height_spin.value()},auto_start:self.auto_start_enabled}# 保存10个通道的配置foriinrange(10):# 使用toPlainText()保留所有格式空格、换行等display_textself.display_text_edits[i].toPlainText()config_data[pv_configs].append({name:self.pv_name_edits[i].text().strip(),display_text:display_text,# 保留原始格式auto_connect:self.pv_configs[i][auto_connect],trigger_edge:self.pv_configs[i][trigger_edge]})# 写入JSON文件withopen(self.config_file,w,encodingutf-8)asf:json.dump(config_data,f,indent4,ensure_asciiFalse)主界面系统 (PVLEDControlSystem类)GUI界面设计多标签页布局实时状态显示和操作控制配置管理和日志系统4核心业务逻辑defon_pv_changed(self,index,value,current_value):PV值变化处理 - 业务逻辑核心trigger_edgeself.pv_configs[index][trigger_edge]# 触发条件判断should_triggerFalseiftrigger_edge上升沿andvalue:# 从False变为Trueshould_triggerTrueeliftrigger_edge下降沿andnotvalue:# 从True变为Falseeliftrigger_edge双边沿:# 任何变化都触发ifshould_trigger:# 获取对应的LED区域area_numberself.area_mapping[index]# 获取显示文本保留所有格式display_textself.display_text_edits[index].toPlainText()ifdisplay_text.strip():try:# 调用LED控制刷新显示self.led_control.refresh_single_area(area_number,display_text)self.log_message(f通道{index1}触发文本已发送到LED区域{area_number})exceptExceptionase:self.log_message(fLED刷新失败:{str(e)})5日志系统defsetup_logging(self):日志系统配置self.log_handlerRotatingFileHandler(self.current_log_file,maxBytesself.max_log_size,# 10MB文件大小限制backupCountself.backup_count,# 保留5个备份文件encodingutf-8)formatterlogging.Formatter([%(asctime)s] %(levelname)s: %(message)s,datefmt%Y-%m-%d %H:%M:%S)self.log_handler.setFormatter(formatter)四、功能测试发布单元测试LED控制功能测试EPICS连接测试配置保存/加载测试界面操作测试集成测试PV触发LED刷新测试多通道并发操作测试长时间运行稳定性测试网络异常恢复测试五、开发流程总结1. 技术架构应用层: PyQt5 GUI 业务逻辑服务层: EPICS监控 LED控制驱动层: pyepics库 ctypes DLL调用硬件层: EPICS IOC LED显示屏2. 注意事项编码处理# GBK编码确保中文正确显示refresh_string.encode(gbk)# UTF-8编码确保配置文件中文正确json.dump(config_data,f,indent4,ensure_asciiFalse)文本格式保留# 使用QPlainTextEdit而不是QLineEditdisplay_editQPlainTextEdit()display_edit.setPlainText(text)# 设置文本保留格式textdisplay_edit.toPlainText()# 获取文本保留所有空格和换行确保DLL文件与程序在同一目录验证EPICS PV名称的正确性检查DLL加载状态End
返回列表