ronkang
倍加福總線
級別: 略有小成
![]() |
SR20帶7臺G120XA變頻器,走USS通訊,一個(gè)子程序中使用7個(gè)USS_CTRL指令讀寫變頻器。另一個(gè)子程序中使用7個(gè)USS_RPM_R指令輪訓(xùn)讀取7臺變頻器電流,現(xiàn)在問題是: 1.兩個(gè)子程序都在主程序中調(diào)用時(shí),USS_RPM_R沒有任何錯(cuò)誤,但是USS_CTRL平均15秒就會報(bào)錯(cuò),錯(cuò)誤代碼2。2這個(gè)代碼不知什么原因引起。 2.主程序中只調(diào)用USS_CTRL這個(gè)子程序時(shí),7個(gè)USS_CTRL指令無任何錯(cuò)誤。 請專家指點(diǎn)一下,USS_RPM_R是輪詢順序執(zhí)行的,應(yīng)該沒有問題,會不會是和USS_CTRL指令沖突了?問題到底出在哪里?有什么解決辦法,麻煩大家了 |
---|---|
|
zhou1211
級別: 略有小成
![]() |
你一個(gè)循環(huán)周期很容易出現(xiàn)uss_ctrl 和Uss_RPM_R 時(shí)間間隔不夠,這樣就被掛起報(bào)錯(cuò) |
---|---|
|
zhou1211
級別: 略有小成
![]() |
IF iAdrOfInsulation =0 THEN iAdrOfInsulation :=91; END_IF IF bSensorCorrectionHMI THEN eCommandNum := 5; END_IF IF bParamAlterHMI THEN eCommandNum := 7; END_IF CASE eCommandNum OF(*SystemTotalData :=1,SubcircuitAnodeToGlobeResistance,ProductParamRead,SubcircuitCathodeToGlobeResistance,SensorCorrection,AddrAlter,ParamAlter*) SystemTotalData: wMBAdr := 16#0320; iLen := 7; bReadEnable := TRUE; bWriteEnable :=FALSE; SubcircuitAnodeToGlobeResistance: wMBAdr := 16#03E8; iLen := iSubTotal; bReadEnable := TRUE; bWriteEnable :=FALSE; ProductParamRead: wMBAdr := 16#0510; iLen := 5; bReadEnable := TRUE; bWriteEnable :=FALSE; SubcircuitCathodeToGlobeResistance: wMBAdr := 16#04B0; iLen := iSubTotal; bReadEnable := TRUE; bWriteEnable :=FALSE; SensorCorrection: wMBAdr := 16#680; wWriteDate := 16#7; bReadEnable := FALSE; bWriteEnable :=TRUE; AddrAlter: bReadEnable := FALSE; bWriteEnable :=TRUE; wMBAdr := 16#1218; IF iWantedAdr <>0 THEN wWriteDate := UINT_TO_WORD(iWantedAdr); ELSE wWriteDate := 16#5B; END_IF ParamAlter: bReadEnable := FALSE; bWriteEnable :=TRUE; IF bSubcircuitCAlterHMI THEN wMBAdr := 16#71A; wWriteDate := UINT_TO_WORD(iWantedSubcircuitAmount); END_IF IF bAlarmLimitSetHMI THEN wMBAdr := 16#71C; wWriteDate := UINT_TO_WORD(iWantedResistanceLimit); END_IF IF bResistanceCheckRangeSetHMI THEN wMBAdr := 16#71E; wWriteDate := UINT_TO_WORD(iWantedResistanceCheckRange); END_IF END_CASE IF NOT bAlter THEN CASE iState OF 0: fbMBCom.ReadRegs(Execute := FALSE); istate := istate +1; 1: fbMBCom.ReadRegs( UnitID := UINT_TO_BYTE(iAdrOfInsulation), (* 站點(diǎn)地址 *) Quantity := iLEN, MBAddr := wMBAdr, CbLength := iLEN*2, pMemoryAddr:= ADR(wMemoryDate[1]), Execute := TRUE AND bReadEnable , Timeout := t#5s, Busy => ); IF NOT fbMBCom.BUSY THEN fbMBCom.ReadRegs(Execute := FALSE); IF fbMBCom.Error THEN iState :=0; ELSE istate := istate +1; END_IF END_IF 2: CASE eCommandNum OF 1: FOR i :=1 TO 7 DO IF i=3 OR i=4 THEN iSysTotalDate := WORD_TO_UINT(wMemoryDate AND 16#3FFF); ELSE iSysTotalDate := WORD_TO_UINT(wMemoryDate); END_IF END_FOR iSubTotal := iSysTotalDate[2]; IF wMemoryDate[3].14 THEN bErrList[1] := TRUE; ELSE bErrList[1] := FALSE; END_IF IF wMemoryDate[4].14 THEN bErrList[2] := TRUE; ELSE bErrList[2] := FALSE; END_IF 2: FOR i :=1 TO 5 DO iProductParam := WORD_TO_INT(wMemoryDate); END_FOR 3: FOR i :=1 TO iSubTotal DO iSubP_EarthR := WORD_TO_INT(wMemoryDate AND 16#3FFF); IF wMemoryDate.15 THEN bErrList[2+i] := TRUE; ELSE bErrList[2+i] := TRUE; END_IF IF wMemoryDate.14 THEN bErrList[2+iSubTotal+i] := TRUE; ELSE bErrList[2+iSubTotal+i] := TRUE; END_IF END_FOR 4: FOR i :=1 TO iSubTotal DO iSubN_EarthR := WORD_TO_INT(wMemoryDate AND 16#3FFF); IF wMemoryDate.15 THEN bErrList[2+2*iSubTotal+i] := TRUE; ELSE bErrList[2+2*iSubTotal+i] := TRUE; END_IF IF wMemoryDate.14 THEN bErrList[2+3*iSubTotal+i] := TRUE; ELSE bErrList[2+3*iSubTotal+i] := TRUE; END_IF END_FOR END_CASE FOR i := 1 TO 64 DO wMemoryDate := 0; END_FOR istate :=0; eCommandNum := eCommandNum +1; IF eCommandNum >4 THEN eCommandNum :=1; END_IF bAlter := bStopHmi;(*參數(shù)修改ON*) END_CASE ELSE CASE istate OF 0: fbMBCom.WriteSingleRegister(Execute := FALSE); istate := istate +1; 1: fbMBCom.WriteSingleRegister( UnitID := UINT_TO_BYTE(iAdrOfInsulation), Quantity := 1, MBAddr := wMBAdr, CbLength := SIZEOF(wWriteDate), pMemoryAddr:= ADR(wWriteDate), Execute := TRUE AND bWriteEnable, Timeout := t#5000ms, Busy => ); IF NOT fbMBCom.BUSY THEN fbMBCom.WriteSingleRegister(Execute := FALSE); IF fbMBCom.Error THEN istate := 0; ELSE istate :=istate +1; END_IF END_IF 2: CASE eCommandNum OF 5:; 6: IF iWantedAdr = BYTE_TO_UINT(fbMBCom.InData.D[4]) THEN iAdrOfInsulation := iWantedAdr; END_IF 7:; END_CASE bWriteEnable :=FALSE; eCommandNum :=1; iState :=0; bAlter := bStopHmi;(*參數(shù)修改OFF*) END_CASE END_IF |
---|---|
|
zhou1211
級別: 略有小成
![]() |
通訊沒你想的那么簡單,對時(shí)間有要求,你的輪詢讀沒問題是每一步都分開了在做,并且,即使你的通訊對象只有一個(gè),也會出現(xiàn)同樣的情況,你這存在2中通訊操作就必須在進(jìn)行另一種的時(shí)候中斷一種,我的程序是用codesys寫的,2種模式切換,但不能同時(shí)進(jìn)行,實(shí)際上切換過程時(shí)間很短,在確認(rèn)發(fā)出和收到回信再切回去 |
---|---|
|
zhou1211
級別: 略有小成
![]() |
你對通訊認(rèn)識還不夠,因?yàn)槟?個(gè)指令都是存在詢問幀,因此他就像modbus的控制字一樣,需要逐條發(fā)送,它又不能像CAN那樣打包發(fā)送,空閑接收。 你這種情況就算同時(shí)發(fā)送那也只是直接下條覆蓋上條,主要還是時(shí)間間隔不夠,例如:modbus幀間隔是3.5個(gè)字符,在一條發(fā)送完沒間隔完就直接下一條,那么2條會串在一塊形成合并幀; 這種幀99.99%的概率是不合法,無法被響應(yīng),因?yàn)樾r?yàn)通不過。 另外,你的設(shè)備越多數(shù)據(jù)量越大,你需要做的間隔就越長,波特率本身就是描述通訊速率的,可以計(jì)算得出你做程序該有的間隔。 PS: 上面的程序并不復(fù)雜,上面是modbus協(xié)議,也是讀和寫。codesys本身就是開放性的,你調(diào)用的是一整塊功能,它調(diào)用可以切入內(nèi)部調(diào)用函數(shù)。即使像你那種調(diào)用也有時(shí)候會寫得很復(fù)雜,你沒用到而已。 比如: 你詢問一個(gè)設(shè)備,設(shè)備回的狀態(tài)可能使你不得不選擇N種參數(shù),我上面的就是,讀寫在上面的case中其實(shí)只出現(xiàn)了2次,其他都是數(shù)據(jù)處理 |
---|---|
|
zhou1211
級別: 略有小成
![]() |
我說的中斷是廣義上的中斷,和PLC外部中斷不是一個(gè)概念,但和定時(shí)中斷類似,就是你必須先知道與通訊的設(shè)備是否成功的完成了上一次,而不是只管發(fā),到時(shí)收一堆報(bào)錯(cuò),這種情況當(dāng)年初學(xué)plc就是這樣。 拿個(gè)最簡單的電池SOC can2.0標(biāo)準(zhǔn)協(xié)議 只讀報(bào)文來講,plc不需要寫數(shù)據(jù)幀,只管讀,對象的報(bào)文分成4種幀,權(quán)重50ms 100ms 200ms 1s ,一是長度不一樣,二是重要程度不一樣,那么這四種必須在確定其中一種發(fā)送完了才能發(fā)另一種,否則極可能出現(xiàn)1s間隔的不重要報(bào)文永遠(yuǎn)發(fā)不出去 |
---|---|
|
zhou1211
級別: 略有小成
![]() |
程序是很簡單,但到實(shí)際應(yīng)用的時(shí)候有不確定性,通信原理都是一樣,協(xié)議也只約定規(guī)則,這些規(guī)則無非就是限制 緊要 1. 數(shù)據(jù)幀的開始標(biāo)志 2. 數(shù)據(jù)長度; 3. 結(jié)束標(biāo)志; 4. 校驗(yàn)方式; 非緊要,在前面4個(gè)重點(diǎn)正確的情況下,后面的一般不會有錯(cuò) 5. 故障碼; 6. 最大長度 你的問題可能原因 1. 發(fā)送緩存區(qū)因相近間隔時(shí)間進(jìn)入過多的數(shù)據(jù)量,導(dǎo)致發(fā)送長度不支持,發(fā)送失; 2. 沒有檢測握手標(biāo)志(發(fā)送完成標(biāo)志,接收完成標(biāo)志),每個(gè)通訊功能塊都有一個(gè)Done 位(雙工只注意單個(gè)done),新手靠拉長收發(fā)時(shí)間,中手看標(biāo)志,老手看綜合狀態(tài);像485線,你發(fā)一幀數(shù)據(jù),必須等收到信息完成,或者確實(shí)超時(shí)才能發(fā)下一次詢問; 檢測的方法最直接是用串口調(diào)試工具去監(jiān)測收發(fā)數(shù)據(jù)的實(shí)際狀態(tài),這樣才能判斷錯(cuò)出在哪了,有時(shí)候你的數(shù)據(jù)沒問題,而通訊的對方可能有問題,比如,你CPU運(yùn)行速度1ms周期,而對方在處理不同數(shù)據(jù)時(shí)響應(yīng)時(shí)間不一樣,以前測試過一款微型伺服,詢問狀態(tài)響應(yīng)2ms,控制指令響應(yīng)時(shí)間很長,讀數(shù)組狀態(tài)的時(shí)候響應(yīng)時(shí)間也很長,所有經(jīng)常被程序認(rèn)為是發(fā)送超時(shí) 寫程序前先了解被通訊對象的素質(zhì)也很重要,先用串口工具測試各種你要用到指令,然后加快收發(fā)速度,去測試響應(yīng)極限,別一上去就干到極限,然后悶逼不知道怎么解決。當(dāng)確實(shí)遇到了問題,那么再回過同用通訊工具采樣你發(fā)和它發(fā)的狀態(tài)找原因 |
---|---|
|
zhou1211
級別: 略有小成
![]() |
圖片:
![]() 所以說你根本看不懂我那個(gè)程序,那個(gè)程序不復(fù)雜,里面數(shù)據(jù)判斷占了大部分,真正收發(fā)指令只占了很小的一部分,你寫一個(gè)通訊程序也是一樣的,當(dāng)然,電機(jī)控制用固定功能塊做的,或者說你只需要固定控制方式,所以顯得簡單; 我程序里面包含了通訊參數(shù)的修改,首先是修改了通訊默認(rèn)地址,再就是模仿modbus切換控制字寫對象的參數(shù),然后根據(jù)不同的控制模式解析對應(yīng)數(shù)據(jù) 你做通訊感覺才入門,上圖是對應(yīng)實(shí)現(xiàn)的功能 大致就是通訊建立,先讀出前排2組數(shù)據(jù),那2組如果和實(shí)際設(shè)備有出入則通過下面的寫操作修改掉,其余時(shí)間是在讀取右邊2列有效數(shù)據(jù),這個(gè)設(shè)備沒有修改軟件,所以得做通訊程序去修改報(bào)警范圍之類的參數(shù),不是每一個(gè)給你的設(shè)備都會給你配一個(gè)參數(shù)修改軟件,也不是每一個(gè)操作工都知道怎么去修改一個(gè)設(shè)備,尤其是第三方,那么你就必須在你的HMI上開放一個(gè)接口去方便修改 [ 此帖被zhou1211在2021-01-17 11:39重新編輯 ] |
---|---|
|