控制系統(tǒng)(十三):安全監(jiān)控服務(wù)——壓力超標(biāo)了怎么辦)
安全監(jiān)控服務(wù)壓力超標(biāo)了怎么辦這是「從零搭建工業(yè)控制系統(tǒng)」系列第13篇。燈塔能顯示狀態(tài)但光顯示不夠。壓力超標(biāo)了得自動關(guān)閥門斷電了得自動啟動保護。這篇講安全監(jiān)控服務(wù)怎么執(zhí)行安全動作。一次差點炸腔的事故去年冬天Chamber腔體正在抽真空壓力傳感器突然故障——讀數(shù)卡在0。系統(tǒng)以為還在真空狀態(tài)繼續(xù)抽。實際上腔體已經(jīng)漏氣壓力回到大氣壓了。如果繼續(xù)抽下去泵會過載。那次靠操作員手動按了急停才沒出大事。事后我花了兩天寫了ChamberSafetyControlService讓系統(tǒng)自己處理這種故障。核心思路壓力數(shù)據(jù)無效時按最安全的狀態(tài)處理。不知道壓力是多少就當(dāng)它不安全。雙重壓力監(jiān)控架構(gòu)系統(tǒng)有兩套壓力監(jiān)控保護不同的設(shè)備監(jiān)控服務(wù)監(jiān)控對象閾值保護設(shè)備ChamberPressureMonitorService腔體壓力模擬量輸入大氣壓閾值腔體閥PumpPressureMonitorService泵口壓力安全閾值泵控制輸出Chamber監(jiān)控保護腔體蓋的安全泵口壓力監(jiān)控保護真空泵的安全。兩套獨立運行互不干擾。Chamber安全控制服務(wù)ChamberSafetyControlService監(jiān)聽壓力變化自動控制AutoChamberValve自動腔體閥和ManualChamberValve手動腔體閥publicpartialclassChamberSafetyControlService:ObservableObject,IRecipientHeaterPCWConfigChangedMessage,IDisposable{privatereadonlyIDeviceCmdService_deviceCmdService;privatereadonlyChamberPressureMonitorService_pressureMonitor;[ObservableProperty]privateboolautoAllowControl;// False: AutoChamberValve直接關(guān)閉; True: 基于壓力智能控制[ObservableProperty]privateboolmanualAllowControl;// False: ManualChamberValve直接關(guān)閉; True: 啟用壓力保護[ObservableProperty]privateboolautoValveAutoEnable;// AutoChamberValve自動開關(guān)計算結(jié)果[ObservableProperty]privateboolmanualValveManualEnable;// ManualChamberValve手動開關(guān)計算結(jié)果}構(gòu)造函數(shù)里訂閱壓力監(jiān)控的屬性變化publicChamberSafetyControlService(IDeviceCmdServicemcuCmdService,ChamberPressureMonitorServicepressureMonitor){_deviceCmdServicemcuCmdService;_pressureMonitorpressureMonitor;// 訂閱壓力監(jiān)控變化事件_pressureMonitor.PropertyChangedOnPressureMonitorPropertyChanged;// 注冊消息接收器監(jiān)聽配置變更WeakReferenceMessenger.Default.Register(this);InitializeConfiguration();}壓力變化的響應(yīng)邏輯壓力監(jiān)控服務(wù)的IsPressureAboveThreshold變化時安全控制服務(wù)收到通知privatevoidOnPressureMonitorPropertyChanged(objectsender,PropertyChangedEventArgse){if(e.PropertyNamenameof(ChamberPressureMonitorService.IsPressureAboveThreshold)){UpdateControlOutputs();}elseif(e.PropertyNamenameof(ChamberPressureMonitorService.IsDataValid)){// 數(shù)據(jù)無效時也要更新——按最安全狀態(tài)處理UpdateControlOutputs();}}關(guān)鍵設(shè)計數(shù)據(jù)無效也觸發(fā)更新。傳感器故障時IsDataValidfalse這時候不能放任不管要按不安全處理。控制輸出計算privateasyncvoidUpdateControlOutputs(){// 計算AutoChamberValve自動控制if(!autoAllowControl){autoValveAutoEnablefalse;// 配置禁用直接關(guān)}elseif(!_pressureMonitor.IsDataValid){autoValveAutoEnablefalse;// 數(shù)據(jù)無效按不安全處理}else{autoValveAutoEnable_pressureMonitor.IsPressureAboveThreshold;// 正常邏輯}// 計算ManualChamberValve手動控制if(!manualAllowControl){manualValveManualEnablefalse;}elseif(!_pressureMonitor.IsDataValid){manualValveManualEnablefalse;}else{manualValveManualEnable_pressureMonitor.IsPressureAboveThreshold;}// 寫入硬件awaitWriteCoilValueAsync(_autoValveCoil,_autoValveCoil.GetWriteValue(autoValveAutoEnable));awaitWriteCoilValueAsync(_manualValveCoil,_manualValveCoil.GetWriteValue(manualValveManualEnable));}三層判斷配置是否啟用 → 數(shù)據(jù)是否有效 → 壓力是否達標(biāo)。任何一層不通過都關(guān)閥門。跨線程寫入的坑安全控制服務(wù)運行在后臺線程但線圈寫入涉及UI綁定的ModbusCoil對象。直接調(diào)用WriteValueManuallyCommand會報跨線程異常。解決方案繞過Command直接調(diào)用底層API// 錯誤做法通過Command寫入會觸發(fā)UI確認(rèn)對話框 跨線程異常// await coil.WriteValueManuallyCommand.ExecuteAsync(value);// 正確做法直接調(diào)用底層APIawait_deviceCmdService.WriteCoilValueAsync(coil,coil.GetWriteValue(enable));這個問題排查了很久。現(xiàn)象是啟動后偶現(xiàn)InvalidOperationException: 調(diào)用線程無法訪問此對象。最后發(fā)現(xiàn)是安全控制服務(wù)的Timer回調(diào)在后臺線程觸發(fā)了UI綁定屬性的更新。配置熱響應(yīng)配置變更時不需要重啟服務(wù)。通過消息機制實時響應(yīng)publicvoidReceive(HeaterPCWConfigChangedMessagemessage){// 配置變了重新計算控制輸出UpdateControlOutputs();}操作員在設(shè)置界面修改AutoAllowControl后保存安全控制服務(wù)立即收到消息并更新硬件輸出。線圈監(jiān)控防止外部篡改除了響應(yīng)壓力變化還有定時器監(jiān)控線圈狀態(tài)。如果有人手動操作了AutoChamberValve或ManualChamberValve服務(wù)會檢測到并糾正privateasyncvoidOnCoilMonitorTick(objectstate){if(_isApplyingControl)return;// 自己寫入時跳過varautoValveActual_autoValveCoil.IsActive();if(autoValveActual!autoValveAutoEnable){_logger.Warn($AutoChamberValve被外部修改: 期望{autoValveAutoEnable}, 實際{autoValveActual}, 正在糾正);awaitWriteCoilValueAsync(_autoValveCoil,_autoValveCoil.GetWriteValue(autoValveAutoEnable));}}_isApplyingControl標(biāo)志位防止自己寫入時觸發(fā)監(jiān)控糾正形成死循環(huán)。三大觸發(fā)時機安全服務(wù)的啟動有三個入口1. 應(yīng)用啟動App.xaml.cs里延遲2秒自動啟動2. 設(shè)備連接設(shè)備連上后檢查是否需要啟動安全服務(wù)3. 配置保存操作員修改配置后立即響應(yīng)// DeviceCmdService中的設(shè)備連接回調(diào)privatevoidOnDeviceStatusChanged(objectsender,DeviceStatusEventArgse){if(e.DeviceTypeDeviceType.DigitalIOe.IsConnected){// DigitalIO連接了檢查Chamber控制服務(wù)CheckAndStartChamberSafetyService();}}安全監(jiān)控踩坑清單坑現(xiàn)象解決跨線程寫入InvalidOperationException繞過Command直接調(diào)API傳感器故障讀數(shù)卡0繼續(xù)抽真空IsDataValidfalse時按不安全處理外部篡改手動操作后狀態(tài)不一致定時器監(jiān)控糾正配置不生效改了配置要重啟消息機制實時響應(yīng)死循環(huán)監(jiān)控糾正觸發(fā)監(jiān)控_isApplyingControl標(biāo)志位本篇小結(jié)知識點關(guān)鍵做法雙重監(jiān)控腔體壓力 泵口壓力獨立監(jiān)控三層判斷配置啟用→數(shù)據(jù)有效→壓力達標(biāo)數(shù)據(jù)無效按最安全狀態(tài)處理不放任跨線程繞過Command直接WriteCoilValueAsync線圈監(jiān)控定時檢測外部篡改并糾正三入口啟動/設(shè)備連接/配置保存安全監(jiān)控的核心原則不知道狀態(tài)時按最危險的情況處理。下期預(yù)告第14篇配置系統(tǒng)基礎(chǔ)安全服務(wù)靠配置驅(qū)動下篇講配置系統(tǒng)——INI文件、JSON配置、熱加載機制怎么設(shè)計。