/*************************** 20/05/17更新说明 ********************************/
我发现我实际电路中焊接的R38和R39分别是3k和1k,由于R38和R39的不同值会对UCQ的测量产生影响,为了和程序中关于UCQ相关的判断对应,我就把这篇博客里面关于UCQ的内容做了调整。
之前我对测量部分的软件进行了分析,如果程序中可以准确进行参数测量了,那么故障判断中就可以判断出绝大部分故障了。现在我来分析一下故障判断部分的软件执行过程,同时分析一下该故障对电路的参数会产生什么影响。
一、故障模式的触发
if(Current_Menu == NULL) //界面
{
if((key == KEY0_PRES) && (device_mode == DEVICE_MODE_MEASURE)) //测量模式 向上键
{
Measure_data.data_reg.Measure = 1;//开始测量
DC_OFFSET_MEASURE();//测直流偏置
vTaskDelay(100);
measure_sta = MEASURE_DC_STA; //测量直流偏置
}
else if(key == KEY1_PRES)//向下键 模式切换
{
if(device_mode == DEVICE_MODE_MEASURE)
{
device_mode = DEVICE_MODE_JUDGE; //判断
Measure_data.data_reg.Measure = 1;//开始测量
DC_OFFSET_MEASURE();//测直流偏置
vTaskDelay(100);
measure_sta = MEASURE_DC_STA; //测量直流偏置
}
else
device_mode = DEVICE_MODE_MEASURE; //测量
DDS_reg.fre_num = 1000;
DDS_reg.fre_sta = 1;
Display_Clear();
}
}
basic_task任务中和模式切换相关的代码如上所示
根据试题中的要求,测试仪进入故障判断模式之后,可以自动判断故障产生的原因,全程不能有人工进行干预操作。因此程序中应该循环的进行参数的测量,然后根据测量的参数进行故障的判断。故障判断模式和测量模式,通过在主界面显示时按下KEY1按键进行切换,切换到故障判断模式后测试仪进行参数的循环测量,一次循环之后进行故障判断,再次按下KEY1按键可以退出故障判断模式进入测量模式。
二、故障判断模式的流程
故障判断模式的基本流程图如图1所示,整个过程就是一个不断循环测量的过程,这里相比于测量模式下测量的参数,增加了Av5k、Av200k和Av200,具体测量这三个参数的作用是什么,稍后进行分析,这里大家只需要把判断模式的大体流程弄清楚即可。
其中R1-R4电阻开路与短路故障、C1和C2电容开路故障全都在函数Judge_Change中进行判断,Judge_Change函数定义在HARDWARE/ADC.c中,函数内容如下,函数具体分析会在后面针对具体的故障中进行分析。
//返回值 0:无故障 其他:故障编号
uint8_t Judge_Change(void)
{
uint8_t i;
for(i = R1_OPEN;i<=C3_TO_2;i++)
{
switch(i)
{
case(R1_OPEN):
if((Measure_data.Ri > 13000) && (Measure_data.Ro < 100) && (Measure_data.Dc > 7000) && (Measure_data.Dc < 9000))
{//R1开路
Judge_Change_Mark.Judge_type = R1_OPEN;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(R2_OPEN):
if((Measure_data.Dc > 3000) && (Measure_data.Dc < 4000))
{//R2开路
Judge_Change_Mark.Judge_type = R2_OPEN;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(R3_OPEN):
if((Measure_data.Dc < 500) && (Measure_data.Ri < 500) && (Measure_data.Ro < 100) && (Measure_data.Av < 10))
{//R3开路
Judge_Change_Mark.Judge_type = R3_OPEN;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(R4_OPEN):
if((Measure_data.Dc > 7000) && (Measure_data.Dc < 9000) && (Measure_data.Ri > 10000) && (Measure_data.Ri < 12000)&& (Measure_data.Ro < 100))
{//R4开路
Judge_Change_Mark.Judge_type = R4_OPEN;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(R1_SHORT):
if((Measure_data.Dc > 10800) && (Measure_data.Dc < 11300) && (Measure_data.Ri < 500) && (Measure_data.Ro < 100))
{//R1短路
Judge_Change_Mark.Judge_type = R1_SHORT;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(R2_SHORT):
if((Measure_data.Dc > 7000) && (Measure_data.Dc < 9000) && (Measure_data.Ri < 100) && (Measure_data.Ro < 100))
{//R2短路
Judge_Change_Mark.Judge_type = R2_SHORT;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(R3_SHORT):
if((Measure_data.Dc > 11500) && (Measure_data.Ro < 100))
{//R3短路
Judge_Change_Mark.Judge_type = R3_SHORT;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(R4_SHORT):
if((Measure_data.Dc < 300) && (Measure_data.Av < 200) && (Measure_data.Av > 20))
{//R4短路
Judge_Change_Mark.Judge_type = R4_SHORT;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(C1_OPEN):
if((Measure_data.Dc > 4000) && (Measure_data.Dc < 5500) && (Measure_data.Ri > 20000) && (Measure_data.Ro < 100) && (Measure_data.Av < 10))
{//C1开路
Judge_Change_Mark.Judge_type = C1_OPEN;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
case(C2_OPEN):
if((Measure_data.Dc > 4000) && (Measure_data.Dc < 5500) && (Measure_data.Ri > 5000) && (Measure_data.Ri < 10000) && (Measure_data.Av < 50))
{//C2开路
Judge_Change_Mark.Judge_type = C2_OPEN;
Judge_Change_Mark.Jude_sta = 1;
return i;
}
break;
default:
Judge_Change_Mark.Judge_type = 0;
Judge_Change_Mark.Jude_sta = 0;
break;
}
}
return 0;
}
三、R1-R4电阻开路与短路故障判断
1. R1开路
R1开路之后,放大电路没有了一个合适的静态工作点,三极管工作在截止区,此时放大电路的输入电阻Ri(以后没有特殊说明时,Ri和Ro指的是输入信号频率为1k时的Ri和Ro。)应该约等于R2的值为15k,由于没有输出的交流信号,Ro的测量值应该为0,测得的UCQ值应该是 1 k + 2 k 1 k + 3 k + 2 k ∗ 12 V = 8 V \frac{1k+2k}{1k+3k+2k}*12V=8V 1k+3k+2k1k+2k∗12V=8V,根据Judge_Change中的case(R1_OPEN):分支代码即可看出,程序中就是依靠的这三个参数进行判断的,判断R1是否开路。由于测量存在误差,元器件的参数存在离散性,所以Ri>13k && Ro<100 && 7000mVCQ<9000mV,这些判断门槛范围都是我根据自己电路进行实际的测量得到的,获得的方法就是在测量模式下将R1开路然后测量一遍数据,看一下测得数据是多少,根据测得的数据进行门槛设置。后面的其他故障同样可以这么做,根据测试仪的实际数据然后结合理论分析设置判断的条件。
2. R2开路
R2开路同样影响的是静态工作点,但是这里的UCQ受三极管的特性影响较大,不同的9013很可能不大相同,我这里的判断依据是 3000mVCQ<4000mV,这个范围是我在测量模式下将R2开路之后测量得到的值,这个值比较特殊,其他的故障不会造成 UCQ等于这个值,这个范围的设定还是需要各位进行实际测量得出。
3. R3开路
R3开路导致三极管集电极没有电压,导致三极管无法正常工作,BE相当于一个二极管,因此输入电阻很小,同时没有信号输出Ro也测量不到,UCQ基本为0,Av(没有说明的话Av表示1k时的增益)基本为0。考虑到测量误差等影响,程序中的判断依据如下,各位可以根据自己电路实际测量值进行设置。
if((Measure_data.Dc < 500) && (Measure_data.Ri < 500) && (Measure_data.Ro < 100)
&& (Measure_data.Av < 10))
4. R4开路
R4开路同样会影响电路的静态工作点,E极没有了直流通路,三极管截止。体现在参数中就是Ri=R1//R2=11k、UCQ=8V、Ro测量值为0。考虑到测量的误差,程序中的判断条件如下。
if((Measure_data.Dc > 7000) && (Measure_data.Dc < 9000) && (Measure_data.Ri > 10000)
&& (Measure_data.Ri < 12000)&& (Measure_data.Ro < 100))
5. R1短路
R1短路影响的还是电路的静态工作点,三极管完全饱和,UCQ=12V-UBE-UCE=12-0.7-0.3=11V,这时的Ri基本为0,Ro测量值为0,这些参数的判断范围和门槛最好根据自己实际的测量值进行设置,特别是UCQ的值,不同的三极管的UBE和饱和UCE还是有点差别的,同时电源的12V的误差也会影响最终的UCQ值,软件中的判断部分代码如下。
case(R1_SHORT):
if((Measure_data.Dc > 10800) && (Measure_data.Dc < 11400) && (Measure_data.Ri < 500)
&& (Measure_data.Ro < 100))
6. R2短路
R2短路导致三极管截止,体现在参数上就是Ri基本为0、UCQ=8V、Ro测量值为0,考虑到误差的情况下设置的判断条件如下。
case(R2_SHORT):
if((Measure_data.Dc > 7000) && (Measure_data.Dc < 9000) && (Measure_data.Ri < 100)
&& (Measure_data.Ro < 100))
7. R3短路
R3短路导致没有输出电阻,三极管的UCQ为12V,同时Ro的测量值为0,代码中判断R3短路的条件如下。主要根据UCQ的与众不同来判断。
case(R3_SHORT):
if((Measure_data.Dc > 11500) && (Measure_data.Ro < 100))
8. R4短路
R4短路的话影响电路的静态工作点,三极管基本饱和,UCQ=UCE=0.3,此时虽然三极管饱和但是Ui还是会对三极管的基极电流产生影响,这里体现在会产生Uo的输出,虽然这个Uo大概率是失真的,但是测试仪还是会测量到信号Uo,参数体现就是Av的值不为0,由于Ui很小,最后的Av可能有一定的数值,但是不会很大。我经过实际的测量,得到我的电路中此时的Av大概在4.0(带一位小数,程序中为40)左右,这个值需要各位实际进行测量然后进行设置。相关判断条件如下。
case(R4_SHORT):
if((Measure_data.Dc < 300) && (Measure_data.Av < 200) && (Measure_data.Av > 20))
四、C1-C3开路
1. C1开路
C1开路不会影响电路的静态工作点,由于输入开路此时测量的到的Ri应该是无穷大,由于没有输出信号Ro测量值为0,Av也为0。由于电路的静态工作点正常,此时的UCQ会由于电路中三极管的差别产生细微的差别,我这里测量得到UCQ为4.8V左右(实际的静态工作点为7.2V,由于外接了R38和R39,导致电压下降。),这个值需要实际测量得出。程序中的相关判断条件代码如下。
case(C1_OPEN):
if((Measure_data.Dc > 4000) && (Measure_data.Dc < 5500) && (Measure_data.Ri > 20000) && (Measure_data.Ro < 100) && (Measure_data.Av < 10))
2. C2开路 3. C3开路 Av200k的测量方式和之前测量截止频率的方法相同,采用的都是扫描法,计算和相应的判断过程在FPTX_Cal_200K_Handle函数中,函数代码如下。 程序中可以看出,C3开路体现在具体参数上的判断依据是,Ro、Ri、UCQ和Av都正常的情况下,只有Av200k > Av5k*0.75的情况在才会判断为C3开路。 C2变为原来两倍的判断程序部分在Av_Cal_200Hz_Handle函数中,函数中计算采样的到数据,计算完成之后得到Av200的值,由于这个判断是在其他故障判断之后的,并且C2变为两倍基本不会对Ri、Ro、UCQ和Av产生影响,并且之前故障的判断门槛已经比较的宽松,不会和C2变为两倍产生冲突,因此这里只是单纯的判断了一下Av200是否大于100.0(这个值还是需要各位去进行实际测量得到,受β的影响比较大。注意Av都是带有一位小数的,所以程序里是大于1000。),大于则认为是C2变为两倍故障。 3. C1变为两倍 从上面3幅图中可以看出,阶跃信号对C1的充电情况,C1变大的时候充电速度明显变慢了,10ms时10uF电容充电了大概941.27mV,20uF电容充电大概830.42mV,有明显的差距,根据这个理论方向去实验测试,应该可以判断出C1是否变化为原来的两倍。 六、判断时间在2s之内 ---------------------------------------------------------------分割线----------------------------------------------------------------- 至此程序中有关故障判断的部分已经分析完了,如果有地方有疑问的话,欢迎各位留言交流。之后将开始更新程序中有关校准的部分。 PS:程序源码和硬件电路图都在之前发的这个系列博文第一篇中,大家可以在那篇博文的最下面,点击网盘链接进行下载。
C2开路同样不影响电路的静态工作点,Ri≈R1//R2//(1+β)R4,由于β的差异不同的电路会有区别,但是Ricase(C2_OPEN):
if((Measure_data.Dc > 4000) && (Measure_data.Dc < 5500) && (Measure_data.Ri > 5000) && (Measure_data.Ri < 10000) && (Measure_data.Av < 50))
C3开路不影响放大电路的任何特性,C3的作用就是和放大电路的输出电阻R3构成了一个低通滤波器,C3存在时截止频率大概是169k,去掉C3之后该电路的截止频率由放大电路的带宽决定,fβ=fT/β,通过查看9013的数据手册可以知道三极管的特征频率fT是100MHz,因此fβ>300kHz。这里为了判断C3是否开路,选择去测量信号频率为200kHz时的Av200k。
通过图1可以知道,测量Av200k之前需要先判断Av5k有没有测量,这里的Av5k认为是放大电路的通频带增益,为了节省时间没有去对整个频率范围进行扫描,直接认为Av5k就是通频带的最大增益,这样做会有误差,但是会减少测量时间,程序中判断C3开路的流程基本如下。
//返回值 :1正常 0C3开路 2C3增大为原来2倍
uint8_t FPTX_Cal_200K_Handle(void)
{
uint16_t data_max[5],data_min[5],min_seaf,max_seaf;//最值
uint16_t i,j;
uint32_t cal;
for(i = 0;i < 5;i++)
{
data_max[i] = 0;
data_min[i] = 0xffff;
}
for(j = 0;j < 5;j++)
{
for(i = 0;i < ADC3_UO2_SIZE;i++)
{
if(data_max[j] < ADC3_BUFF_UO2[i])
{
data_max[j] = ADC3_BUFF_UO2[i];
max_seaf = i;
}
if(data_min[j] > ADC3_BUFF_UO2[i])
{
data_min[j] = ADC3_BUFF_UO2[i];
min_seaf = i;
}
}
ADC3_BUFF_UO2[min_seaf] = ADC3_BUFF_UO2[max_seaf] = (data_min[j] + data_max[j])/2;
}
data_min[0] = (data_min[0] + data_min[1] + data_min[2] + data_min[3] + data_min[4])/5;
data_max[0] = (data_max[0] + data_max[1] + data_max[2] + data_max[3] + data_max[4])/5;
cal = data_max[0] - data_min[0];
cal = cal*3300/4096*Uo_gain/10;//单位mv Uo峰峰值
//计算增益
cal = cal*100/Ui_Rms;//得到增益大小0.1
if((cal <= Judge_5K_Av*75/100))//200K时的增益小于 5K时的增益的0.75-0.55 认为是C3没开路了
{
if((cal >= Judge_5K_Av*55/100))//正常
return 1;
else//衰减很大
{
if((Measure_data.Dc > 4000) && (Measure_data.Dc < 5500) && (Measure_data.Ri > 800) && (Measure_data.Ri < 3000)
&& (Measure_data.Ro < 2500) && (Measure_data.Ro > 1500) && (Measure_data.Av > 1000))//满足这些条件才是C3to2
return 2;
}
}
else
{
if((Measure_data.Dc > 4000) && (Measure_data.Dc < 5500) && (Measure_data.Ri > 800) && (Measure_data.Ri < 3000)
&& (Measure_data.Ro < 2500) && (Measure_data.Ro > 1500) && (Measure_data.Av > 1000))//满足这些条件才是C3开路
return 0;
}
return 1;
}
五、C1-C3增大为原来两倍
1. C3增大为原来两倍
C3增大为原来的两倍,对整体的影响体现在后面的低通滤波器的带宽变窄了,我这里的判断方法是和C3开路一起判断,同样是测量Av200k来进行判断。按照理想的阻抗计算的话,C3为470pF时Av200k应该等于Av5k(认为是通频带的最大增益)的0.65左右,C3为940pF时Av200k应该等于Av5k的0.39左右,算上元器件的误差(电阻电容的误差需要尽可能的接近理论值,否则需要校准。),最后经过实际的测试我这里取了0.55作为门槛判断值。具体的程序在FPTX_Cal_200K_Handle函数中,上面已经给出了函数的具体代码。
2. C2增大为原来的两倍
C2增大为原来的两倍后,主要影响的就是放大电路的低频特性,我这里采用的判断依据是测量信号频率为200Hz是的Av200,此时放大电路的低频特性主要受C2影响,如果C2增大为原来的两倍的话那么Av200也将会适当的变大。放大电路的增益 A v ≈ β R 3 r b e + ( 1 + β ) R e Av≈\frac{βR3}{rbe+(1+β)Re} Av≈rbe+(1+β)ReβR3,C2变大会为原来的两倍时主要影响的就是rbe+(1+β)Re的大小,将信号频率变为200会放大其对rbe+(1+β)Re的影响。由于这里的rbe会比测量得到的Ri大一些,我实际测量的到Ri在2k左右,所以rbe我设为3k。信号为1k时C2变大为2倍,Re从3.4欧变为1.7欧,设β为150,则rbe+(1+β)Re从3513欧变为3255欧,变化了7%,这个变化程度很小,可能一点测量误差就会导致判断出错。信号频率为200欧时,C2变为原来的两倍后,Re从16.95欧变为8.47欧,则rbe+(1+β)Re从5559欧变为4279欧,变化了23%,这个变化就比较大了,一点测量误差基本不会影响最后的判断。
上面的理论分析,只是为我们确定了一个判断的方向,需要去求Av200,求Av200的方法我采用了均方根算法,由于这个频率不大,采用均方根算法比较准确。判断流程图如下所示。
也可以将本次Av200的值和之前Av200的值进行比较,如果本次Av200的值突然变大了不少,认为是C2变为2倍了。
C1变为两倍的故障判断,我在程序中没有实现,根据理论分析来说,C1变为原来的两倍会影响放大电路的输入电阻Ri的大小,但是这个变化不会很明显,采用我原来的硬件电路这个变化是测量不出来的。要判断C1是否变大为原来的两倍,需要采用一个阶跃信号对电容进行充电,然后测量电容充电的快慢,来判断C1是否变大为原来的两倍,按照这个思路我去仿真了一下。下面是仿真结果。
想要改进获得这个功能的话,需要在原来的电路基础上,在增加一路Ui输出,及串联电阻输出一个阶跃信号,然后再回采Ui信号的大小即可。(后续可能会完善更新这部分内容)
题目要求中,判断时间控制在2s之内,程序中每进行一次完整的测量流程之后,就会显示当前是否有故障,有故障则显示故障的种类。显示任务Main_Display中,每当一次循环完成之后,就会判断并显示当前的电路状态。所以必须要使得程序中,2次循环的时间小于2s,目前我在程序中加入了很多等待电路就绪稳定的延时,主要体现在不同参数测量之间,循环用时主要都浪费在各种延时上了,各位如果觉得判断的慢的话,可以适当的减少延时时间,但是减少延时的时间能会让参数的量出现不稳定的现象,切记。
同时R1-R3的开路和短路、C1和C2的开路这些故障的判断速度会相对快一点,因为这些故障不需要去测量Av200k和Av200,C3开路和C2、C3变为两倍故障则判断时间相对较长。