模拟PWM波的自适应取阈值算法
模拟PWM波的自适应取阈值算法
前言:
单片机开发中,我们常常接触到的波形就是PWM波,一般都是0~3.3V的数字PWM波,很少涉及模拟PWM波。两者有什么不同呢?模拟PWM波不只有高低电平,还有中间的一些变化过程,且波形可能也不是规整的矩形波,再者它的电压可能超过3.3v导致无法直接用单片机IO口识别,PWM无法直接捕获到上升下降沿。
如果你预算充足,开发的设备也不是非常的小型话,可以容纳额外的电路,那么你可以考虑从硬件上增加一些运放电路或整形电路,尽可能将模拟PWM变为数字PWM,如果不行就得考虑串联电阻来分压,然后代码中通过AD采样到数据后进行算法处理。
1 自适应算法
1.1 自适应取阈值算法思路:
模拟PWM波的自适应取阈值算法
前言:
单片机开发中,我们常常接触到的波形就是PWM波,一般都是0~3.3V的数字PWM波,很少涉及模拟PWM波。两者有什么不同呢?模拟PWM波不只有高低电平,还有中间的一些变化过程,且波形可能也不是规整的矩形波,再者它的电压可能超过3.3v导致无法直接用单片机IO口识别,PWM无法直接捕获到上升下降沿。
如果你预算充足,开发的设备也不是非常的小型话,可以容纳额外的电路,那么你可以考虑从硬件上增加一些运放电路或整形电路,尽可能将模拟PWM变为数字PWM,如果不行就得考虑串联电阻来分压,然后代码中通过AD采样到数据后进行算法处理。
1 自适应算法
1.1 自适应取阈值算法思路:
这里的MAX,MIN,LOW电压值都是不确定的,受传输距离和干扰影响。
1.2 具体算法:
- 求出PWM波采样值的MAX和MIN值:监测波形20ms(大于周期15.01ms),采集这段时间内的最大的20个采样值和最小的20个采样值(使用插入排序),舍弃20个数据的头尾各2个共4个数据,对十六个数据求平均值(求和后右移4位)。得出PWM的MAX和MIN值。
- 识别PWM波开始输出的第一个上升沿:差值MAXMINDiff = MAX - MIN, 监测波形20ms,寻找采样值从小于MIN + MAXMINDiff/3(避免1/3除法运算,1/3 = 5/15 约等于5/16 = 4/16 + 1/16 = 1/4 + 1/16 = >>2 + >>4)跳变到大于MAX - MAXMINDiff/3(且小于MIN + MAXMINDiff/3的持续时间需大于一个25kHz的周期,PWM输出期间半个周期就会有一个上升沿,若持续一个周期都未出现认为当前处于无PWM输出阶段)的上升沿。最大采集20ms,如果期间识别到上升沿则会提前结束,这段时间是不固定的。
- 识别PWM波的波峰值High和波谷值Low:PWM开始输出后进行1ms(理论PWM输出时间为1.28ms,监测时间需小于此)的监测,方法同步骤1,求出Low平均值, High平均值等于MAX平均值。
- 取阈值:求出差值HighLowDiff = High - Low,采样值取SampleHigh = High - HighLowDiff/3(1/3运算同步骤3), SampleLow = Low + HighLowDiff/3。
- 根据需要阈值也可选取为(SampleHigh + SampleLow)/2。
c代码实现(这段代码我在一个自动测试程序中一直在使用,暂未发现问题):
1 | //自适应求阈值函数,用于区分模拟PWM的上升下降沿。此函数工作在32MHz晶振下 |
这里的MAX,MIN,LOW电压值都是不确定的,受传输距离和干扰影响。
1.2 具体算法:
- 求出PWM波采样值的MAX和MIN值:监测波形20ms(大于周期15.01ms),采集这段时间内的最大的20个采样值和最小的20个采样值(使用插入排序),舍弃20个数据的头尾各2个共4个数据,对十六个数据求平均值(求和后右移4位)。得出PWM的MAX和MIN值。
- 识别PWM波开始输出的第一个上升沿:差值MAXMINDiff = MAX - MIN, 监测波形20ms,寻找采样值从小于MIN + MAXMINDiff/3(避免1/3除法运算,1/3 = 5/15 约等于5/16 = 4/16 + 1/16 = 1/4 + 1/16 = >>2 + >>4)跳变到大于MAX - MAXMINDiff/3(且小于MIN + MAXMINDiff/3的持续时间需大于一个25kHz的周期,PWM输出期间半个周期就会有一个上升沿,若持续一个周期都未出现认为当前处于无PWM输出阶段)的上升沿。最大采集20ms,如果期间识别到上升沿则会提前结束,这段时间是不固定的。
- 识别PWM波的波峰值High和波谷值Low:PWM开始输出后进行1ms(理论PWM输出时间为1.28ms,监测时间需小于此)的监测,方法同步骤1,求出Low平均值, High平均值等于MAX平均值。
- 取阈值:求出差值HighLowDiff = High - Low,采样值取SampleHigh = High - HighLowDiff/3(1/3运算同步骤3), SampleLow = Low + HighLowDiff/3。
- 根据需要阈值也可选取为(SampleHigh + SampleLow)/2。
c代码实现(这段代码我在一个自动测试程序中一直在使用,暂未发现问题):
1 | //自适应求阈值函数,用于区分模拟PWM的上升下降沿。此函数工作在32MHz晶振下 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 OnlyCalm's Blog!
评论
ValineGitalk