📄 gaojin.c
字号:
#include "GaoJin.h"
#include "includes.h"
#include "ADC12.H"
#include "msp430x14x.h"
#include <stdlib.h>
#include "TimerA.H"
//告警检测原理
//首先根据有效值判断,如果有效值小于6V那么肯定不会过载,
//在有效值大于6v的情况下判断采样值寻找削顶的情况
//然后根据频率跟踪得到的频率值再进行判断是否振荡了
gjsta GJSta;
//gjsta GJFiltered; //滤波后的
void GJTask(void *pdata)
{
pdata=pdata;
InitGjSta();
P2DIR&=~BIT0;
P2DIR|=BIT1;
P2OUT|=BIT1; //置为输出高电平,用来做告警禁止短接
while(1)
{
CheckFreq();
if(!(P2IN&BIT0)) //P2.0接地允许告警
{
GJOut();
}
//OSTimeDly(1);
}
}
void InitGjSta(void)
{
GJSta.gj=0;
}
void GJCheck(char Channel)
{
unsigned int max,min;
int sameMaxValNum,sameMinValNum;
int i,maxValLoca,minValLoca;
unsigned int subMax,subMin; //次大值和次小值
int subMaxValNum,subMinValNum;
int subMaxValLoca,SubMinValLoca;
int temp,temp1;
sameMaxValNum=sameMinValNum=0;
subMaxValNum=subMinValNum=0;
if(Channel<6)
{
if(val[Channel].Value>7000) //有效值大于7v才判断是否有削顶的值存在
{
//寻找最大值和最小值
max=min=adBuff.buff[0];
for(i=1;i<SAMPLENUM;i++)
{
if(adBuff.buff[i]>max)
{
max=adBuff.buff[i];
maxValLoca=i; //记录最大值的位置
}
else if(adBuff.buff[i]<min)
{
min=adBuff.buff[i];
minValLoca=i; //记录最小值的位置
}
}
//在记录的最大和最小值的位置周围搜索是否有一样的采样值存在并记录个数
for(i=maxValLoca-1;i>=0;i--) //往左边查找
{
if((max-adBuff.buff[i])<=sameValRange)
sameMaxValNum++;
else
break;
}
for(i=maxValLoca+1;i<SAMPLENUM;i++) //往右边查找
{
if((max-adBuff.buff[i])<=sameValRange)
sameMaxValNum++;
else
break;
}
//寻找最小值的个数
for(i=minValLoca-1;i>=0;i--) //往左边查找
{
if((adBuff.buff[i]-min)<=sameValRange)
sameMinValNum++;
else
break;
}
for(i=minValLoca+1;i<SAMPLENUM;i++) //往右边查找
{
if((adBuff.buff[i]-min)<=sameValRange)
sameMinValNum++;
else
break;
}
//寻找次大值和次小值
temp=max-adBuff.buff[0];
temp1=adBuff.buff[0]-min;
for(i=1;i<SAMPLENUM;i++)
{
if(i!=maxValLoca)
{
if(temp>(max-adBuff.buff[i]))
{
temp=adBuff.buff[i];
subMaxValLoca=i;
subMax=adBuff.buff[i];
}
}
if(i!=minValLoca)
{
if(temp1>(adBuff.buff[i]-min))
{
temp1=adBuff.buff[i];
SubMinValLoca=i;
subMin=adBuff.buff[i];
}
}
}
for(i=subMaxValLoca-1;i>=0;i--) //往左边查找
{
if((subMax-adBuff.buff[i])<=sameValRange)
subMaxValNum++;
else
break;
}
for(i=subMaxValLoca+1;i<SAMPLENUM;i++) //往右边查找
{
if((subMax-adBuff.buff[i])<=sameValRange)
subMaxValNum++;
else
break;
}
//寻找次小值的个数
for(i=SubMinValLoca-1;i>=0;i--) //往左边查找
{
if((adBuff.buff[i]-subMin)<=sameValRange)
subMinValNum++;
else
break;
}
for(i=SubMinValLoca+1;i<SAMPLENUM;i++) //往右边查找
{
if((adBuff.buff[i]-subMin)<=sameValRange)
subMinValNum++;
else
break;
}
}
if(sameMaxValNum>GJsameValNum || sameMinValNum>GJsameValNum ||subMaxValNum>GJsameValNum ||subMinValNum>GJsameValNum) //削顶了
{
switch(Channel)
{
case UA:
GJSta.ua=1;
break;
case UB:
GJSta.ub=1;
break;
case UC:
GJSta.uc=1;
break;
case IA:
GJSta.ia=1;
break;
case IB:
GJSta.ib=1;
break;
case IC:
GJSta.ic=1;
break;
}
}
else
{
switch(Channel)
{
case UA:
GJSta.ua=0;
break;
case UB:
GJSta.ub=0;
break;
case UC:
GJSta.uc=0;
break;
case IA:
GJSta.ia=0;
break;
case IB:
GJSta.ib=0;
break;
case IC:
GJSta.ic=0;
break;
}
}
}
else if(Channel==6) //电源通道
{
if(abs(val[Channel].Value/1000-POWERVOLT)>=POWERDROPVAL) //电源差异达到5v
GJSta.pwr=1;
else
GJSta.pwr=0;
}
}
//原理:
//判断最大和最小值是否在过零点偏移90度的地方,
//如果不是那么就是过载了,这个判据可以解决上面的方法不能解决的
//一些情况,比如严重削顶时有可能顶部一条水平的线而是带斜度的,那么
//光是寻找有多少个相似的最大值可能就判断不出来了
void GJCheckNew(char Channel)
{
unsigned int max;
char j,k;
int i,maxValLoca;
long adAverage;
int temp,Offset90DegLocal;
temp=0;
maxValLoca=0;
if(Channel<6)
{
if(val[Channel].Value>10000) //有效值大于7v才判断是否有削顶的值存在
{
//寻找最大值和最小值
max=adBuff.buff[0];
adAverage=0;
for(i=0;i<SAMPLENUM;i++)
{
if(adBuff.buff[i]>max)
{
max=adBuff.buff[i];
maxValLoca=i; //记录最大值的位置
}
adAverage+=adBuff.buff[i];
}
i=0;
temp=SAMPLENUM;
do
{
temp/=2;
i++;
}
while(temp);
adAverage=adAverage>>(i-1); //求得平均值
//寻找过零点,在最大值的两边分别寻找过零点
//如果波形没有削顶那么在最大值的某一侧偏移90度的地方
//肯定可以找到一个过零的位置,如果找不到那么就说明最大值出现的位置
//不是在正弦波的顶点也就是说削顶了
//每周波采样SAMPLENUM个点,两个点之间相差360/(SAMPLENUM-1)度
//90度的位置在maxValLoca+-(90/(360/(SAMPLENUM-1)))的地方
//
Offset90DegLocal=(int)((double)90.0/(360.0/((double)SAMPLENUM-1.0)));
temp=1;
j=k=0;
if(maxValLoca+Offset90DegLocal<(SAMPLENUM-SERCHRANGE))//往右侧搜索,如果存在削顶相象那么过零点肯定在
{ //maxValLoca+Offset90DegLocal位置的右边所以留4个点的裕量
for(i=0;i<SERCHRANGE;i++) //这样可以更加准确的得到判断
{
if(adBuff.buff[maxValLoca+Offset90DegLocal+i]<adAverage)
j++;
if(adBuff.buff[maxValLoca+Offset90DegLocal-i]>adAverage)
k++;
}
if(j>=2 && k>=2)//确实在过零点附近
temp=0;
//if(abs((adBuff.buff[ maxValLoca+Offset90DegLocal]-adAverage))>20) //削顶了
// temp=1;
}
else if(maxValLoca-Offset90DegLocal>=SERCHRANGE)//往左边查找
{
for(i=0;i<SERCHRANGE;i++) //这样可以更加准确的得到判断
{
if(adBuff.buff[maxValLoca-Offset90DegLocal+i]>adAverage)
j++;
if(adBuff.buff[maxValLoca-Offset90DegLocal-i]<adAverage)
k++;
}
if(j>=2 && k>=2)//确实在过零点附近
temp=0;
//if(abs((adBuff.buff[ maxValLoca+Offset90DegLocal]-adAverage))>20) //削顶了
// temp=1;
}
}
if(temp) //削顶了
{
switch(Channel)
{
case UA:
GJSta.ua=1;
break;
case UB:
GJSta.ub=1;
break;
case UC:
GJSta.uc=1;
break;
case IA:
GJSta.ia=1;
break;
case IB:
GJSta.ib=1;
break;
case IC:
GJSta.ic=1;
break;
}
}
else
{
switch(Channel)
{
case UA:
GJSta.ua=0;
break;
case UB:
GJSta.ub=0;
break;
case UC:
GJSta.uc=0;
break;
case IA:
GJSta.ia=0;
break;
case IB:
GJSta.ib=0;
break;
case IC:
GJSta.ic=0;
break;
}
}
}
else if(Channel==6) //电源通道
{
if(abs(val[Channel].Value/1000-POWERVOLT)>=POWERDROPVAL) //电源差异达到5v
GJSta.pwr=1;
else
GJSta.pwr=0;
}
}
/*
//综合以上两个方法的告警检测函数,更可靠更灵敏,更加可以信赖
void GJCheckExtra(char Channel)
{
unsigned int max,min;
char sameMaxValNum,sameMinValNum;
char maxValLoca,minValLoca;
int i;
static char count=0;
static char count1=0;
static long time=0;
static long time1=0;
//char subMaxValNum,subMinValNum;
//char subMaxValLoca,subMinValLoca;
//int temp1;
int temp;
long adAverage;
int Offset90DegLocal;
signed char j,k;
sameMaxValNum=sameMinValNum=0;
temp=0;
adAverage=0;
maxValLoca=0;
minValLoca=0;
//subMaxValLoca=subMinValLoca=0;
if(Channel<6)
{
if(val[Channel].Value>12500) //有效值大于12.5v才判断是否有削顶的值存在
{
//寻找最大值和最小值
max=min=adBuff.buff[0];
for(i=0;i<SAMPLENUM;i++)
{
if(adBuff.buff[i]>max)
{
if((adBuff.buff[i]-adBuff.buff[i-1]<400) && (adBuff.buff[i]-adBuff.buff[i+1]<400)) //变化太大为干扰或误采样
{
max=adBuff.buff[i];
maxValLoca=i; //记录最大值的位置
}
}
else if(adBuff.buff[i]<min)
{
if((adBuff.buff[i-1]-adBuff.buff[i]<400) && (adBuff.buff[i+1]-adBuff.buff[i]<400)) //变化太大为干扰或误采样
{
min=adBuff.buff[i];
minValLoca=i; //记录最小值的位置
}
}
adAverage+=adBuff.buff[i];
}
//在记录的最大和最小值的位置周围搜索是否有一样的采样值存在并记录个数
for(i=maxValLoca-1;i>=0;i--) //往左边查找
{
if((max-adBuff.buff[i])<=sameValRange)
sameMaxValNum++;
else
break;
}
for(i=maxValLoca+1;i<SAMPLENUM;i++) //往右边查找
{
if((max-adBuff.buff[i])<=sameValRange)
sameMaxValNum++;
else
break;
}
//寻找最小值的个数
for(i=minValLoca-1;i>=0;i--) //往左边查找
{
if((adBuff.buff[i]-min)<=sameValRange)
sameMinValNum++;
else
break;
}
for(i=minValLoca+1;i<SAMPLENUM;i++) //往右边查找
{
if((adBuff.buff[i]-min)<=sameValRange)
sameMinValNum++;
else
break;
}
i=0;
temp=SAMPLENUM;
do
{
temp/=2;
i++;
}
while(temp);
adAverage=adAverage>>(i-1); //求得平均值
//寻找过零点,在最大值的两边分别寻找过零点
//如果波形没有削顶那么在最大值的某一侧偏移90度的地方
//肯定可以找到一个过零的位置,如果找不到那么就说明最大值出现的位置
//不是在正弦波的顶点也就是说削顶了
//每周波采样SAMPLENUM个点,两个点之间相差360/(SAMPLENUM-1)度
//90度的位置在maxValLoca+-(90/(360/(SAMPLENUM-1)))的地方
//
Offset90DegLocal=(int)((double)90.0/(360.0/((double)SAMPLENUM-1.0)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -