是否使用DMA传输
使用DMA传输,那么流程为:
- ADC初始化,DMA初始化,TIM2初始化
其中:TIM2作为ADC的中断源 - 当发生一次定时器的中断时,进入AD转换,在DMA的初始化时与ADC-DR寄存器进行绑定,在该寄存器获得数据时,直接通过DMA通道将该寄存器的数据保存在给定的数组里面,把缓存数组装满后,会触发一次DMA的中断,在DMA的中断里面将缓存数组保存到100个电压值的数组里面。
- 定时器设为200us发生一次中断,来进行一次AD转换,获得寄存器里面的数据以后,保存在数组,保存100个数组后停止定时器的工作以及DMA的工作,对这份数据进行处理。
至此,DMA工作的流程已经结束,那么其中又怎样的缺漏导致不用DMA进行操作,按照上述流程获得的100个离散点的电压是较为准确的(PS:这里可以把TIM2的定时中断时间改为采集32个点的625us或者采集64个点的312us),但是,如果只是放置在采集单相电压电流可以考虑,如果采集多相的电流电压,就要考虑到相位的问题,在之前的思路中
使用定时采集,流程为:
- ADC初始化、定时器TIM3初始化
这里的TIM3的中断时间为100us - 进过200us,即0.2ms,启动AD转换,比如三相交流电压,依次对A,B,C三通道AD进行转换,获得当前的电压值,保存在数组里面。
- 当保存了100个数据以后,如果不考虑误差,那么0.2ms*100=20ms,即为50Hz电压的一个周期的时间采集到的电压值,采集到的100个离散点使用均方根公式进行求值获得该通道的电压的有效值。
- 在此转换中,进过0.2ms进行一次转换,不停止,功耗比较大,但是每次获得数据后,都要通过数据是否过上升沿下降沿开始,判断有无错相。(关于是否错相算法见下文)
总结
对比两个流程可以知道:如果不考虑相位问题,那么可以使用DMA+ADC采集数据,比如0.5s开启一下DMA与定时器采集一次,采集到的100个数据保存在数组里面,关闭定时器与DMA,采集好以后进行处理一下存储在当前电压值的变量里面,但是这样的一组周期内的电压,存在着可能无法判断是否错相的情况,比如采集ABC三相,当A出现下降沿过抬高电压位置时,开始计时,可能从这时开始到这个周期结束没有发生B相出现上升沿过抬高电压的情况,这样判断错相就会出现问题,当然,也可以直接使用DMA+ADC去类似0.2ms就进行一次转换,不间断的进行这个流程,这个方式我认为与0.2ms手动开启AD转换,不经过DMA传输直接读取寄存器ADC-DR的值相差的功耗不大。(待测)
算法
采集
- AD采集到的数据进行处理获得当前的瞬时电压值:
ADC_DR/当前电压值 = 4096/3300毫伏
即 当前电压值 = (ADC_DR*3300)/4096;
在程序中我们对其进行了简化,最终的公式为
当前电压值 = (ADC_DR*825)>>10
就这样,我们保存了一个周期内100个点的电压值,也就是100个正弦波形上的离散点。
计算
根据100个离散点求得该引脚的电压的有效值:
均方根公式:
- 这个网上不少,直接百度即可
Xi为离散点的电压值,N为100,Xrms为电压有效值
其中要注意的是:Xi²实则为(引脚处电压 – 抬高电压)²
错相判断
下面为正相序时的波形图:
- 改天抽时间重画,原来的文件没了
譬如检测AB有无错相,当A出现下降沿并且过0点时(实际程序中是过抬高电压值时),开始计时,当B出现上升沿并且过0点时停止计时,这段时间T = 16.67ms,如果考虑一些特殊情况,比如电压的频率波动,开启计时的时间存在误差,可以假定T ≥15.5ms,AB为正相序。
下面为反相序时的波形图:
由此图我们可以看出,依旧像上面说的那样,在A(假定是A)相电压出现下降沿过0点时开启计时,在B相电压出现上升沿过零点时停止计时,此时时间远远小于正相序时的时间,如果无误差时T = 3.3ms,考虑到上述误差影响,那么我们把时间T ≤3.6ms时判断得AB为反相序。在程序中扩大了一下范围,把这个判断是否为反相序的时间调整为4.0ms,如果这段时间小于4.0ms,那么就认为是错相,大于的话默认为正相序。
错相与缺相的逻辑判断:
<1>. 当存在缺相时,不执行错相判断函数;
<2>. 当存在缺相时,将通信返回的内容里面的错相位置为0,只将缺相对应位置为1。
<3>. 当不存在缺相时,只判断AB是否错相,从A出现下降沿过0点开始计时,B出现上升沿过0点关闭计时,判断是否小于4.0ms,若是,则将错相位全部置为1,如果不是,全部置为0。
<4>. 关于缺相判断,在求得电压的有效值后,有一个范围,目前设定为50mv,如果小于50mv,说明该相电压缺相。