| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238 |
- /******************************************************************************
- 版权所有:
- 文件名称: xdljd.c
- 文件版本: 01.01
- 创建作者: sunxi
- 创建日期: 2016-12-22
- 功能说明: 小电流接地检测
- 其它说明: !!!!!在不了解整个原理的情况下,不要轻易修改此文件中的算法!!!!!!
- 修改记录:
- */
- /*------------------------------- 头文件 --------------------------------------
- */
- #include "head.h"
- #ifdef XDL_ZT
- /*------------------------------- 宏定义 --------------------------------------
- */
- #define XDL_ZERO_LEN (ADC_REC_SAMPLE/4)
- #define XDL_SEG_NUM 10
- enum
- {
- XDL_ST_IDLE,
- XDL_ST_QT,
- XDL_ST_END,
- };
- /*------------------------------ 类型结构 -------------------------------------
- */
- struct point
- {
- s32 v;
- u32 p;
- };
- struct segment
- {
- u32 bgn; // 段开始
- u32 end; // 段结束
- u32 acc; // 累加值
- u32 max_p; // 最大值出现的位置
- u32 max_v; // 最大值的绝对值
- s32 dir; // 方向
- };
- struct xdl
- {
- // 状态
- int st;
- unsigned long qd_us0;
- unsigned long dz_us0;
- unsigned long gj_us0;
- unsigned long dz_fh_us0;
- // unsigned long gj_fh_us0;
- // 动作
- int dz;
- // 动作值记忆
- int dz_i0[2];
- int dz_u0[2];
- int dz_Ia[2];
- int dz_Ib[2];
- int dz_Ic[2];
- // 零偏
- s16 zero_sum;
- s16 zero_cnt;
- };
- struct i0_argument
- {
- s16 ref_v_set;
- bool scale_is_1A;
- };
- /*------------------------------ 全局变量 -------------------------------------
- */
- // 零偏
- //s16 g_xdl_zero_sum[SWITCH_NUM_MAX]; // 零偏和
- //s16 g_xdl_zero_cnt[SWITCH_NUM_MAX]; // 零偏计数
- //int g_xdl_qd[SWITCH_NUM_MAX]; // 小电流接地启动
- //int g_xdl_dz[SWITCH_NUM_MAX]; // 小电流接地动作
- //unsigned long g_xdl_qd_us0[SWITCH_NUM_MAX]; // 小电流接地启动时间
- struct xdl g_xdl[SWITCH_NUM_MAX];
- struct i0_argument g_i0_arg[SWITCH_NUM_MAX];
- // 滤波后数据
- s16 g_u0[XDL_SAMPLE_LEN];
- s16 g_i0[XDL_SAMPLE_LEN];
- // 原始的数据
- s16 g_u0_raw[XDL_SAMPLE_LEN];
- s16 g_i0_raw[XDL_SAMPLE_LEN];
- // 小波处理的数据
- float g_u0_dwt[XDL_SAMPLE_LEN];
- float g_i0_dwt[XDL_SAMPLE_LEN];
- struct segment g_u0_seg[XDL_SEG_NUM];
- struct segment g_i0_seg[XDL_SEG_NUM];
- // 小电流接地零压零流定时器
- #ifdef RECORD_SW_U0TB
- TIMERELAY g_tXDLTime_U0TB[SWITCH_NUM_MAX]; //零压突变定时器
- #else
- TIMERELAY g_tXDLTime_U[2];
- #endif
- TIMERELAY g_tXDLTime_I[SWITCH_NUM_MAX];
- int g_cur_direction_adaptaion = 0; //临时在此定义 EWen // TODO 方向自适应处理
- int XDLCHZWC = 0;
- char * g_xdl_rcd_a[] =
- {
- "U0_原始",
- "U0_滤波",
- "U0_区域",
- "U0_最大",
- "I0_原始",
- "I0_滤波",
- "I0_区域",
- "I0_最大",
- };
-
- #define XDL_RCD_A_NUM (sizeof(g_xdl_rcd_a)/sizeof(char *))
- const char * g_line_type[] =
- {
- "界外动作:",
- "界内动作:",
- };
- const char * g_tbl_type[] =
- {
- "小电流突变",
- "零压突变",
- };
- /*------------------------------ 函数声明 -------------------------------------
- */
- #if 0
- static void xdl_ar_dataset(void);
- static void xdl_ar_recharge(DWORD dStep);
- static void xdl_ar_disable(void);
- static void xdl_ar_start(DWORD dStep);
- static void xdl_ar_logic(DWORD dStep);
- static void xdl_ar_reset(DWORD dStep);
- static int xdl_ar_check(DWORD mode); // 检同期
- #endif
- static u32 xdl_get_LLTB_waves(int sw);
- /*------------------------------ 外部函数 -------------------------------------
- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
- */
- #if 0
- /**************************************************************************
- 函数名称: xdl_auto_reclose
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸功能块
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- void xdl_auto_reclose(DWORD dStep)
- {
- xdl_ar_dataset(); // 小电流重合闸数据准备
- xdl_ar_recharge(dStep); // 小电流重合闸充电
- xdl_ar_disable(); // 小电流重合闸闭锁
- xdl_ar_start(dStep); // 小电流重合闸启动
- xdl_ar_logic(dStep); // 小电流重合闸逻辑
- xdl_ar_reset(dStep); // 小电流重合闸复归
- return;
- }
- /**************************************************************************
- 函数名称: xdl_ac_check
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸加速块
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- void xdl_ac_check(int sw,DWORD dStep)
- {
- static bool bFZOut, bQD=false;
- bool bQDD;
- TRELAY_T *pR=&g_tRelay[sw];
- TXDLCH_T *pSW=&pR->tXDLCHZ;
- TSWST *pSWST =&pR->tSWST;
- TSETSW *pSet = &pRunSet->tSwSet[sw];
-
- /***********启动 **********************************/
- // 开放后加速允许有效延时3S展宽
- RunTR(&pSW->tTXDLCHJLY_HJS, XDLCHZWC, dStep);
- // 时间到
- if (pSW->tTXDLCHJLY_HJS.boolTrip)
- {
- XDLCHZWC =0;
- ResetTR(&pSW->tTXDLCHJLY_HJS);
- if (bFZOut)
- {
- soe_record_ev(EV_OVERU0+sw*EV_SW_NUM, 0, 0,0,0 );
- bFZOut = 0;
- }
- }
- if(pRunSet->tSwSet[sw].bTT_Power_v2)
- {
- bQDD = OverRelay(g_ui[PUB_AC_U02].m2[0],pRunSet->dOverU0,pRunSet->dOverU0_fh,bQD);
- }
- else
- {
- bQDD = OverRelay(g_ui[PUB_AC_U01].m2[0],pRunSet->dOverU0,pRunSet->dOverU0_fh,bQD);
- }
-
-
- bQD = BH_ALL_EN(sw)
- && pSet->bTT_xdltz//投退字
- && pSWST->uSWST.bFlag.bHZWZ //在合闸位置
- && bQDD
- && XDLCHZWC
- && !pSW->tTXDLCHJLY_HJS.boolTrip;
- /************事件记录及出口****************************/
- if(bQD)
- {
- if (!bFZOut) // 保证只动作一次未进行跳闸失败检测
- {
- DWORD U0;
- sw_do(sw,SW_DO_BHT,SW_DO_TYPE_ON);
-
- if(pRunSet->tSwSet[sw].bTT_Power_v2)
- {
- U0 = _Mul_Div_U(sqrt_32fix(g_ui[PUB_AC_U02].m2[0]), 256, g_ui[PUB_AC_U02].m2_factor_k);
- }
- else
- {
- U0 = _Mul_Div_U(sqrt_32fix(g_ui[PUB_AC_U01].m2[0]), 256, g_ui[PUB_AC_U01].m2_factor_k);
- }
- soe_record_ev( EV_OVERU0+sw*EV_SW_NUM, 1, U0,0,0 );
- bFZOut = 1;
- rt_printf("开关%d小电流检零压跳闸\r\n", sw);
- }
- }
-
- }
- /**************************************************************************
- 函数名称: xdl_ar_dataset
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸数据准备
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- static void xdl_ar_dataset(void)
- {
- u32 sw = g_protect.sw;
- TRELAY_T *pR=&g_tRelay[sw];
- TXDLCH_T *pSW =&pR->tXDLCHZ;
- InitTR_Time(&pSW->tTXDLCHJD_ARDelay, 10*T_1s, 0 ); // 小电流重合闸延时
- InitTR_Time(&pSW->tTXDLCHFAIL_TW, 11*T_1s, 0 ); // 小电流重合闸延时
- }
- /**************************************************************************
- 函数名称: xdl_ar_disable
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸闭锁
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- static void xdl_ar_disable(void)
- {
- u32 sw = g_protect.sw;
- TRELAY_T *pR=&g_tRelay[sw];
- TXDLCH_T *pSW =&pR->tXDLCHZ;
- pSW->sta.bFlag.bBSCH = pR->tOC[OC_LX1].sta.bFlag.bBSCH // 零序1闭锁重合闸
- || pR->tOC[OC_LX2].sta.bFlag.bBSCH // 零序2闭锁重合闸
- || pR->tOC[OC_LX3].sta.bFlag.bBSCH // 零序3闭锁重合闸
- || pR->tLostVot.uLostVot.bFlag.bTz // 失压跳闸闭锁重合
- || pR->tXXTZ.uZOV.bFlag.bTz
- || pR->tU0TZ.uZOV.bFlag.bTz ; // 零压分闸闭锁重合
- }
- /**************************************************************************
- 函数名称: xdl_ar_recharge
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸充电
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- static void xdl_ar_recharge(DWORD dStep)
- {
- u32 sw = g_protect.sw;
- TRELAY_T *pR=&g_tRelay[sw];
- TXDLCH_T *pSW =&pR->tXDLCHZ;
- TSETSW *pSet = &pRunSet->tSwSet[sw];
- bool bHCD1,bHCD2,bHCD3,bHCD4;
- // 放电条件
- RunTR(&pSW->tTXDLCHFAIL_TW, pR->tSWST.uSWST.bFlag.bTZWZ, dStep); // 三相跳位延时
- bHCD1 = pSW->tTXDLCHFAIL_TW.boolTrip; // 放电标志1:三相跳位时间到
- bHCD2 = (pR->tSWST.uSWST.bFlag.bTZWZ || pR->uBHDZ.bFlag.bBHT) // 此处小电流动作标志或者有保护动作
- && (!pSW->sta.bFlag.bCDWC); // 放电标志2:充电未完成,小电流动作
- bHCD3 = pR->uRmtSW.bHandTz // 手动跳闸
- || pR->uRmtSW.bYTExecute // 遥控跳闸
- || pR->uBHDZ.bFlag.bTZSB // 跳闸失败
- || pR->tSWST.uSWST.bFlag.bTWYL // 跳位有流
- || pR->tSWST.uSWST.bFlag.bWCN // 弹簧未储能告警
- || pSW->sta.bFlag.bBSCH // 重合闸闭锁条件
- || pSW->sta.bFlag.bCHFD; // 重合闸动作放电
-
- pSW->sta.bFlag.bFDBZ = (!BH_ALL_EN(sw)) // 总保护未投入
- || (!pSet->bTT_xdltz) // 小电流跳闸: 未投入
- || (!pR->run_stu.chz) // 重合闸硬压板未投入
- || bHCD1
- || bHCD2
- || bHCD3;
-
- // 充电条件
- bHCD4 = !pSW->sta.bFlag.bFDBZ // 重合放电标
- && (((!pR->uBHQD.bFlag.bZQD) && pR->tSWST.uSWST.bFlag.bHZWZ ) // 非保护启动 && 合闸位置
- || pSW->sta.bFlag.bCDWC); // 充电完成自保持
- RunTR(&pSW->tTXDLCHCD15s0s, bHCD4, dStep); // 充电15秒
- pSW->sta.bFlag.bCDWC = pSW->tTXDLCHCD15s0s.boolTrip;
- if(pSW->sta.bFlag.bCDWC)
- {
- // TODO:液晶应增加小电流重合闸标志
- if((g_disp_flag.xdl_chz_cd & (1<<sw)) == 0)
- {
- g_disp_flag.xdl_chz_cd |= 1<<sw;
- rt_printf_time("开关%02d小电流充电完成!\r\n",sw+1);
- }
- }
- else
- {
- if((g_disp_flag.xdl_chz_cd & (1<<sw)))
- {
- g_disp_flag.xdl_chz_cd &= ~(1<<sw);
- pSW->sta.bFlag.bXDLDZ = false;
- pR->tXDLCHZ.sta.wfFlag=0;
- pR->tXDLCHZ.wAR_ActTimes=0;
- ResetTR(&pR->tXDLCHZ.tTXDLCHJD_HJS);
- rt_printf_time("开关%02d小电流放电完成!\r\n",sw+1);
- }
- }
- }
- /**************************************************************************
- 函数名称: xdl_ar_start
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸启动
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- static void xdl_ar_start(DWORD dStep)
- {
- bool bCHQD_CHQD; // 三相启动重合闸
- u32 sw = g_protect.sw;
- TRELAY_T *pR=&g_tRelay[sw];
- TXDLCH_T *pSW =&pR->tXDLCHZ;
- TSETSW *pSet = &pRunSet->tSwSet[sw];
- bool bCQD1,bCQD2,bCQD3,bCQD4,bCQD5,bCQD6;
- // 不对应启动
- // 开关位置从合闸位置切换至分闸位置完成后,保留50ms展宽
- RunTR(&pSW->tTXDLCHQDHW0ms50ms, pR->tSWST.uSWST.bFlag.bHZWZ, dStep);
- bCQD1 = pSW->tTXDLCHQDHW0ms50ms.boolTrip;
- // 偷跳条件准备
- bCQD2 = pSet->bTT_TTCH
- && bCQD1
- && (!pR->tSWST.uSWST.bFlag.bHZWZ);
- // 保护启动
- // 保护动作后至保护动作返回,保留50ms展宽
- RunTR(&pSW->tTXDLCHQD0ms50ms, pR->uBHDZ.bFlag.bBHT, dStep);
- bCQD3 = pSW->tTXDLCHQD0ms50ms.boolTrip;
- // 重合已启动或保护启动,用于闭锁不对应启动
- bCQD4 = pSW->sta.bFlag.bCHQD ||bCQD3;
-
- // 此处保护跳信号,是实时信号,即保护已返回
- bCQD5 = bCQD3 && (!pR->uBHDZ.bFlag.bBHTrip);
- // 重合启动自保持
- // 重合闸出口条件,用于防止重合闸合闸过程中,TWJ没有返回时,再次误发启动重合闸报文。
- bCQD6 = pSW->sta.bFlag.bCDWC // 重合充电完成
- && pSW->sta.bFlag.bCHQD // 三相启动重合闸
- && (!pSW->sta.bFlag.bCHCK); // 重合闸出口,取反
-
- // 偷跳启动重合闸
- pSW->sta.bFlag.bTTQD = pSW->sta.bFlag.bCDWC // 重合闸充电完成
- && bCQD2 // 偷跳判断完成
- && (!bCQD4); // 重合未启动,无保护跳过程
- // 重合闸检同期
- // bCQD7 =xdl_ar_check(pSet->dCKModes);
- // 三跳启动重合闸
- #if 0
- pSW->sta.bFlag.bTLQD = pSW->sta.bFlag.bCDWC // 重合闸充电完成
- &&bCQD7 // 湖南专检重合闸检同期
- &&pSW->sta.bFlag.bXDLDZ //
- && (!pSW->sta.bFlag.bCHQD); // 三相启动重合闸未启动
- #else
- pSW->sta.bFlag.bTLQD = pSW->sta.bFlag.bCDWC // 重合闸充电完成
- &&pSW->sta.bFlag.bXDLDZ //
- && (!pSW->sta.bFlag.bCHQD); // 三相启动重合闸未启动
- #endif
- // 三相启动重合闸
- bCHQD_CHQD = pSW->sta.bFlag.bTTQD // 偷跳启动重合闸
- || pSW->sta.bFlag.bTLQD // 三跳启动重合闸
- || bCQD6; // 三相启动重合闸
- if( bCHQD_CHQD )
- {
- if( !pSW->sta.bFlag.bCHQD ) //重合开出标尚未置位
- {
- pSW->sta.bFlag.bCHQD = true; //此标志会一直维持到重合闸出口或充电标志放电
- pSW->sta.bFlag.bQDFG=true; //整组复归时有效
- soe_record_ev(EV_AR_START+sw*EV_SW_NUM, 1, 0,0,0);//重合启动SOE
- //rcd_start(sw,RECORD_TYPE_CHZ, RECORD_LEN_TZQD); //录波类型:跳闸类
- }
- }
- else
- {
- if( pSW->sta.bFlag.bCHQD )
- {
- pSW->sta.bFlag.bCHQD = false;
- soe_record_ev(EV_AR_START+sw*EV_SW_NUM,0 ,0,0,0);
- }
- }
- }
- /**************************************************************************
- 函数名称: xdl_ar_logic
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸逻辑
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- static void xdl_ar_logic(DWORD dStep)
- {
- bool bWCN;
- u32 sw = g_protect.sw;
- TRELAY_T *pR=&g_tRelay[sw];
- TXDLCH_T *pSW =&pR->tXDLCHZ;
- TSETSW *pSet = &pRunSet->tSwSet[sw];
- bool bHZL1,bHZL2,bHZL3,bHZL4,bHZL5,bHZL6,bHZL8,bHZL9;
- // 重合闸条件准备
- bHZL1 = BH_ALL_EN(sw) // 总投退
- && pSet->bTT_xdltz // 小电流跳闸投入
- && pR->run_stu.chz // 重合闸硬压板投入
- && pSW->sta.bFlag.bCHQD // 三相启动重合闸
- && pSW->sta.bFlag.bCDWC; // 重合闸充电完成
-
- RunTR(&pSW->tTXDLCHJD_ARDelay, bHZL1, dStep); //重合延时
- bHZL2 = pSW->tTXDLCHJD_ARDelay.boolTrip;
- // 弹簧未储能下降沿展宽30ms
- bWCN = pR->run_stu.wcn && pSet->bTT_WCN;
- RunTR(&pSW->tTXDLCHJD_0ms30ms, bWCN, dStep);
- bHZL3 = pSW->tTXDLCHJD_0ms30ms.boolTrip;
- // 重合闸检同期
- bHZL9 =xdl_ar_check(pSet->dCKModes);
- // 重合闸条件准备好,弹簧储能OK,重合闸出口
- pSW->sta.bFlag.bCHCK = (!bHZL3) && bHZL2 && bHZL9;
-
- // 重合闸开出自保持
- bHZL4 = pSW->sta.bFlag.bHz || pSW->sta.bFlag.bCHCK;
- // 重合开出持续200ms
- RunTR(&pSW->tTXDLCHJD_200ms0ms, bHZL4, dStep);
- bHZL5 = pSW->tTXDLCHJD_200ms0ms.boolTrip;
- // 重合闸开出,经过200ms后开出解除
- pSW->sta.bFlag.bHz =bHZL4 && (!bHZL5);
- // 重合闸指令发出后,且开关已经跳闸完成
- bHZL6 = pSW->sta.bFlag.bHz || pSW->sta.bFlag.bHZL7;
- pSW->sta.bFlag.bHZL7 = pR->tSWST.uSWST.bFlag.bTZWZ && bHZL6;
- // 开放后加速允许有效延时200ms展宽
- RunTR(&pSW->tTXDLCHJD_HJS, pSW->sta.bFlag.bHZL7, dStep);
- bHZL8 = pSW->tTXDLCHJD_HJS.boolTrip;
- pSW->sta.bFlag.bCHJS = pSW->tTXDLCHJD_HJS.boolTrip
- && (!pR->tSWST.uSWST.bFlag.bTZWZ);
- //出口及发信
- if(pSW->sta.bFlag.bHz)
- {
- if(!pSW->sta.bFlag.bEvent) //重合开出标尚未置位
- {
- // 检零压后加速标识
- XDLCHZWC = 1;
- //亮重合动作灯
- pSW->sta.bFlag.bCHZLed = true;
-
- pSW->wAR_ActTimes++; //重合动作次数
- pSW->sta.bFlag.bEvent = true;
- //pSW->uCHFG.wfFlag=0; //每次重合出口后,清重合复归标志 修改时注意,此处需对标志字特殊处理
- pSW->sta.bFlag.bCHDZ=false; //重合闸动作
- pSW->sta.bFlag.bBYSD=false; //重合闸闭锁时间到
- pSW->sta.bFlag.bCHFD=false; //重合闸动作放电
- pSW->sta.bFlag.bCHBS=false; //重合闸闭锁
- pSW->sta.bFlag.bCK=false; //放电条件1
- if(pSW->wAR_ActTimes==1)
- {
- soe_record_ev(EV_AR1+sw*EV_SW_NUM, 1, 0,0,0); //重合动作SOE
- }
- else if(pSW->wAR_ActTimes==2)
- {
- soe_record_ev(EV_AR2+sw*EV_SW_NUM, 1, 0,0,0); //重合动作SOE
- }
- else
- {
- soe_record_ev(EV_AR3+sw*EV_SW_NUM, 1, 0,0,0); //重合动作SOE
- }
- rcd_start(sw,RECORD_TYPE_CHZ,RECORD_LEN_TZQD);
- ResetTR(&pSW->tTXDLCHFAIL_TW); // 重合出口后,重新复归时间继电器
- ResetTR(&pSW->tTXDLCHOKTime); //重合成功时间继电器,在重合出口后重新计数
- ResetTR(&pSW->tTXDLCHBSDelay); //闭锁重合延时继电器重新计数
-
- }
- }
- else
- {
- if( pSW->sta.bFlag.bEvent ) //重合开出标尚未置位
- {
- pSW->sta.bFlag.bEvent = false;
-
- if(soe_check(EV_AR1+sw*EV_SW_NUM))
- {
- soe_record_ev(EV_AR1+sw*EV_SW_NUM, 0, 0,0,0 ); //重合1动作SOE返回
- }
- if(soe_check(EV_AR2+sw*EV_SW_NUM))
- {
- soe_record_ev(EV_AR2+sw*EV_SW_NUM, 0, 0,0,0 ); //重合2动作SOE返回
- }
- if(soe_check(EV_AR3+sw*EV_SW_NUM))
- {
- soe_record_ev(EV_AR3+sw*EV_SW_NUM, 0, 0,0,0 ); //重合3动作SOE返回
- }
- }
- }
- }
- /**************************************************************************
- 函数名称: xdl_ar_reset
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.6.10
- 函数功能说明:小电流重合闸复归
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- static void xdl_ar_reset(DWORD dStep)
- {
- u32 sw = g_protect.sw;
- TRELAY_T *pR=&g_tRelay[sw];
- TXDLCH_T *pSW =&pR->tXDLCHZ;
- bool bFD1;
- // 重合闸动作后,即启动重合闸闭锁时间,在此时间内,有保护动作即闭锁重合闸
- // 重合闸出口且重合闸动作次数<整定动作次数,重合闸闭锁
- pSW->sta.bFlag.bCHDZ = (pSW->sta.bFlag.bCHCK && (pSW->wAR_ActTimes<1))
- || pSW->sta.bFlag.bCHBS;
- // 重合闸闭锁延时,从重合闸动作开始统计
- RunTR(&pSW->tTXDLCHBSDelay, pSW->sta.bFlag.bCHDZ, dStep);
- pSW->sta.bFlag.bBYSD = pSW->tTXDLCHBSDelay.boolTrip;
-
- pSW->sta.bFlag.bCHBS = (pSW->wAR_ActTimes<1) // 未到最后一次重合
- && pSW->sta.bFlag.bCHDZ // 一次重合闸动作
- && (!pSW->sta.bFlag.bBYSD); // 重合闸闭锁时间未到
- // 重合闸出口后,经过重合闸确认时间,无保护动作,即放电,完成该次重合过程
- // 如果在确认时间内,重合闭锁时间外,有保护动作,即进入下一计数重合
- pSW->sta.bFlag.bCK = ((!pR->uBHDZ.bFlag.bBHT)
- && (pSW->sta.bFlag.bCHCK || pSW->sta.bFlag.bCK)); //重合出口及自保持
- RunTR(&pSW->tTXDLCHOKTime, pSW->sta.bFlag.bCK, dStep);
- bFD1 = pSW->tTXDLCHOKTime.boolTrip;
- // 重合闸闭锁时间内,有保护动作,放电
- // 重合闸次数已到最大,放电
- // 重合成功,重合闸确认时间内无保护动作,放电
- pSW->sta.bFlag.bCHFD = (pR->uBHDZ.bFlag.bBHT && pSW->sta.bFlag.bCHBS)
- || (pSW->sta.bFlag.bCHCK && (pSW->wAR_ActTimes>=1))
- || bFD1;
- // 整组复归条件:(1)重合闸放电(2)重合已启动,但充电标志已清零
- if(pSW->sta.bFlag.bCHFD
- || (!pSW->sta.bFlag.bCDWC && pSW->sta.bFlag.bQDFG))
- {
- pSW->sta.bFlag.bQDFG = false;
- }
- }
- /**************************************************************************
- 函数名称: xdl_ar_check
- 函数版本:1.00
- 函数版本:1.00
- 作者: 赵海洋
- 创建日期:2021.06.10
- 函数功能说明:重合闸检同期
- 0:无检定;1:检一侧有压一侧无压;2:检同期;3:检一侧有压一侧无压+检同期
- 输入参数:
- 输出参数:
- 返回值:
- ***************************************************************************/
- #if 1
- static int xdl_ar_check(DWORD mode)
- {
- // 0:无检定;1:检一侧有压一侧无压;2:检同期;3:检一侧有压一侧无压+检同期
- u32 sw = g_protect.sw;
- TSETSW *pSet = &pRunSet->tSwSet[sw];
- TRELAY_T *pR=&g_tRelay[sw];
- DWORD deltaU1=0,deltaU2=0,deltaU3=0;
- bool Volt,Volt1,Volt2,Volt3,angle1,bFEQ=false;
- bool bY1 ,bY2 , sp , bLock = false;
- int ret = 0;
- bY1= ((!g_run_stu.pt1yy) && g_run_stu.pt2yy);
- bY2= (g_run_stu.pt1yy && (!g_run_stu.pt2yy));
- bLock = bY1 || bY2;
- switch (mode)
- {
- case 0:
- ret = 1 ;
- break;
- case 1:
- /* 检一侧有压一侧无压 */
- ret = bLock;
- break;
- case 2:
- /* 检同期 */
- // 分别取出两侧各线电压压差
- deltaU1 = _AbsL(g_ui[PUB_AC_UAB1].fz - g_ui[PUB_AC_UAB2].fz);
- deltaU2 = _AbsL(g_ui[PUB_AC_UBC1].fz - g_ui[PUB_AC_UBC2].fz);
- deltaU3 = _AbsL(g_ui[PUB_AC_UCA1].fz - g_ui[PUB_AC_UCA2].fz);
- // 角差与定值比对
- angle1 = SynAngle(g_ui[PUB_AC_UAB1].p, g_ui[PUB_AC_UAB2].p,pSet->dTQ_ANGLE_FZ);
- // 频差与定值比对
- bFEQ = SynFrequency(g_sw_pub.ac_in[PUB_AC_IN_F1],g_sw_pub.ac_in[PUB_AC_IN_F2],pSet->dTQ_FREQ_FZ);
- // 压差与定值比对
- Volt1 = LowRelay(deltaU1, pSet->dTQ_U_FZ, pSet->dTQ_U_FZ_fh, false);
- Volt2 = LowRelay(deltaU2, pSet->dTQ_U_FZ, pSet->dTQ_U_FZ_fh, false);
- Volt3 = LowRelay(deltaU3, pSet->dTQ_U_FZ, pSet->dTQ_U_FZ_fh, false);
- Volt = Volt1&&Volt2&&Volt3;
- sp = Volt&&angle1&&bFEQ&&(!pR->tSWST.uSWST.bFlag.bDIHW);
- ret = sp;
- break;
- case 3:
- /* 检一侧有压一侧无压+检同期 */
- // 分别取出两侧各线电压压差
- deltaU1 = _AbsL(g_ui[PUB_AC_UAB1].fz - g_ui[PUB_AC_UAB2].fz);
- deltaU2 = _AbsL(g_ui[PUB_AC_UBC1].fz - g_ui[PUB_AC_UBC2].fz);
- deltaU3 = _AbsL(g_ui[PUB_AC_UCA1].fz - g_ui[PUB_AC_UCA2].fz);
- // 角差与定值比对
- angle1 = SynAngle(g_ui[PUB_AC_UAB1].p, g_ui[PUB_AC_UAB2].p,pSet->dTQ_ANGLE_FZ);
- // 频差与定值比对
- bFEQ = SynFrequency(g_sw_pub.ac_in[PUB_AC_IN_F1],g_sw_pub.ac_in[PUB_AC_IN_F2],pSet->dTQ_FREQ_FZ);
- // 压差与定值比对
- Volt1 = LowRelay(deltaU1, pSet->dTQ_U_FZ, pSet->dTQ_U_FZ_fh, false);
- Volt2 = LowRelay(deltaU2, pSet->dTQ_U_FZ, pSet->dTQ_U_FZ_fh, false);
- Volt3 = LowRelay(deltaU3, pSet->dTQ_U_FZ, pSet->dTQ_U_FZ_fh, false);
- Volt = Volt1&&Volt2&&Volt3;
- sp = Volt&&angle1&&bFEQ&&(!pR->tSWST.uSWST.bFlag.bDIHW);
- if (bLock)
- {
- ret =1;
- }
- else if ((!bLock) && sp)
- {
- ret =1;
- }
- else
- {
- ret = 0;
- }
- // ret = (!bLock) && sp;
- break;
- default:
- ret = 0 ;
- break;
- }
- return ret;
- }
- #endif
- #endif
- int xdl_get_chan_cnt(void)
- {
- return XDL_RCD_A_NUM;
- }
- char * xdl_get_chan_name(int chan_no)
- {
- if(chan_no >= XDL_RCD_A_NUM)
- {
- return NULL;
- }
- return g_xdl_rcd_a[chan_no];
- }
- // 小电流录波点值获取函数
- s16 xdl_rcd_a(int chn,int idx)
- {
- int i;
- //s16 v;
-
- switch(chn)
- {
- case 0:
- return g_u0_raw[idx];
- case 1:
- return g_u0[idx];
- case 2:
- for(i=0;i<XDL_SEG_NUM;i++)
- {
- if(g_u0_seg[i].dir)
- {
- #if 1
- if(idx>=g_u0_seg[i].bgn && idx <= g_u0_seg[i].end)
- {
- return g_u0[idx];
- }
- #else
- if(idx == (g_u0_seg[i].end + g_u0_seg[i].bgn)/2)
- {
- v = g_u0_seg[i].acc/2;
- v = v > 32767 ? 32767 : v;
-
- return v*g_u0_seg[i].dir;
- }
- else if(idx>=g_u0_seg[i].bgn && idx <= g_u0_seg[i].end)
- {
- v = g_u0_seg[i].acc/4;
- //v = g_u0_seg[i].acc/(g_u0_seg[i].end - g_u0_seg[i].bgn +1);
- v = v > 32767 ? 32767 : v;
-
- return v*g_u0_seg[i].dir;
- }
- #endif
- }
- }
- return 0;
- case 3:
- for(i=0;i<XDL_SEG_NUM;i++)
- {
- if(g_u0_seg[i].dir && idx == g_u0_seg[i].max_p)
- {
- return g_u0_seg[i].max_v*g_u0_seg[i].dir;
- }
- }
- return 0;
- case 4:
- return g_i0_raw[idx];
- case 5:
- return g_i0[idx];
- case 6:
- for(i=0;i<XDL_SEG_NUM;i++)
- {
- if(g_i0_seg[i].dir)
- {
- #if 1
- if(idx>=g_i0_seg[i].bgn && idx <= g_i0_seg[i].end)
- {
- return g_i0[idx];
- }
- #else
- if(idx == (g_i0_seg[i].end + g_i0_seg[i].bgn)/2)
- {
- v = g_i0_seg[i].acc/2;
- v = v > 32767 ? 32767 : v;
-
- return v*g_i0_seg[i].dir;
- }
- else if(idx>=g_i0_seg[i].bgn && idx <= g_i0_seg[i].end)
- {
- v = g_i0_seg[i].acc/4;
- // v = g_i0_seg[i].acc/(g_i0_seg[i].end - g_i0_seg[i].bgn +1);
- v = v > 32767 ? 32767 : v;
-
- return v*g_i0_seg[i].dir;
- }
- #endif
- }
- }
- return 0;
- case 7:
- for(i=0;i<XDL_SEG_NUM;i++)
- {
- if(g_i0_seg[i].dir && idx == g_i0_seg[i].max_p)
- {
- return g_i0_seg[i].max_v*g_i0_seg[i].dir;
- }
- }
- return 0;
- }
- return 0;
- }
- // 方向包括-1、0、+1,共3个值
- // 方向相反:两个数一正一负,不包含0
- // 主要用于检测电压、电流是否反向。
- static inline int _xdl_dir_inv(int v0,int v1)
- {
- if((v0>0 && v1<0) || (v0<0 && v1>0))
- {
- return 1;
- }
- return 0;
- }
- // 方向相同:两个数同时为3个方向值中的一个,包含0
- // 主要用在判断区域是否完整。
- static inline int _xdl_dir_equ(int v0,int v1)
- {
- if((v0>0 && v1>0) || (v0<0 && v1<0) || (v0==0 && v1==0))
- {
- return 1;
- }
- return 0;
- }
- // 区域更新,保留最大值最大的几个区域
- void _xdl_seg_update(struct segment * seg_a,struct segment * seg,struct segment * u_seg, uint *updateNum)
- {
- int i,j;
- int space_num = 0;
- // s32 u_end = u_seg->end + 4; //扩大4个点
- if(seg->dir == 0)
- {
- return;
- }
- //上下两部分:重点->上半部主要处理以“电压段范围内”索引的电流区域
- // 下半部为大于“电压段范围内”索引的电压区域,通常不会用到
- // 如果u_end < seg->end,当u_seg->bgn == seg->bgn,则判定为稳态触发,需放入上半部
- // if((u_end < seg->end) && (u_seg->bgn != seg->bgn))
- // space_num = XDL_SEG_NUM>>1;
- // else
- // space_num = 0;
-
- for(i=space_num;i<XDL_SEG_NUM;i++)
- {
- if(seg->max_v > seg_a[i].max_v)
- {
- if( (*updateNum)++ >= XDL_SEG_NUM) /**< 更新满XDL_SEG_NUM后,不再更新 */
- {
- return;
- }
- for(j=XDL_SEG_NUM-1;j>i;j--)
- {
- seg_a[j] = seg_a[j-1];
- }
-
- seg_a[i] = *seg;
- return;
- }
- }
- return;
- }
- // 区域排序,根据时间顺序排序
- void _xdl_seg_sort(struct segment * seg_a)
- {
- u32 i,j,index;
- struct segment s;
- for(i=0;i<XDL_SEG_NUM-1;i++)
- {
- index = i;
- for(j=i+1;j<XDL_SEG_NUM;j++)
- {
- // 区域存在,且在前面就调整
- if(seg_a[j].dir && seg_a[j].bgn < seg_a[index].bgn)
- {
- index = j;
- }
- }
- if(index != i)
- {
- s = seg_a[i];
- seg_a[i] = seg_a[index];
- seg_a[index] = s;
- }
- }
- return;
- }
- // 检查区域是否完整,完整的区域指区域首尾和区域外的值的方向不同。
- int _xdl_seg_is_complete(s16 *dot,struct segment * seg,s32 zero)
- {
- if(_xdl_dir_equ(dot[seg->bgn -1]-zero,dot[seg->bgn]-zero))
- {
- return 0;
- }
-
- if(_xdl_dir_equ(dot[seg->end]-zero,dot[seg->end+1]-zero))
- {
- return 0;
- }
- return 1;
- }
- // 如果mode为1,扩大区域范围(0算在范围内),电压使用。
- int _xdl_seg_search(s16 *dot,u32 bgn,u32 end,struct segment * seg,int mode)
- {
- s32 v,dir;
- u32 i;
- memset(seg,0,sizeof(*seg));
- if(mode)
- {
- seg->bgn = bgn;
- }
- for(i=bgn;i<=end;i++)
- {
- // 得到值和方向
- v = dot[i];
- if(v)
- {
- dir = v > 0 ? 1 : -1;
- }
- else
- {
- dir = 0;
- }
- v = abs(v);
-
- // 初始化区间
- if(seg->dir == 0)
- {
- if(dir)
- {
- seg->dir = dir;
- seg->acc += v;
- seg->max_v = v;
-
- if(mode == 0)
- {
- seg->bgn = i;
- }
- seg->end = i;
- seg->max_p = i;
- }
- }
- // 当前区间处理
- else
- {
- // 反向,当前区间结束
- if(mode)
- {
- if(dir == -seg->dir)
- {
- return 1;
- }
- }
- else
- {
- if(dir != seg->dir)
- {
- return 1;
- }
- }
-
- // 同相,扩大区间
- seg->acc += v;
- seg->end = i;
- if(v > seg->max_v)
- {
- seg->max_v = v;
- seg->max_p = i;
- }
- }
- }
- seg->dir = 0;
- return 0;
- }
- // 微分增速段搜索,微分0在前面
- int _xdl_seg_search_ds_f(s16 *dot,u32 u_set,u32 bgn,u32 end,struct segment * seg)
- {
- s32 v,dir,dir_old;
- u32 i;
- s32 next_v;
- s32 zct = 0, zct_pre = 0, zct_i = 0;
- memset(seg,0,sizeof(*seg));
- dir = 0;
- dir_old = 0;
- seg->bgn = bgn;
- for(i=bgn;i<=end;i++)
- {
-
- // 得到值和方向
- dir_old= dir;
- v = dot[i]-dot[i-1];
- if(v)
- {
- dir = v > 0 ? 1 : -1;
- }
- else
- {
- dir = 0;
- }
- v = abs(v);
-
- // 初始化区间
- if(seg->dir == 0)
- {
- if(dir)
- {
- seg->acc = v;
- seg->dir = dir;
- seg->end = i;
- zct_i = i; //by ygl 电压需要逼近突变点,第一个微分不为0的点
- }
- zct_pre = (dot[i] > 0 ? 1 : -1);
- }
- // 当前区间处理
- else
- {
- /* 寻找过零点,为了开始平缓转突变的数据*/
- zct = (dot[i] > 0 ? 1 : -1);
- if(zct != zct_pre){
- zct_i = i;
- zct_pre = zct;
- }
- if((dir == -seg->dir)|| ((dir == 0) && (dir_old==0)))
- {
- if (i < end)
- {
- next_v = (dot[i+1]-dot[i]) > 0? 1:-1; //ygl 再往下推算一个点的方向
- if(dir == -next_v) //如果和当前方向不一致,则判为瞬变
- {
- dir = next_v; //保存方向 注意此时:next_v == seg->dir
- seg->acc += v;
- seg->end = i;
- continue; //继续搜索下一个点
- }
- }
- // 退一步,退回本区域内
- i--;
- seg->max_p = i;
- seg->max_v = abs(dot[i]);
- // 最大值计算忽略末尾微分为0的点
- while(i>seg->bgn)
- {
- if(dot[i] != dot[i-1])
- {
- break;
- }
- i--;
- }
- break;
- }
- // 同相,扩大区间
- seg->acc += v;
- seg->end = i;
- }
- }
- if(seg->dir){
-
- if( abs(dot[seg->max_p] - dot[seg->bgn-1]) < u_set)
- {
- seg->dir = 0;
- }
-
- /* 开始点大于定值,则电压差值必须是开始点的4倍以上。否则清零 */
- v = abs(dot[seg->bgn-1]);
- if(v > u_set && (v*4 > abs(dot[seg->max_p] - dot[seg->bgn-1])))
- {
- seg->dir = 0;
- }
- /*如果方向有效,则调整电流开始点为“过零点”或“第一个微分不为0的点”开始*/
- if(zct_i != 0 && seg->dir != 0){
- seg->bgn = zct_i-1;
- // if(zct == zct_pre) //如果没产生过零点
- // seg->bgn -= 1;
- }
- return 1;
- }
- return 0;
- }
- // 微分增速段搜索,微分0在后面
- int _xdl_seg_search_ds_r(s16 *dot,u32 i_set,u32 bgn,u32 end,struct segment * seg,struct segment * u_seg)
- {
- s32 v,dir,dir_old,b_add;
- u32 i;
- s32 next_v = 0;
- s32 U_mean = 0; //对应零压均值
- memset(seg,0,sizeof(*seg));
-
- u_seg->acc = 0;
- dir = 0;
- dir_old = 0;
- b_add = 0;
- for(i=bgn;i<=end;i++)
- {
- if(u_seg->acc) // 有首次后,累加
- u_seg->acc += g_u0[i-1];
- // 得到值和方向
- dir_old= dir;
- v = dot[i]-dot[i-1];
- if(v)
- {
- dir = v > 0 ? 1 : -1;
- }
- else
- {
- dir = 0;
- }
- v = abs(v);
-
- // 初始化区间
- if(seg->dir == 0)
- {
- if(dir)
- {
- seg->acc += v;
- u_seg->acc += g_u0[i-1]; //by ygl 记录首零压值
- seg->dir = dir;
- seg->bgn = i;
- seg->end = i;
- }
- }
- // 当前区间处理
- else
- {
- // 反向,当前区间结束
- // if((dir == -seg->dir)|| (dir && (dir_old==0)))
- if((dir == -seg->dir && seg->dir)|| ((dir == 0) && (dir_old==0)))
- {
- if (i < end)
- {
- next_v = (dot[i+1]-dot[i]) > 0? 1:-1; //ygl 再往下推算一个点的方向
- //1、如果启动方向和当前方向一致,则判为瞬变 例:5、3、3、2、3、3、4、、、、
- //2、连续微分为0的点,则判阶梯波形 例:1、2、3、3、3、3、4、、、、
- if(seg->dir == next_v || ((next_v == 0) && (dir == 0)))
- {
- dir = next_v; //保存方向 注意此时:next_v == seg->dir
- seg->acc += v;
- seg->end = i;
- continue; //继续搜索下一个点
- }
- }
- U_mean = (abs(u_seg->acc)-abs(g_u0[i-1]))/(i-seg->bgn); //ygl 根据当前零流段,计算对应区间零压均值
- if(U_mean)
- u_seg->max_v = abs(g_u0[seg->end] - g_u0[seg->bgn])*10/U_mean; //零压区间变化率
- // 退一步,退回本区域内
- i--;
- seg->max_p = i;
- seg->end = i;
- seg->max_v = abs(dot[i] - dot[seg->bgn-1]);
- // seg->max_v = abs(dot[i]); - ygl
- // 最大值计算忽略末尾微分为0的点
- while(i>seg->bgn)
- {
- if(dot[i] != dot[i-1])
- {
- break;
- }
- i--;
- }
- break;
- //return 1;
- }
-
- // 同相,扩大区间
- seg->acc += v;
- seg->end = i;
- }
- }
- #if 0
- // 如果区域不是以微分0结尾,延长到下一个微分最大值的位置
- // 否则有可能判不到电压方向
- if(dir_old)
- {
- for(i++;i<=end;i++)
- {
- if(_xdl_dir_equ(dir,dot[i] - dot[i-1]) == 0)
- {
- seg->end = i;
- break;
- }
-
- }
- }
- #endif
-
- if(seg->dir)
- {
- #if 1
- // 零流首半波条件:
- // 1、开始点小于定值或电流差值是开始点的4倍以上。其中第二点是考虑在定值尽量小的情况下,
- // 如果有大的零序电流出现,其开始点可能大于定值,但其结束点拥有更大的值,有利于提高
- // 判断的准确性。
- // 2、开始点结束点之差大于定值。使用此条件,导致启动后可能找不到首半波,
- // 但如果不使用此条件,仅使用最大值大于定值条件,则可能导致极小电流差值启动判断,
- // 最终导致判断失误。
- v = abs(dot[seg->bgn-1]);
- if(v == 0)
- {
- v = 1;
- }
- // if(v > i_set && (v*4 > abs(dot[seg->max_p] - dot[seg->bgn-1])))
- // {
- // seg->dir = 0;
- // }
- //如果已经电流区域结束点超载了“电压区域结束点”,则要增加差值
- if(u_seg->end < seg->end){
- i_set *= 2;
- // rt_printf("丢弃1:bgn=%d,end=%d,dot=%d, i_set=%d.\r\n",seg->bgn,seg->end,dot[seg->bgn-1],i_set);
- }
- //零压变化率小于30%”,定值尽量小,则要增加差值
- if(u_seg->max_v < 3){
- i_set *= 6;
- // rt_printf("丢弃2:bgn=%d,end=%d,dot=%d, i_set=%d.\r\n",seg->bgn,seg->end,dot[seg->bgn-1],i_set);
- }
-
- if( abs(dot[seg->max_p] - dot[seg->bgn-1]) < i_set)
- {
- seg->dir = 0;
- // rt_printf("丢弃3:bgn=%d,end=%d,dot=%d, i_set=%d.\r\n",seg->bgn,seg->end,dot[seg->bgn-1],i_set);
- }
- #else
- if(i_set == 0)
- {
- if((abs(dot[seg->bgn-1])*4 > abs(dot[seg->max_p] - dot[seg->bgn-1])))
- {
- seg->dir = 0;
- }
- }
- else
- {
- if(abs(dot[seg->bgn-1]) > i_set)
- {
- // rt_printf("丢弃:bgn=%d,end=%d,dot=%d.\r\n",seg->bgn,seg->end,dot[seg->bgn-1]);
- seg->dir = 0;
- }
- }
- #endif
- return 1;
- }
-
- return 0;
- }
- // 微分增速段搜索
- int _xdl_seg_search_ds(s16 *dot,u32 bgn,u32 end,struct segment * seg)
- {
- s32 v,dir,dir_old;
- u32 i;
- memset(seg,0,sizeof(*seg));
- dir = 0;
- dir_old = 0;
- for(i=bgn;i<=end;i++)
- {
-
- // 得到值和方向
- dir_old= dir;
- v = dot[i]-dot[i-1];
- if(v)
- {
- dir = v > 0 ? 1 : -1;
- }
- else
- {
- dir = 0;
- }
- v = abs(v);
-
- // 初始化区间
- if(seg->dir == 0)
- {
- if(dir)
- {
- seg->acc += v;
- seg->dir = dir;
- seg->bgn = i;
- seg->end = i;
- }
- }
- // 当前区间处理
- else
- {
- // 反向,当前区间结束
- // if(dir != seg->dir)
- if((dir == -seg->dir)|| (dir && (dir_old==0)))
- {
- i--;
- if(_xdl_dir_inv(dot[i],dot[bgn-1]))
- {
- // seg->max_v = abs(dot[i]);
- seg->max_v = abs(dot[i])*10/(i-seg->bgn+1);
- }
- else
- {
- seg->max_v = abs(dot[i] - dot[seg->bgn-1])*10/(i-seg->bgn+1);
- // seg->max_v = abs(dot[i] - dot[seg->bgn-1]);
- }
- seg->max_p = i;
- // rt_printf("v=%d,p=%d.\r\n",seg->max_v,seg->max_p);
- return 1;
- }
-
- // 同相,扩大区间
- seg->acc += v;
- seg->end = i;
- }
- }
- seg->dir = 0;
- return 0;
- }
- // 处理波形的微分和零轴移动
- int _xdl_proc_diff_zero(s16 *ui0,s16 *ui0_d,int wave_len,u32 set,struct point *max_d)
- {
- int i,v0,v;
- u32 min_d; // 最小微分值
- struct point max_ui;
- // 求导,并得到最大差分值
- min_d = -1;
- max_d->p = 0;
- max_d->v = 0;
- max_ui.p = 0;
- max_ui.v = abs(ui0[0]);
- for(i=1; i<wave_len;i++)
- {
- // 微分求导
- v0 = ui0[i] -ui0[i-1];
- v = abs(v0);
- // 取得最小微分值
- if(v != 0 && v < min_d)
- {
- min_d = v;
- }
- // 计算微分最大值
- if(v > abs(max_d->v))
- {
- max_d->v = v0;
- max_d->p = i;
- }
- // 计算原值最大值
- if(abs(ui0[i]) > abs(max_ui.v))
- {
- max_ui.v = ui0[i];
- max_ui.p = i;
- }
- }
- max_d->v = max_ui.v;
- v = set == 0 ? (5*min_d) : set;
- if(abs(max_ui.v) < v)
- {
- return -2;
- }
- return 0;
- }
- // 三点线性平滑
- void xdl_f_smooth3 ( short in[], float out[], int N )
- {
- int i;
- if ( N < 3 )
- {
- for ( i = 0; i <= N - 1; i++ )
- {
- out[i] = in[i];
- }
- }
- else
- {
- out[0] = ( 5 * in[0] + 2 * in[1] - in[2]) / 6;
- for ( i = 1; i <= N - 2; i++ )
- {
- out[i] = ( in[i - 1] + in[i] + in[i + 1]) / 3;
- }
- out[N - 1] = ( 5 * in[N - 1] + 2 * in[N - 2] - in[N - 3]) / 6;
- }
- }
- // 三点线性平滑
- void xdl_smooth3 ( short in[], short out[], int N )
- {
- int i;
- if ( N < 3 )
- {
- for ( i = 0; i <= N - 1; i++ )
- {
- out[i] = in[i];
- }
- }
- else
- {
- out[0] = ( 5 * in[0] + 2 * in[1] - in[2]) / 6;
- for ( i = 1; i <= N - 2; i++ )
- {
- out[i] = ( in[i - 1] + in[i] + in[i + 1]) / 3;
- }
- out[N - 1] = ( 5 * in[N - 1] + 2 * in[N - 2] - in[N - 3]) / 6;
- }
- }
- //五点线性平滑
- void xdl_smooth5 ( short in[], short out[], int N )
- {
- int i;
- if ( N < 5 )
- {
- for ( i = 0; i <= N - 1; i++ )
- {
- out[i] = in[i];
- }
- }
- else
- {
- out[0] = ( 3 * in[0] + 2 * in[1] + in[2] - in[4] +3) / 5;
- out[1] = ( 4 * in[0] + 3 * in[1] + 2 * in[2] + in[3] +5) / 10;
- for ( i = 2; i <= N - 3; i++ )
- {
- out[i] = ( in[i - 2] + in[i - 1] + in[i] + in[i + 1] + in[i + 2] +3) / 5;
- }
- out[N - 2] = ( 4 * in[N - 1] + 3 * in[N - 2] + 2 * in[N - 3] + in[N - 4] +5) / 10;
- out[N - 1] = ( 3 * in[N - 1] + 2 * in[N - 2] + in[N - 3] - in[N - 5] +3) / 5;
- }
- }
- // 零序电压启动后,调用此函数查找故障线路
- // 采用暂态零序电流方向法:
- // 1、零序电压求导。
- // 2、暂态零序电流与零序电压导数比较极性。
- // 3、极性相反的选定为故障线路。
- // 4、此判据只在首半波内有效。
- //
- int xdl_proc_u0(int len,u32 u_set)
- {
- int bgn,ret;
- struct segment seg;
- struct point max_d;
-
- // memset(g_u0_raw,0,sizeof(g_u0_raw));
- memset(g_u0_seg,0,sizeof(g_u0_seg));
-
- // 零序电压求导
- ret = _xdl_proc_diff_zero(g_u0_raw,0,len,0,&max_d);
- if(ret < 0)
- {
- return ret;
- }
-
- // 搜索几个电压变化最大的区间
- bgn = 1;
- // while(_xdl_seg_search(g_u0_raw,bgn,len-1,&seg,1))
- while(_xdl_seg_search_ds_f(g_u0,u_set,bgn,len-1,&seg))
- {
- _xdl_seg_update(g_u0_seg,&seg,NULL, NULL);
- #if 1
- bgn = seg.end + 1;
- #else
- // 得到下一个区域的开始点,和上一个区域的零结束点重合
- for(bgn = seg.end;bgn>0;bgn--)
- {
- if(g_u0_raw[bgn] != 0)
- {
- break;
- }
- }
- bgn++;
- #endif
- }
- // 将搜索出的区域按时间排序
- _xdl_seg_sort(g_u0_seg);
- return 0;
- }
- #define seg_extend_dot 8
- int xdl_seg_u0_ok(int len,struct segment * seg, u32 u_set)
- {
- u32 bgn,end,i;
- s16 v_bgn;
- s16 max_v = 0;
- s16 limit_end = seg->end + seg_extend_dot; //扩展首半波至少范围,
- // 扩展首半波范围,电压延后16个点,45度。
- bgn = seg->bgn > 0 ? (seg->bgn -1) : seg->bgn;
- end = seg->end + (seg->end - seg->bgn); //seg_extend_dot -> (seg->end - seg->bgn)
- end = end > limit_end ? end : limit_end;
- if(end >= len)
- {
- end = len;
- }
-
- // 检查电压幅值,在此区域后,必须有电压大于设定值
- // v_bgn = g_u0[bgn];
- max_v = v_bgn = g_u0[bgn];
- // rt_printf("u0 check fail bgn=%d,end =%d,max_v = %d,v_bgn = %d,set = %d\r\n",bgn,end,max_v,v_bgn,u_set);
- for(i=bgn;i<end;i++)
- {
- if(max_v < g_u0[i])
- max_v = g_u0[i];
- if(abs(g_u0[i] - v_bgn) > u_set)
- {
- // rt_printf("u0 check ok bgn=%d,end =%d,max_v = %d,v_bgn = %d,v_p = %d,set = %d\r\n",bgn,end,max_v,v_bgn,i,u_set);
- return 1;
- }
- }
-
- return 0;
- }
- int xdl_seg_i0_ok(int len,struct segment * seg, u32 i_set)
- {
- u32 bgn,end,i;
- s16 v_bgn;
- // 扩展首半波范围,电流延后16个点,45度。
- bgn = seg->bgn > 0 ? (seg->bgn -1) : seg->bgn;
- end = seg->end + 8;
- if(end >= len)
- {
- end = len;
- }
-
- // 检查电压幅值,在此区域后,必须有电压大于设定值
- v_bgn = g_i0[bgn];
- for(i=bgn;i<end;i++)
- {
- if(abs(g_i0[i] - v_bgn) > i_set)
- {
- return 1;
- }
- }
- return 0;
- }
- #define U_SET_COEF 1
- int xdl_proc_i0(uint32_t sw,int len,u32 i_set,u32 u_set,int *ps,int h_sign)
- {
- int i,s,bgn=1,end,ret,dir=0;
- int j =0, hilbert_count =0;
- u32 updateNum =0, zero_set;
- s32 zero_max;
- struct point di_max;
- struct segment seg,u_seg;
- // 全局电流数据清零
- // memset(g_i0_raw,0,sizeof(g_i0_raw));
- memset(g_i0_seg,0,sizeof(g_i0_seg));
-
- // 零序电流求导,并得到最大差分值
- if(g_i0_arg[sw].scale_is_1A)
- {
- // 零流采样电阻51Ω更换为了300Ω,经过系数转换为码值后,值变大了6倍左右,直接用i_set判断
- zero_set = i_set;
- }
- else
- {
- //没换电阻还是按照原本方式处理
- if (h_sign > 0) //H变换计算成功后,需要判断全段有流值大于4倍定值,防止无流误判
- {
- zero_set = i_set*4;
- }
- else
- {
- zero_set = i_set*2;
- }
- if(zero_set < 18) /**< zero_set判值不能小于18,保证小电流阀值不能过低 */
- zero_set = 18;
- }
- zero_max = _xdl_proc_diff_zero(g_i0,0,len,zero_set,&di_max);
- if(zero_max < 0)
- {
- rt_printf("第%d行, %s无流(zero_max=%d) zero_set=%d.\r\n",__LINE__, g_line_type[0],zero_max,zero_set);
- return -1;
- }
- // 零压触发时,搜索第一个电压突变的区间,精确捕捉过零点
- while(_xdl_seg_search_ds_f(g_u0,u_set,bgn,len-1,&u_seg))
- {
- if(u_seg.dir)
- break;
- bgn = u_seg.end + 1;
- }
- if(pRunSet->bTT_TBLTYPE)
- {
- u_seg.bgn -= 1 ; //电压突变沿作为电流首半波始启点,需再回退一个采样点。
- bgn = u_seg.bgn;
- }
- else
- bgn = u_seg.bgn;
- // rt_printf("v0=%d,p=%d.u_dir=%d,u_bgn=%d,u_end=%d.\r\n",u_seg.max_v,u_seg.max_p,u_seg.dir,bgn,u_seg.end);
- // 方法2: 电流微分首半波判断
- // 搜索几个电流变化最大的区间
- while(_xdl_seg_search_ds_r(g_i0,i_set,bgn,len-1,&seg,&u_seg))
- {
- bgn = seg.end+1;
- // 区间有效,且区间电压有效才更新
- // 零压定值过大会导致暂态零压设定
- // 值过高进而导致索引零压失败最终
- // 误判或者无法启动小电流接地判断
- if(seg.dir && xdl_seg_u0_ok(len,&seg,u_set))
- {
- // rt_printf("v1=%d,p=%d.dir=%d,bgn=%d,end=%d,ubgn=%d,uend=%d,updateNum=%d.\r\n",seg.max_v,seg.max_p,seg.dir,seg.bgn,seg.end,u_seg.bgn,u_seg.end,updateNum);
- _xdl_seg_update(g_i0_seg,&seg,&u_seg,&updateNum);
- }
- }
- // 将搜索出的区域按时间排序
- _xdl_seg_sort(g_i0_seg) ;
- // 寻找电流首半波,条件是最大值最大的区域,是其前面区域最大值的8倍以上
- s = 0;
- if(pRunSet->bTT_GZJD != 1) //选高阻接地方式,不考虑最大区域选择
- {
- for(i=1; i<(XDL_SEG_NUM>>1);i++) //XDL_SEG_NUM ->暂时只使用前5组区域
- {
- if(g_i0_seg[i].max_v > (g_i0_seg[s].max_v <<3))
- {
- s = i;
- }
- }
- }
-
- // 如果首半波条件成立,寻找零序电压方向。
- if(g_i0_seg[s].dir)
- {
- // 扩展首半波范围
- if(g_i0_seg[s].bgn > 0)
- {
- g_i0_seg[s].bgn--;
- }
- // 检查电压幅值,在此区域后,必须有电压大于设定值
- {
- s16 v,v_bgn,v_max;
- // 延长电压检查区间 ,延长为180度+额外增加8个点
- end = g_i0_seg[s].bgn + ADC_REC_SAMPLE/2+8;
- //极端情况下会进这里,例如零流:为长而平衡的小波,造成区段划分过长,长度超越了半个周波(180度)
- if(g_i0_seg[s].end > end)
- {
- end = g_i0_seg[s].end + 16;
- }
- if(end > len)
- {
- end = len;
- }
-
- v_max = 0;
- v_bgn = g_u0[g_i0_seg[s].bgn];
- for(i=g_i0_seg[s].bgn;i<=end;i++)
- {
- v = g_u0[i] - v_bgn;
- if(abs(v) > abs(v_max))
- {
- v_max = v;
- }
- if (i == g_i0_seg[s].end) //区间内搜索,采用区域中的最大值计算
- {
- // 区域电压差值必须大于定值
- if(abs(v_max) > u_set*U_SET_COEF)
- {
- // dir = v;
- // 如果电流区间起点的电压的绝对值减终点的电压的绝对值大于定值,反向
- // if(abs(g_u0[g_i0_seg[s].bgn]) < abs(g_u0[i])) // 此算法跨零点时容易失误
- if(abs(g_u0[g_i0_seg[s].bgn]) < (abs(g_u0[g_i0_seg[s].end])+u_set))
- {
- dir = g_u0[g_i0_seg[s].end]; //使用区域结束点,判趋势
- rt_printf("电压正向v_max:bgn=%d,end=%d,u_set=%d,v_bgn=%d,v_end=%d,dir=%d.\r\n",
- g_i0_seg[s].bgn,g_i0_seg[s].end,u_set,g_u0[g_i0_seg[s].bgn],g_u0[g_i0_seg[s].end],dir);
- }
- else
- {
- dir = -g_u0[g_i0_seg[s].end];
- rt_printf("电压反向v_max:bgn=%d,end=%d,u_set=%d,v_bgn=%d,v_end=%d,dir =%d.\r\n",
- g_i0_seg[s].bgn,g_i0_seg[s].end,u_set,g_u0[g_i0_seg[s].bgn],g_u0[g_i0_seg[s].end],dir);
- }
-
- break;
- }
- }
- else if(i > g_i0_seg[s].end) //延长区间搜索
- {
- // 区域电压差值必须大于定值
- if(abs(v) > u_set*U_SET_COEF)
- {
- dir = v;
- // 如果电流区间起点的电压的绝对值减终点的电压的绝对值大于定值,反向
- // if(abs(g_u0[g_i0_seg[s].bgn]) < abs(g_u0[i])) // 此算法跨零点时容易失误
- if(abs(g_u0[g_i0_seg[s].bgn]) < (abs(g_u0[g_i0_seg[s].end])+u_set))
- {
- dir = v;
- }
- else
- {
- dir = -v;
- rt_printf("电压反向v:bgn=%d,end=%d,u_set=%d,v_bgn=%d,v_end=%d,dir =%d.\r\n",
- g_i0_seg[s].bgn,g_i0_seg[s].end,u_set,g_u0[g_i0_seg[s].bgn],g_u0[g_i0_seg[s].end],dir);
- }
-
- break;
- }
- }
- }
- if(i == end)
- {
- rt_printf("电压欠幅:seg_bgn=%d,seg_end=%d,end=%d,u_set=%d,v_max=%d.\r\n",g_i0_seg[s].bgn,g_i0_seg[s].end,end,u_set,v_max);
- *ps = s;
- ret = -2;
- goto RET;
- }
- else if(i > g_i0_seg[s].end)
- {
- rt_printf("电压查找超范围:bgn=%d,end=%d,uv0=%d,uvd=%d,uv=%d,up=%d,u_set=%d.\r\n",
- g_i0_seg[s].bgn,g_i0_seg[s].end,g_u0[g_i0_seg[s].bgn],g_u0[g_i0_seg[s].end],g_u0[i],i,u_set);
- }
- }
- // 判电压方向
- if(dir)
- {
- ret=_xdl_dir_inv(dir,g_i0_seg[s].dir);
- if(ret == 0 && pRunSet->bTT_HILEBERT) //H 变换
- {
- for(j = (g_i0_seg[s].bgn&0x7f); j < XDL_SAMPLE_LEN ; j+=ADC_REC_SAMPLE )
- {
- hilbert_count++;
- ret = (hilbert_filter(&g_u0_dwt[j], &g_i0_dwt[j], ADC_REC_SAMPLE)>0)? 1:0;
- if(ret)
- {
- rt_printf("hilbert activation,begin at %d,计算:%d 次 \r\n",(g_i0_seg[s].bgn&0x7f),hilbert_count);
- break;
- }
- }
- if(!ret)
- {
- rt_printf("hilbert not find,begin at %d,计算:%d 次 \r\n",(g_i0_seg[s].bgn&0x7f),hilbert_count);
- }
- }
- rt_printf("%s(s=%d,dir=%d,bgn=%d,iv=%d,ip=%d,uv=%d,up=%d,i_set=%d,u_set=%d).\r\n",
- g_line_type[ret],s,dir,g_i0_seg[s].bgn,g_i0[g_i0_seg[s].max_p],g_i0_seg[s].max_p,g_u0[i],i,i_set,u_set);
- *ps = s;
- return ret;
- }
- else
- {
- rt_printf("电压无方向:s=%d,bgn=%d,end=%d,i=%d,u0=%d.\r\n",
- s,g_i0_seg[s].bgn,g_i0_seg[s].end,i,g_u0[i]);
- *ps = s;
- ret = -3;
- goto RET;
- }
- }
- else
- {
- if(h_sign > 0 && pRunSet->bTT_HILEBERT) //H变换,缩小区间再判一次
- {
- for(j = (ADC_REC_SAMPLE<<0) ; j < XDL_SAMPLE_LEN ; j+=ADC_REC_SAMPLE )
- {
- hilbert_count++;
- ret = (hilbert_filter(&g_u0_dwt[j], &g_i0_dwt[j], ADC_REC_SAMPLE)>0)? 1:0;
- if(ret)
- {
- rt_printf("%s hilbert activation,计算:%d 次 \r\n",g_line_type[ret],hilbert_count);
- return ret;
- }
- }
- if(!ret)
- {
- rt_printf("%s hilbert not find,计算:%d 次 \r\n",g_line_type[ret],hilbert_count);
- }
- }
- rt_printf("首半波未找到:s=%d,dir=%d,max=%d.\r\n",s,g_i0_seg[s].dir,g_i0_seg[s].max_v);
- *ps = s;
- ret = -4;
- }
- RET:
- return ret;
- }
- #define COEF 1.0
- int xdl_proc_adc(u32 sw,u32 dt,struct timespec *ts)
- {
- int i,ret,seg;
- int ch0,cha,chb,chc;
- int i0,u0;
- char Hilbert_Sign = 0; //H变换计算成功标志
- float H_ret = 0; //H变换计算返回值
- // 三项电流
- int ui_begin;
- DWORD Ia,Ib,Ic;
- wave_object obj=NULL;
- wt_object wt=NULL;
- char *method = "modwt";
- if(pRunSet->bTT_FILTER == 2)
- {
- // char *name = "haar";
- obj = wave_init(pRunSet->bTT_WAVE);// Initialize the wavelet
- wt = wt_init(obj, method, XDL_SAMPLE_LEN, pRunSet->bTT_WAVE_ORDER);// Initialize the wavelet transform object
- }
- // 得到零序电压采样值
- if(pRunSet->tSwSet[sw].bTT_Power_v2 == 0)
- {
- ch0 = (short)g_sw_pub.ac_cfg_index[PUB_AC_U01];
- cha = (short)g_sw_pub.ac_cfg_index[PUB_AC_UA1];
- chb = (short)g_sw_pub.ac_cfg_index[PUB_AC_UB1];
- chc = (short)g_sw_pub.ac_cfg_index[PUB_AC_UC1];
- }
- else
- {
- ch0 = (short)g_sw_pub.ac_cfg_index[PUB_AC_U02];
- cha = (short)g_sw_pub.ac_cfg_index[PUB_AC_UA2];
- chb = (short)g_sw_pub.ac_cfg_index[PUB_AC_UB2];
- chc = (short)g_sw_pub.ac_cfg_index[PUB_AC_UC2];
- }
-
- if(ch0 != INDEX_INVALLID)
- {
- ch0=equ_get_ac_channel(g_equ_config_ac[ch0].slot, g_equ_config_ac[ch0].index);
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- g_u0_raw[i] = g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][ch0];
- g_u0_dwt[i] = (float)g_u0_raw[i];
- }
- if(pRunSet->bTT_GZJD != 1) //选高阻接地方式,则小波计算不考虑:三点滤波算法
- {
- memset(g_u0_dwt,0,sizeof(g_u0_dwt));
- xdl_f_smooth3(g_u0_raw, g_u0_dwt, XDL_SAMPLE_LEN);
- }
- switch (pRunSet->bTT_FILTER)
- {
- case 0:
- xdl_smooth3(g_u0_raw, g_u0, XDL_SAMPLE_LEN);
- break;
- case 1:
- DWT_Matrix_Transform(g_u0_dwt, g_u0, XDL_SAMPLE_LEN);
- break;
- case 2:
- modwt(wt, g_u0_dwt);// Perform MODWT
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- g_u0[i] = (s16)(wt->output[i]*COEF);
- }
- break;
- default:
- memcpy(g_u0, g_u0_raw, XDL_SAMPLE_LEN);
- break;
- }
- }
- else if( (cha != INDEX_INVALLID)
- && (chb != INDEX_INVALLID)
- && (chc != INDEX_INVALLID))
- {
- cha=equ_get_ac_channel(g_equ_config_ac[cha].slot, g_equ_config_ac[cha].index);
- chb=equ_get_ac_channel(g_equ_config_ac[chb].slot, g_equ_config_ac[chb].index);
- chc=equ_get_ac_channel(g_equ_config_ac[chc].slot, g_equ_config_ac[chc].index);
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- g_u0[i] = g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][cha];
- g_u0[i] += g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][chb];
- g_u0[i] += g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][chc];
- }
-
- }
- else
- {
- ret = -11;
- goto RET;
- }
- if(sw < g_sw_num)
- {
- TSETSW *pSet = &pRunSet->tSwSet[sw];
- TSDHZ_T *pSW=&g_tRelay[sw].tSDHZ;
- int zero;
- if((BH_ALL_EN(sw) && (pSet->bTT_xdlgj || pSet->bTT_xdltz)) == 0)
- {
- ret = -12;
- goto RET;
- }
- zero = 0;
- if(!pRunSet->bTT_TBLTYPE) //使用电流突变
- {
- if(g_xdl[sw].zero_cnt)
- {
- zero = g_xdl[sw].zero_sum/g_xdl[sw].zero_cnt;
- }
- }
- // 得到零序电流采样值
- ch0 = (short)g_sw[sw].ac_cfg_index[SW_AC_I0];
- if(ch0 != INDEX_INVALLID)
- {
- ch0=equ_get_ac_channel(g_equ_config_ac[ch0].slot, g_equ_config_ac[ch0].index);
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- g_i0_raw[i] = g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][ch0] - zero;
- g_i0_dwt[i] = (float)g_i0_raw[i];
- }
- if(pRunSet->bTT_GZJD != 1) //选高阻接地方式,则小波计算不考虑:三点滤波算法
- {
- memset(g_i0_dwt,0,sizeof(g_i0_dwt));
- xdl_f_smooth3(g_i0_raw, g_i0_dwt, XDL_SAMPLE_LEN);
- }
- switch (pRunSet->bTT_FILTER)
- {
- case 0:
- xdl_smooth3(g_i0_raw, g_i0, XDL_SAMPLE_LEN);
- break;
- case 1:
- DWT_Matrix_Transform(g_i0_dwt, g_i0, XDL_SAMPLE_LEN);
- break;
- case 2:
- modwt(wt, g_i0_dwt);// Perform MODWT
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- g_i0[i] = (s16)(wt->output[i]*COEF);
- }
- break;
- default:
- memcpy(g_i0, g_i0_raw, XDL_SAMPLE_LEN);
- break;
- }
- }
- else if( (cha != INDEX_INVALLID)
- && (chb != INDEX_INVALLID)
- && (chc != INDEX_INVALLID))
- {
- cha=equ_get_ac_channel(g_equ_config_ac[cha].slot, g_equ_config_ac[cha].index);
- chb=equ_get_ac_channel(g_equ_config_ac[chb].slot, g_equ_config_ac[chb].index);
- chc=equ_get_ac_channel(g_equ_config_ac[chc].slot, g_equ_config_ac[chc].index);
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- g_i0[i] = g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][cha];
- g_i0[i] += g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][chb];
- g_i0[i] += g_adc_dots_rec[((dt+i)&ADC_REC_DOTS_MASK)][chc];
- }
- }
- else
- {
- ret = -13;
- goto RET;
- }
- // rt_free(p_uo);
- // rt_free(p_io);
- wave_free(obj);
- wt_free(wt);
- // 检查处理是否及时
- // 启动(1.28-0.3-0.02×6)秒内必须完成小电流数据copy,否则录波缓冲中的数据将被覆盖。
- {
- u32 n;
- n = (u32)(g_adc_dots_count<<3) - dt;
- if(n > ADC_REC_DOTS_CHANNEL)
- {
- rt_printf("处理超时:n=%d,now=%d,old=%d.\r\n",n,(g_adc_dots_count<<3),dt);
- ret = -14;
- goto RET;
- }
- }
-
- // 零序电流处理
- seg = -1;
- if(pRunSet->bTT_TBLTYPE) //选零压突变,使用H变换计算以增加准确率
- {
- for(i = 0 ; i < XDL_SAMPLE_LEN ; i+=ADC_REC_SAMPLE ) //(ADC_REC_SAMPLE<<1)
- {
- H_ret = hilbert_filter(&g_u0_dwt[i], &g_i0_dwt[i], ADC_REC_SAMPLE);
- if(H_ret > 0)
- {
- Hilbert_Sign++;
- // break;
- }
- // rt_printf("i= %d,status =%d,hilbert_filter ret = %f.\r\n",i,Hilbert_Sign,H_ret);
- }
- ret = xdl_proc_i0(sw,XDL_SAMPLE_LEN,pSet->dI_xdl_zt,pRunSet->dU_xdl_u0_zt[pRunSet->tSwSet[sw].bTT_Power_v2],&seg,Hilbert_Sign);
- }
- else // 零序电流处理
- ret = xdl_proc_i0(sw,XDL_SAMPLE_LEN,pSet->dI_xdl_zt,pRunSet->dU_xdl_u0_zt[pRunSet->tSwSet[sw].bTT_Power_v2],&seg,0);
- //如果电流反向,结果反向。
- if((pRunSet->tSwSet[sw].bTT_Current_Inv || pRunSet->tSwSet[sw].bTT_lxpolar || g_cur_direction_adaptaion) && (ret >= 0))
- {
- ret = !ret;
- }
-
- // 计算I0、U0
- i0 = 0;
- u0 = 0;
- if(seg >= 0)
- {
- for(i=g_i0_seg[seg].bgn; i<g_i0_seg[seg].end; i++)
- {
- if(abs(g_i0[i]) > abs(i0))
- {
- i0 = g_i0[i];
- }
- if(abs(g_u0[i]) > abs(u0))
- {
- u0 = g_u0[i];
- }
- }
- i0 = i0*(g_ui[UI_SW_INDEX(sw,SW_AC_I0)].e_factor0*1.4142)*Q16_BASE;
- u0 = u0*(g_ui[PUB_AC_U01].e_factor0*1.4142)*Q16_BASE;
- }
- // 计算三项电流
- ui_begin = UI_SW_INDEX_BEGIN(sw);
- Ia = _Mul_Div_U(sqrt_32fix(g_ui[ui_begin + SW_AC_IA].m2[0]), 256, g_ui[ui_begin + SW_AC_IA].m2_factor_k);
- Ib = _Mul_Div_U(sqrt_32fix(g_ui[ui_begin + SW_AC_IB].m2[0]), 256, g_ui[ui_begin + SW_AC_IB].m2_factor_k);
- Ic = _Mul_Div_U(sqrt_32fix(g_ui[ui_begin + SW_AC_IC].m2[0]), 256, g_ui[ui_begin + SW_AC_IC].m2_factor_k);
- // 启动事件
- soe_record_ev(EV_LX_XDL_QD+sw*EV_SW_NUM, 1, i0,u0,ret);
- if(ret>0) //小电流接地:启动[界内动作]
- {
- g_xdl[sw].dz = 1;
- // 提前打开启动继电器,以节省硬件耗用时间
- // 并等待超时释放
- sw_do(sw,SW_DO_BHT,SW_DO_TYPE_SELECT_ON);
-
- if(pSet->dT_xdl_T) //暂态时间不为0时,才启动间歇性接地逻辑
- {
- // jxjd_set_JDGZ(sw); //间歇接地故障(用于计次) // TODO
- }
- if (!pSet->dT_xdl_GT) // 告警
- {
- // 告警
- if(pSet->bTT_xdlgj)
- {
- soe_record_ev(EV_LX_XDL_GJ+sw*EV_SW_NUM, 1, i0,u0,0 );
- soe_record_ev(EV_ABC_JDTZ+sw*EV_SW_NUM, 1, i0,u0,0 );
- pSW->uSdhz_S.bFlag.bJD = true;
- }
- }
- else
- {
- pSW->uSdhz_S.bFlag.bJD = true;
- g_xdl[sw].gj_us0 = g_xdl[sw].qd_us0;
- g_xdl[sw].dz_i0[0] = i0;
- g_xdl[sw].dz_u0[0] = u0;
- g_xdl[sw].dz_Ia[0] = Ia;
- g_xdl[sw].dz_Ib[0] = Ib;
- g_xdl[sw].dz_Ic[0] = Ic;
- }
-
- if (!pSet->dT_xdl_T) // 跳闸
- {
- // 跳闸
- if(pSet->bTT_xdltz)
- {
- sw_do(sw,SW_DO_BHT,SW_DO_TYPE_ON);
- soe_record_ev(EV_LX_XDL_TZ+sw*EV_SW_NUM, 1, i0,u0,0 );
- soe_record_ev(EV_ABC_JDTZ+sw*EV_SW_NUM, 1, i0,u0,0 );
- if ((Ia>Ib)&&(Ia>Ic))
- {
- soe_record_ev(EV_A_JDTZ+sw*EV_SW_NUM, 1, Ia,0,0 );
- }
- else if ((Ib>Ia)&&(Ib>Ic))
- {
- soe_record_ev(EV_B_JDTZ+sw*EV_SW_NUM, 1, Ib,0,0 );
- }
- else if ((Ic>Ia)&&(Ic>Ib))
- {
- soe_record_ev(EV_C_JDTZ+sw*EV_SW_NUM, 1, Ic,0,0 );
- }
- pSW->uSdhz_S.bFlag.bJD = true;
- // g_tRelay[sw].tXDLCHZ.sta.bFlag.bXDLDZ = true; //TODO EWen
-
- //jxjd_sw_reset(sw);
- }
- }
- else
- {
- pSW->uSdhz_S.bFlag.bJD = true;
- g_xdl[sw].dz_us0 = g_xdl[sw].qd_us0;
- g_xdl[sw].dz_i0[1] = i0;
- g_xdl[sw].dz_u0[1] = u0;
- g_xdl[sw].dz_Ia[1] = Ia;
- g_xdl[sw].dz_Ib[1] = Ib;
- g_xdl[sw].dz_Ic[1] = Ic;
- }
- }
- rcd_start_xdl(NULL,sw,g_xdl_rcd_a,XDL_RCD_A_NUM,XDL_SAMPLE_LEN,ts);
- g_xdl[sw].st = XDL_ST_END;
- ret = 0;
- }
- else
- {
- ret = -15;
- }
- RET:
- if(ret != 0)
- {
- soe_record_ev(EV_LX_XDL_QD+sw*EV_SW_NUM, 1, 0,0,ret);
- }
- rt_printf_time("小电流接地完成(sw=%d,ret=%d,inv=%d,dir=%d).\r\n",sw,ret,pRunSet->tSwSet[sw].bTT_Current_Inv, g_cur_direction_adaptaion);
- return ret;
- }
- // 零流突变判断定值
- #define REV_F_CT_DEFAULT 20 // CT默认,额定5A
- #define REV_F_CT_1A 10 // CT_1V/1A, 额定1A
- // 小电流突变量启动,放在156us中断中
- void xdl_tbl_qd(int mod)
- {
- s16 v,v0,v1,zero;
- s16 iv,iv0,iv1,ref_i,ref_v=0; //零压触发,电流参考辅助触发
- u32 sw,ui;
- u32 xdl_zt_v;
- int ret;
- TSETSW *pSet = NULL;
- // u32 index = g_adc_dots_index_rec - 1;
- u32 index = ((g_adc_dots_count-1)<<3) + mod;
-
- for (sw=0; sw<g_sw_num; sw++)
- {
- // 已启动,退出
- if(g_xdl[sw].st)
- {
- continue;
- }
- pSet = &pRunSet->tSwSet[sw];
-
- //突变量启动前提条件:保护总投入,小电流接地告警或出口投入或录波投入。
- if(BH_ALL_EN(sw) == 0 || (pSet->bTT_xdlgj || pSet->bTT_xdltz)== 0)
- {
- continue;
- }
-
- // 如果索引通道不存在,不需计算
- if(pRunSet->bTT_TBLTYPE) //高阻接地方式,零序电流较小,可以采用电压突变启动
- {
- ui = PUB_AC_U01;
- xdl_zt_v = pRunSet->dU_xdl_u0_zt[0];
- }
- else
- {
- ui = UI_SW_INDEX(sw,SW_AC_I0);
- xdl_zt_v = pRunSet->tSwSet[sw].dI_xdl_zt;
- }
- if(g_ui[ui].chn_index == CFG_ADC_CHANNEL_ZERO)
- {
- continue;
- }
- // 检查硬件通道是否正常
- if(equ_ac_channel_is_ok(g_ui[ui].chn_index) == 0)
- {
- continue;
- }
- // 得到当前值和一个周期前的值
- v0 = g_adc_dots_rec[(index - ADC_REC_SAMPLE*2) & ADC_REC_DOTS_MASK][g_ui[ui].chn_index];
- v1 = g_adc_dots_rec[(index - ADC_REC_SAMPLE) & ADC_REC_DOTS_MASK][g_ui[ui].chn_index];
- v = g_adc_dots_rec[(index) & ADC_REC_DOTS_MASK][g_ui[ui].chn_index];
- //电流零偏处理,由于在DTU3.0电磁式的设计中,AD一个码值代表6mA,10个码值代表60mA,所以必须修正
- // 电流零偏计算
- g_xdl[sw].zero_sum += v1;
- if(g_xdl[sw].zero_cnt < ADC_REC_SAMPLE)
- {
- g_xdl[sw].zero_cnt++;
- return;
- }
- else
- {
- g_xdl[sw].zero_sum -= v0;
- }
- // 根据zero,修正v值,
- zero = g_xdl[sw].zero_sum/g_xdl[sw].zero_cnt;
- v -= zero;
- // 如果大于定值,启动录波 间隔电流大于无流值
- if((abs(v) > xdl_zt_v))
- {
- // if(sw > 0) /**< sw = 0 默认间隔不判无流值,其它间隔要判 */
- {
- // if(g_sw[sw].m2_max < pRunSet->dIWL_SQR[sw])
- // continue;
- if(pRunSet->bTT_TBLTYPE){ /**< 改为所有间隔都要判零流 */
- ref_i = UI_SW_INDEX(sw,SW_AC_I0);
- iv0 = g_adc_dots_rec[(index - ADC_REC_SAMPLE*2) & ADC_REC_DOTS_MASK][g_ui[ref_i].chn_index];
- iv1 = g_adc_dots_rec[(index - ADC_REC_SAMPLE) & ADC_REC_DOTS_MASK][g_ui[ref_i].chn_index];
- iv = g_adc_dots_rec[(index) & ADC_REC_DOTS_MASK][g_ui[ref_i].chn_index];
- ref_v = abs(iv0 - iv1*2 + iv);
- if(ref_v < g_i0_arg[sw].ref_v_set)
- continue;
- }
- }
-
- // 置启动标志,不能放在录波启动成功的条件里,避免启动失败后频繁打印
- g_xdl[sw].st = XDL_ST_QT;
- g_xdl[sw].qd_us0 = ustimer_get_origin();
- ret = rcd_start(sw, RECORD_TYPE_XDLJD, xdl_get_LLTB_waves(sw));
- if(ret == 0)
- {
- rt_printf("%s启动:sw=%d,v=%d,ref_v=%d,i_m2=%d,nor_i=%d,i_set=%d,zero=%d.\r\n",g_tbl_type[pRunSet->bTT_TBLTYPE],sw,v,ref_v,g_sw[sw].m2_max,pRunSet->dIWL_SQR[sw],xdl_zt_v,zero);
- }
- else
- {
- rt_printf("录波启动失败(ret=%d,sw=%d.\r\n)",ret,sw);
- }
- // if(pRunSet->bTT_TBLTYPE){ //零压触发每次只判一间隔,下次进来再判下一间隔单元
- // return;
- // }
- }
- }
- }
- /******************************************************************************
- 函数名称: max3
- 函数版本: 01.01
- 创建作者: 赵海洋
- 创建日期: 2022-03-22
- 函数说明: 三值比较函数
- 参数说明: 无
- 返回值: 无.
- 修改记录:
- */
- #if 0
- static int max3 (int a, int b, int c)
- {
- if (a>=b)
- if (a>=c)
- return a;
- else
- return c;
- else
- if (b>=c)
- return b;
- else
- return c;
- }
- #endif
- #define XDL_FG_INTERVAL (1) //(5) //复归间隔 unit: s
- //小电流跳闸、复归
- static void _xdl_protect_TZ_FG(int sw, DWORD dStep)
- {
- int soeno;
- bool bQD;
- static uint8_t gj_flag[SWITCH_NUM_MAX]={0};
- static uint8_t dz_flag[SWITCH_NUM_MAX]={0};
- // 电流闭锁复归
- bQD = OverRelay(g_ui[UI_SW_INDEX(sw,SW_AC_I0)].m2[0], pRunSet->tSwSet[sw].dI_xdl,pRunSet->tSwSet[sw].dI_xdl_fh, g_tXDLTime_I[sw].boolTrip);
- RunTR(&g_tXDLTime_I[sw], bQD, dStep);
- // 小电流告警延时动作
- if (pRunSet->tSwSet[sw].dT_xdl_GT)
- {
- if((g_xdl[sw].gj_us0) && (ustimer_get_duration(g_xdl[sw].gj_us0) >= (pRunSet->tSwSet[sw].dT_xdl_GT*USTIMER_SEC)))
- {
- if (gj_flag[sw]==0)
- {
- g_xdl[sw].gj_us0 = 0;
- #ifdef RECORD_SW_U0TB
- if(g_tXDLTime_U0TB[sw].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #else
- if(g_tXDLTime_U[pRunSet->tSwSet[sw].bTT_Power_v2].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #endif
- {
- // 告警
- if(pRunSet->tSwSet[sw].bTT_xdlgj)
- {
- // g_xdl[sw].gj_fh_us0 = ustimer_get_origin();
- soe_record_ev(EV_LX_XDL_GJ+sw*EV_SW_NUM, 1, g_xdl[sw].dz_i0[0],g_xdl[sw].dz_u0[0],0 );
- if(!soe_check(EV_ABC_JDTZ +sw*EV_SW_NUM))
- {
- soe_record_ev(EV_ABC_JDTZ +sw*EV_SW_NUM, 1, g_xdl[sw].dz_i0[0],g_xdl[sw].dz_u0[0],0 );
- }
- }
- gj_flag[sw] = 1;
- }
- }
- }
- else
- {
- gj_flag[sw] = 0;
- }
- }
- // 小电流跳闸延时动作
- if (pRunSet->tSwSet[sw].dT_xdl_T)
- {
- if((g_xdl[sw].dz_us0) && (ustimer_get_duration(g_xdl[sw].dz_us0) >= (pRunSet->tSwSet[sw].dT_xdl_T*USTIMER_SEC)))
- {
- if (dz_flag[sw]==0)
- {
- g_xdl[sw].dz_us0 = 0;
- #ifdef RECORD_SW_U0TB
- if(g_tXDLTime_U0TB[sw].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #else
- if(g_tXDLTime_U[pRunSet->tSwSet[sw].bTT_Power_v2].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #endif
- {
- // 跳闸
- if(pRunSet->tSwSet[sw].bTT_xdltz)
- {
- sw_do(sw,SW_DO_BHT,SW_DO_TYPE_SELECT_ON);
- sw_do(sw,SW_DO_BHT,SW_DO_TYPE_ON);
- // g_xdl[sw].dz_fh_us0 = ustimer_get_origin();
- soe_record_ev(EV_LX_XDL_TZ+sw*EV_SW_NUM, 1, g_xdl[sw].dz_i0[1],g_xdl[sw].dz_u0[1],0 );
- if(!soe_check(EV_ABC_JDTZ +sw*EV_SW_NUM))
- {
- soe_record_ev(EV_ABC_JDTZ +sw*EV_SW_NUM, 1, g_xdl[sw].dz_i0[1],g_xdl[sw].dz_u0[1],0 );
- }
- if ((g_xdl[sw].dz_Ia[1]>g_xdl[sw].dz_Ib[1])&&(g_xdl[sw].dz_Ia[1]>g_xdl[sw].dz_Ic[1]))
- {
- soe_record_ev(EV_A_JDTZ+sw*EV_SW_NUM, 1, g_xdl[sw].dz_Ia[1],0,0 );
- }
- else if ((g_xdl[sw].dz_Ib[1]>g_xdl[sw].dz_Ia[1])&&(g_xdl[sw].dz_Ib[1]>g_xdl[sw].dz_Ic[1]))
- {
- soe_record_ev(EV_B_JDTZ+sw*EV_SW_NUM, 1, g_xdl[sw].dz_Ib[1],0,0 );
- }
- else if ((g_xdl[sw].dz_Ic[1]>g_xdl[sw].dz_Ia[1])&&(g_xdl[sw].dz_Ic[1]>g_xdl[sw].dz_Ib[1]))
- {
- soe_record_ev(EV_C_JDTZ+sw*EV_SW_NUM, 1, g_xdl[sw].dz_Ic[1],0,0 );
- }
- // g_tRelay[sw].tXDLCHZ.sta.bFlag.bXDLDZ = true; //TODO
- }
- dz_flag[sw] = 1;
- }
- }
- }
- else
- {
- dz_flag[sw] = 0;
- }
- }
- // 小电流启动重合闸
- #if 0 // TODO
- if((g_xdl[sw].st) && g_tRelay[sw].tXDLCHZ.sta.bFlag.bXDLDZ)
- {
- #ifdef RECORD_SW_U0TB
- if((!g_tXDLTime_U0TB[sw].boolTrip) && (!g_tXDLTime_I[sw].boolTrip))
- #else
- if((!g_tXDLTime_U[pRunSet->tSwSet[sw].bTT_Power_v2].boolTrip) && (!g_tXDLTime_I[sw].boolTrip))
- #endif
- {
- g_tRelay[sw].tXDLCHZ.sta.bFlag.bXDLDZ = false;
- g_tRelay[sw].tXDLCHZ.sta.bFlag.bXDLCH = true;
- }
- }
- #endif
- // 此标志置1时可以确定产生了界内故障
- if(g_xdl[sw].dz)
- {
- if(g_xdl[sw].dz_fh_us0 == 0)
- {
- g_xdl[sw].dz_fh_us0 = ustimer_get_origin();
- }
- else
- {
- #ifdef RECORD_SW_U0TB
- if(g_tXDLTime_U0TB[sw].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #else
- if(g_tXDLTime_U[pRunSet->tSwSet[sw].bTT_Power_v2].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #endif
- {
- // 故障还没消失,更新计时
- g_xdl[sw].dz_fh_us0 = ustimer_get_origin();
- }
- }
- }
- // 小电流信号延迟复归
- if((g_xdl[sw].dz_fh_us0) && (ustimer_get_duration(g_xdl[sw].dz_fh_us0) >= (uint32_t)(tRunPara.fT_LBXH_RST*USTIMER_SEC)))
- {
- g_xdl[sw].dz_fh_us0 = 0;
- // 告警
- soeno = EV_LX_XDL_GJ+sw*EV_SW_NUM;
- if(soe_check(soeno))
- {
- soe_record_ev(soeno, 0, 0,0,0 );
- }
- // 跳闸
- soeno = EV_LX_XDL_TZ+sw*EV_SW_NUM;
- if(soe_check(soeno))
- {
- soe_record_ev(soeno, 0, 0,0,0 );
- }
- // 接地故障总
- soeno = EV_ABC_JDTZ+sw*EV_SW_NUM;
- if(soe_check(soeno))
- {
- soe_record_ev(soeno, 0, 0,0,0 );
- }
- // A相
- soeno = EV_A_JDTZ+sw*EV_SW_NUM;
- if(soe_check(soeno))
- {
- soe_record_ev(soeno, 0, 0,0,0 );
- }
- // B相
- soeno = EV_B_JDTZ+sw*EV_SW_NUM;
- if(soe_check(soeno))
- {
- soe_record_ev(soeno, 0, 0,0,0 );
- }
- // C相
- soeno = EV_C_JDTZ+sw*EV_SW_NUM;
- if(soe_check(soeno))
- {
- soe_record_ev(soeno, 0, 0,0,0 );
- }
- //间歇接地故障消失
- // jxjd_clr_JDGZ(sw);//TODO EWen
- }
- // 两次判断最小间隔为5S.
- if((g_xdl[sw].st) && (ustimer_get_duration(g_xdl[sw].qd_us0) > (XDL_FG_INTERVAL*USTIMER_SEC)))
- {
- // 如果接地启动,必须等小电流零压零流消失后才能复归
- #ifdef RECORD_SW_U0TB
- if(g_tXDLTime_U0TB[sw].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #else
- if(g_tXDLTime_U[pRunSet->tSwSet[sw].bTT_Power_v2].boolTrip || g_tXDLTime_I[sw].boolTrip)
- #endif
- {
- return;
- }
- rt_printf_time("小电流接地复归(sw=%d,st=%d)。\r\n",sw,g_xdl[sw].st);
- g_xdl[sw].st = XDL_ST_IDLE;
- g_xdl[sw].dz = 0;
- g_xdl[sw].zero_sum = 0;
- g_xdl[sw].zero_cnt = 0;
- // g_tRelay[sw].tXDLCHZ.sta.bFlag.bXDLCH = false;
- // 启动
- soeno = EV_LX_XDL_QD+sw*EV_SW_NUM;
- if(soe_check(soeno))
- {
- soe_record_ev(soeno, 0, 0,0,0 );
- }
- //间歇接地故障消失
- // jxjd_clr_JDGZ(sw); //TODO EWen
- }
- }
- #ifndef RECORD_SW_U0TB //保留原有逻辑
- void xdl_protect(DWORD dStep)
- {
- int sw,soeno;
- bool bQD;
- // 小电流零序电压过压逻辑1
- bQD = OverRelay(g_ui[PUB_AC_U01].m2[0], pRunSet->dU_xdl_u0[0], pRunSet->dU_xdl_u0_fh[0], g_tXDLTime_U[0].boolTrip);
- RunTR(&g_tXDLTime_U[0], bQD, dStep);
- // 记录事件
- soeno = EV_XDL_U0GJ1;
- if(g_tXDLTime_U[0].boolTrip && pRunSet->dU_xdl_u0[0])
- {
-
- if(soe_check(soeno)==false)
- {
- DWORD u0;
- u0 = _Mul_Div_U(sqrt_32fix(g_ui[PUB_AC_U01].m2[0]), 256, g_ui[PUB_AC_U01].m2_factor_k);
- soe_record_ev(soeno, 1, u0,0,0);
- // 小电流零压启动录波,但不进行接地判断
- for(sw=0;sw<g_sw_num;sw++)
-
- {
- if(pRunSet->tSwSet[sw].bTT_Power_v2 == 0)
- {
- rcd_start(sw,RECORD_TYPE_LXDY,RECORD_LEN_TZQD);
- }
- }
- }
- }
- else
- {
-
- if(soe_check(soeno)==true)
- {
- soe_record_ev( soeno, 0, 0,0,0 );
- }
- }
- // 小电流零序电压过压逻辑2
- bQD = OverRelay(g_ui[PUB_AC_U02].m2[0], pRunSet->dU_xdl_u0[1], pRunSet->dU_xdl_u0_fh[1], g_tXDLTime_U[1].boolTrip);
- RunTR(&g_tXDLTime_U[1], bQD, dStep);
- // 记录事件
- soeno = EV_XDL_U0GJ2;
- if(g_tXDLTime_U[1].boolTrip && pRunSet->dU_xdl_u0[1])
- {
-
- if(soe_check(soeno)==false)
- {
- DWORD u0;
- u0 = _Mul_Div_U(sqrt_32fix(g_ui[PUB_AC_U02].m2[0]), 256, g_ui[PUB_AC_U02].m2_factor_k);
- soe_record_ev(soeno, 1, u0,0,0);
- // 小电流零压启动录波,但不进行接地判断
- for(sw=0;sw<g_sw_num;sw++)
-
- {
- if(pRunSet->tSwSet[sw].bTT_Power_v2)
- {
- rcd_start(sw,RECORD_TYPE_LXDY,RECORD_LEN_TZQD);
- }
- }
- }
- }
- else
- {
-
- if(soe_check(soeno)==true)
- {
- soe_record_ev( soeno, 0, 0,0,0 );
- }
- }
- // 小电流启动延时复归
- for(sw=0;sw<g_sw_num;sw++)
- {
- _xdl_protect_TZ_FG(sw, dStep);
- }
- }
- #endif
- #ifdef RECORD_SW_U0TB //专业检测用
- void xdl_protect_sw(int sw, DWORD dStep)
- {
- /* //零压突变录波单独做功能,不再用此函数
- int soeno;
- bool bQD;
- TSETSW *pSet = &pRunSet->tSwSet[sw];
- // 小电流零序电压过压
- bQD = OverRelay(g_ui[PUB_AC_U01].m2[0], pSet->dU_xdl_u0TB, pSet->dU_xdl_u0TB_fh, g_tXDLTime_U0TB[sw].boolTrip);
- RunTR(&g_tXDLTime_U0TB[sw], bQD, dStep);
- // 记录事件
- soeno = EV_XDL_U0TB + sw*EV_SW_NUM;
- if(g_tXDLTime_U0TB[sw].boolTrip && pSet->dU_xdl_u0TB)
- {
- if(soe_check(soeno)==false)
- {
- DWORD u0;
- u0 = _Mul_Div_U(sqrt_32fix(g_ui[PUB_AC_U01].m2[0]), 256, g_ui[PUB_AC_U01].m2_factor_k);
- soe_record_ev(soeno, 1, u0,0,0);
- // 小电流零压启动录波,但不进行接地判断
- rcd_start(sw, RECORD_TYPE_LXDY, RECORD_LEN_TZQD);
- }
- }
- else
- {
- if(soe_check(soeno)==true)
- {
- soe_record_ev( soeno, 0, 0,0,0 );
- }
- }
- */
- _xdl_protect_TZ_FG(sw, dStep);
- }
- #endif
- // 查询小电流接地是否动作过
- int xdl_is_dz(int sw)
- {
- if(g_xdl[sw].dz == 0)
- {
- return 0;
- }
- return 1;
- }
- static u32 xdl_get_LLTB_waves(int sw)
- {
- #if(EN_REC_MORE_WAVES==1)
- float set_xdl_T;
- u32 waves;
- set_xdl_T = pRunSet->tSwSet[sw].dT_xdl_T;
- waves = (u32)(set_xdl_T *1000 /20); // 周波数= X毫秒/20ms
- if(waves > XDL_RECORD_WAVES) {
- waves = XDL_RECORD_WAVES; //最大5秒
- }
- waves += RECORD_LEN_TZQD;
- return waves;
- #else
- return RECORD_LEN_TZQD;
- #endif
- }
- int xdl_proc_file(char *szname,int *ok_num,int * err_num,int *skip_num,int *question_num)
- {
- static char cfg_file[128];
- static char dat_file[128];
- static int ui[32];
- int fd;
- struct stat s;
- char *pdata,*name;
- int ret,seg;
- int A,D,N;
- int i,j,k;
- int d_bytes; //数字开关数占用的字节数
- int flag = 0;
- sprintf(cfg_file, "%s.cfg", szname);
- sprintf(dat_file, "%s.dat", szname);
- //获取文件属性
- if(sys_newstat(cfg_file, &s))
- {
- rt_printf("%s:sys_newstat error\n", __func__);
- return -1;
- }
- pdata = rt_malloc(s.st_size+1);
- if(!pdata)
- {
- return -1;
- }
- pdata[s.st_size] = 0;
-
- fd = sys_open(cfg_file, O_RDONLY, 0);
- if(fd < 0)
- {
- rt_printf("%s:sys_open(%s) error\r\n", __func__, cfg_file);
- rt_free(pdata);
- return -1;
- }
- ret = sys_read(fd, pdata, s.st_size);
- if(ret != s.st_size)
- {
- rt_printf("%s:sys_read(%d) error\r\n", __func__, ret);
- rt_free(pdata);
- return -1;
- }
- sys_close(fd);
-
- ret = rcd_get_A_D_N(pdata, &A, &D, &N, ui);
- if(N > XDL_SAMPLE_LEN)
- {
- N = XDL_SAMPLE_LEN;
- }
- if(ret!=0)
- {
-
- return -1;
- }
- rt_free(pdata);
- //获取文件属性
- if(sys_newstat(dat_file, &s))
- {
- rt_printf("%s:sys_newstat error\n",__func__);
- return -1;
- }
- pdata = rt_malloc(s.st_size);
-
- if(!pdata)
- {
- return -1;
- }
- fd = sys_open(dat_file, O_RDONLY, 0);
- if(fd < 0)
- {
- rt_printf("%s:sys_open(%s) error\r\n", __func__, dat_file);
- rt_free(pdata);
- return -1;
- }
- ret = sys_read(fd, pdata, s.st_size);
- if(ret != s.st_size)
- {
- rt_printf("%s:sys_read(%d) error\r\n", __func__, ret);
- rt_free(pdata);
- return -1;
- }
- sys_close(fd);
- //查找零序电压
- for(k=0;k<A;k++)
- {
- if(ui[k]==0)
- {
- flag = 1;
- break;
-
- }
- }
- if(!flag)
- {
- rt_printf("没有找到U0\r\n");
- rt_free(pdata);
- return -1;
- }
-
- d_bytes = ((D + 15)/16 ) * 2;
-
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- if(i < N)
- {
- int r = i*(8+2*A+d_bytes)+8+2*k;
-
- g_u0_raw[i] = (s16)(u8)pdata[r];
- g_u0_raw[i] |= (s16)(u8)pdata[r+1] << 8;
- }
- else
- {
- g_u0_raw[i] = 0;
- }
- }
- // 数字信号不需要滤波
- //xdl_smooth3(g_u0_raw, g_u0, XDL_SAMPLE_LEN);
- // memcpy(g_u0,g_u0_raw,sizeof(g_u0));
- DWT_Matrix_Transform(g_u0_dwt, g_u0, XDL_SAMPLE_LEN);
- // 处理零序电压
- // ret = xdl_proc_u0(N);
- // if(ret < 0)
- // {
- // *err_num = A-1;
- // return ret;
- // }
- name = strrchr(szname,'/');
- name++;
- for(i=0;i <A; i++)
- {
- // 得到零序电流采样值
- for(j=0; j<XDL_SAMPLE_LEN;j++)
- {
- if(j < N)
- {
- if(ui[i]>0)
- {
- int r = j*(8+2*A+d_bytes)+8+2*i;
- g_i0_raw[j] = (s16)(u8)pdata[r];
- g_i0_raw[j] |= (s16)((u8)pdata[r+1] << 8);
- g_i0_dwt[j] = (float)g_i0_raw[j];
- }
- }
- else
- {
- g_i0_raw[j] = 0;
- g_i0_dwt[j] = 0;
- }
- }
- //xdl_smooth3(g_i0_raw, g_i0, XDL_SAMPLE_LEN);
- // memcpy(g_i0,g_i0_raw,sizeof(g_i0));
- DWT_Matrix_Transform(g_i0_dwt, g_i0, XDL_SAMPLE_LEN);
- if(ui[i]>0)
- {
- int ret,jd;
- struct timespec ts;
- TSETSW *pSet = &pRunSet->tSwSet[0];
-
- memset(&ts,0,sizeof(ts));
-
- // 零序电流处理
- // ret = xdl_proc_i0(N,0,7,&seg);
- ret = xdl_proc_i0(0,N,pSet->dI_xdl_zt,pRunSet->dU_xdl_u0_zt[0],&seg,0);
- jd = ui[i]-1;
- if(ui[i] >10)
- {
- *question_num = *question_num + 1;
- rt_printf("线路%s_%d:波形异常(ret=%d,jd=%d)!\r\n",name,i,ret,ui[i]-11);
- }
- else if(ret < 0 && jd == 0)
- {
- *skip_num = *skip_num + 1;
- //rt_printf("线路%s_%d:无算法(ret=%d,jd=%d)!\r\n",name,i,ret,jd);
- }
- else if(((ret-1) == jd)|| (ret == jd))
- {
- *ok_num = *ok_num + 1;
- //rt_printf("线路%s_%d:判断正确(ret=%d,jd=%d)!\r\n",name,i,ret,jd);
- }
- else
- {
- *err_num = *err_num + 1;
- rt_printf("线路%s_%d:判断错误(ret=%d,jd=%d)!\r\n",name,i,ret,jd);
- // xdl_info_printf();
- rt_printf("\r\n");
- }
-
- rcd_start_xdl(name,i,g_xdl_rcd_a,XDL_RCD_A_NUM,XDL_SAMPLE_LEN,&ts);
- }
- }
-
- rt_free(pdata);
-
- return 0;
- }
- /**
- * @brief xdl_i0_argument_init_by_scale
- * @details 通过零流采样通道CT类型初始化小电流i0判断参数
- * @param none
- * @return none
- * @author EW
- * @date 2024-01-16
- * @remarks 根据采样电阻的不同,小电流用不同的突变判断定值,目的是兼容未改电阻的采样板
- */
- void xdl_i0_argument_init_by_scale(void)
- {
- int cfg_index;
- uint32_t sw = 0;
- memset(&g_i0_arg, 0,sizeof(g_i0_arg));
- for(sw = 0; sw < g_sw_num; sw++)
- {
- cfg_index = g_sw[sw].ac_cfg_index[SW_AC_I0];
- // TODO 待确认是否更改硬件
- // if(g_equ_config_ac[cfg_index].scale == EQU_SCALE_CT_20A_300)
- // {
- // g_i0_arg[sw].ref_v_set = REV_F_CT_1A;
- // g_i0_arg[sw].scale_is_1A = true;
- // // rt_printf("sw: %d,i0 CT is CT_1V/1A\n", sw+1);
- // }
- // else
- {
- g_i0_arg[sw].ref_v_set = REV_F_CT_DEFAULT;
- g_i0_arg[sw].scale_is_1A = false;
- }
- }
- }
- /*------------------------------ 内部函数 -------------------------------------
- 内部函数以下划线‘_’开头,不需要检查参数的合法性.
- */
- /*------------------------------ 测试函数 -------------------------------------
- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中
- 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数).
- */
- int xdl_info_printf(void)
- {
- int i;
- rt_printf("小电流接地信息:\r\n");
- rt_printf("名称\t方向\t开始\t结束\t累加\t最大值\t最大位置\r\n");
- for(i=0;i<XDL_SEG_NUM;i++)
- {
- rt_printf("U0[%d]:\t%d\t%d\t%d\t%d\t%d\t%d\t\r\n",
- i,
- g_u0_seg[i].dir,
- g_u0_seg[i].bgn,
- g_u0_seg[i].end,
- g_u0_seg[i].acc,
- g_u0_seg[i].max_v,
- g_u0_seg[i].max_p);
- rt_printf("I0[%d]:\t%d\t%d\t%d\t%d\t%d\t%d\t\r\n",
- i,
- g_i0_seg[i].dir,
- g_i0_seg[i].bgn,
- g_i0_seg[i].end,
- g_i0_seg[i].acc,
- g_i0_seg[i].max_v,
- g_i0_seg[i].max_p);
-
- rt_printf("\r\n");
- }
- return 0;
- }
- int xdl_info_fromfile_printf(void)
- {
- int f_cnt=0;
- int i;
- int len;
- int ok_num,err_num,skip_num,question_num,ok_num0,err_num0,skip_num0,question_num0;
- struct dir_file_ext_struct *p_dfes;
- static char buf[128];
- p_dfes = hf_get_dir_file_ext(RCD_XDL_FILE_PATH, &f_cnt, "/tmp/xdl.tmp");
- if(!p_dfes)
- {
- rt_printf("没有录波文件 \r\n");
- rt_file_del("/tmp/xdl.tmp");
- return -1;
- }
- ok_num=0;
- err_num=0;
- skip_num=0;
- question_num = 0;
- for(i=0;i<f_cnt;i=i+2)
- {
- sprintf(buf, "%s%s",RCD_XDL_FILE_PATH, p_dfes[i].file_name);
- len=strlen(buf);
- buf[len-4]=0;
- rt_printf("文件:%s\r\n", p_dfes[i].file_name);
- ok_num0=0;
- err_num0=0;
- skip_num0=0;
- question_num0 =0;
- if(xdl_proc_file(buf,&ok_num0,&err_num0,&skip_num0,&question_num0)==0)
- {
- // xdl_info_printf();
- }
- ok_num += ok_num0;
- err_num += err_num0;
- skip_num += skip_num0;
- question_num += question_num0;
- rt_printf("\r\n");
- }
- i = ok_num+err_num+skip_num+question_num;
- if(i== 0)i=1;
- rt_printf("小电流算法:文件数=%d,线路总数=%d,正确线路=%d,忽略线路=%d,错误线路=%d,问题线路=%d,正确率=%d%%!\r\n",
- f_cnt/2,i,ok_num,skip_num,err_num,question_num,(ok_num+skip_num)*100/(i));
- rt_free(p_dfes);
- rt_file_del("/tmp/xdl.tmp");
- return 0;
- }
- int xdl_proc_highz(int sw) // 根据电流值大小判断接地属性,小于200ma,认为是高阻接地,用其他算法
- {
- int i;
- int v_max,v_min,v;
- u32 i0_300ma,u0_22v,i0_30ma;
- int dotmax,dotmin,dotv;
- int bgn,end;
- int ret=0;
- if(sw<0)return -1;
- u0_22v=pRunSet->dU_xdl_22V[pRunSet->tSwSet[sw].bTT_Power_v2];
- i0_300ma=pRunSet->tSwSet[sw].dI_xdl_300ma;
- i0_30ma=i0_300ma/9;
-
- v_max = INT_MIN;
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- v=abs(g_i0[i]);
- if(v> v_max )
- {
- v_max =v;
- }
- }
- if(v_max>i0_300ma||v_max<i0_300ma/4) //最大电流大于200ma,认为不是高阻接地,最大值小于66ma,认为无零序电流
- {
- return -1;
- }
- for(i=0; i<XDL_SAMPLE_LEN;i++)
- {
- if(abs(g_u0[i])>u0_22v)break;
- }
- if(i>=XDL_SAMPLE_LEN-ADC_REC_SAMPLE/2)return -1; //电压值太小
- v_max = INT_MIN;
- v_min=INT_MAX;
- bgn=i;
- end=bgn+ADC_REC_SAMPLE/2;
- dotmax=bgn;
- dotmin=bgn;
- for(i=bgn;i<end;i++) //找第一个极值点
- {
- v=g_u0[i];
- if(v> v_max )
- {
- v_max = v;
- dotmax=i;
- }
- if(v< v_min )
- {
- v_min = v;
- dotmin=i;
- }
- }
- if(dotmax>dotmin)
- {
- dotv=dotmin;
- }
- else
- {
- dotv=dotmax;
- }
- bgn=dotv-ADC_REC_SAMPLE/4;
- if(bgn<0)bgn=0;
- end=dotv+ADC_REC_SAMPLE/4;
- v_max = INT_MIN;
- v_min=INT_MAX;
- for(i=bgn;i<end;i++) //找第一个极值点
- {
- v=g_i0[i];
- if(v> v_max )
- {
- v_max = v;
- dotmax=i;
- }
- if(v< v_min )
- {
- v_min = v;
- dotmin=i;
- }
- }
- rt_printf("\r\ndot:bgn=%d,top=%d ,low=%d,vol=%d, top差值=%d low差值=%d\r\n ",dotv,dotmax,dotmin,dotv,abs(g_i0[dotv]-g_i0[dotmax]),abs(g_i0[dotv]-g_i0[dotmin]));
- // 判断电压极值点是否也是电流极值点
- if((abs(g_i0[dotv]-g_i0[dotmax])<=i0_30ma)
- ||(abs(g_i0[dotv]-g_i0[dotmin])<=i0_30ma)
- ||(abs(dotmax-dotv)<=10)
- ||(abs(dotmin-dotv)<=10)
- ) // 极值点相同,为界内
- {
- rt_printf("\r\ngz界内故障\r\n");
- ret=1;
- }
- else
- {
- rt_printf("\r\ngz界外故障\r\n");
- }
- return ret;
- }
- #endif
- /*------------------------------ 文件结束 -------------------------------------
- */
|