0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32的ADC采样及各式滤波算法实现

硬件攻城狮 来源:CSDN-混分巨兽龙某某 2024-10-28 10:51 次阅读

前言:本文为手把手教学ADC采样及各式滤波算法教程,本教程的MCU采用STM32F103ZET6。以HAL库的ADC采样函数为基础进行教学,通过各式常见滤波的实验结果进行分析对比,搭配VOFA+工具直观的展示滤波效果。

实验效果图:

3c464060-90dd-11ef-a511-92fbcf53809c.png

3c5c841a-90dd-11ef-a511-92fbcf53809c.png

一、ADC采样

1.1 ADC简介

单片机是数字芯片,只认识由0和1组成的逻辑序列。但实际情况下,生活中还有许多非0和1的模拟物理量存在,例如温度,湿度等。这时候往往需要使用到AD转换,AD转换的英文就是Analog(模拟) to Digital(数字) ,由模拟量转化为数字量;同理DA,则为Digital to Analog,数字量转化为模拟量。

ADC,Analog to Digital Converter 的缩写,中文名称模数转换器。它可以将外部的模拟信号转化成数字信号。使用它去读取IO口上的数值将不再是简单的0或1,而是连续可变的数值。ADC采样就是把随时间连续变化的模拟量转换为时间离散的模拟量。

ADC几个比较重要的参数

(1)测量范围:测量范围对于 ADC 来说就好比尺子的量程,ADC 测量范围决定了你外接的设备其信号输出电压范围,不能超过 ADC 的测量范围(比如,STM32系列的 ADC 正常就不能超过3.3V)。

(2)分辨率:假如 ADC 的测量范围为 0-5V,分辨率设置为12位,那么我们能测出来的最小电压就是 5V除以 2 的 12 次方,也就是 5/4096=0.00122V。很明显,分辨率越高,采集到的信号越精确,所以分辨率是衡量 ADC 的一个重要指标。

(3)采样时间:当 ADC 在某时刻采集外部电压信号的时候,此时外部的信号应该保持不变,但实际上外部的信号是不停变化的。所以在 ADC 内部有一个保持电路,保持某一时刻的外部信号,这样 ADC 就可以稳定采集了,保持这个信号的时间就是采样时间。

(4)采样率:也就是在一秒的时间内采集多少次。很明显,采样率越高越好,当采样率不够的时候可能会丢失部分信息,所以 ADC 采样率是衡量 ADC 性能的另一个重要指标(详细参考信号处理方向书籍)

1.2 STM32的ADC

STM32 拥有 1~3 个 ADC(STM32F101/102 系列只有 1 个 ADC,STM32F103系列则有3个ADC和1个DAC),这些 ADC 可以独立使用,也可以使用双重模式(提高采样率)。STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。

特别说明:

ADC 是12位逐次逼近型模数转换器,

输出数值范围是 0 ~ 2^12 -1(0 ~ 4095),满量程是 3.3V ,

分辨率就是最低有效位(LSB)的对应输入电压值。

分辨率 =3300/4095 ≈ 0.806mV。

STM32F10X 系列将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于正常运行的程序,而注入通道呢,就相当于中断打断式通道选择。在程序正常执行的时候,中断是可以打断程序执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。

3c907b62-90dd-11ef-a511-92fbcf53809c.png

二、VOFA+

2.1 VOFA+简介

VOFA+是一款直观、灵活、强大的插件驱动高自由度的上位机,在与电气打交道的领域里,如自动化、嵌入式物联网机器人等,都能看到VOFA+的身影。VOFA+的名字来源于:Volt/伏特、Ohm/欧姆、Fala/法拉、Ampere/安培,是电气领域的基础单位,与他们的发明者——4位电子物理学领域的科学巨人,分别同名。他们的首字母共同构成了VOFA+的名字。

VOFA+特点概览:

平台支持:Windows、Linux、MacOS;

接口支持:串口(超高波特率,稳定支持)、网口(TCP客户端/服务端,UDP);

协议支持:协议为插件,已开源,人人可编写。目前已支持CSV风格的字符串协议,和十六进制浮点数组形式的字节流协议;

控件支持:控件为插件,已开源,人人可编写。目前已支持波形图、按钮、状态灯、图片、滑动条、3D立方控件(可更换模型)等;

数据维度自由化:2维度与3维,一个也不能拉下;

自主研发的波形控件:支持每通道百万采样点的绘制,性能强劲;

自主研发的波形控件:无缝嵌入了实时直方统计和点数可设置的傅里叶变换,可以使用VOFA+进行数据分析。

2.2 VOFA+使用方法

VOFA+的数据协议引擎有3种:FireWater,JustFloat,RawData。每种数据协议引擎都有自己特殊的使用效果,读者朋友可以根据自己的实际需要去选择使用。作者这里主要给大家演示一下FireWater协议下的VOFA+使用效果和方法。

FireWater协议是CSV风格的字符串流,直观简洁,编程像printf简单。但由于字符串解析消耗更多的运算资源(无论在上位机还是下位机),建议仅在通道数量不多、发送频率不高的时候使用。

3cb8edea-90dd-11ef-a511-92fbcf53809c.png

将鼠标放到FireWater协议上,可以很贴心的得到使用格式帮助。如上图所示,我们使用printf("simples:%f, %f ", sin(t1), sin(t2)")函数进行打印测试。

#include "math.h"
#include "stdio.h"
....
int main(void)
{
  /* USER CODE BEGIN 1 */
  float t1 = 0;
  float t2 = 0;
  /* USER CODE END 1 */
.......


 while (1)
  {
    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */
    t1 += 0.1;
        t2 += 0.5;
    printf("simples:%f, %f
", sin(t1), sin(t2));     
    HAL_Delay(100);  
  }
  /* USER CODE END 3 */
}

1、选择串口通讯、端口号、波特率等参数设置;

3ccafcc4-90dd-11ef-a511-92fbcf53809c.png

2、去控件中选择波形图,拉入tab中,右键选择Y轴将2个输入I0与I1都选中,之后开启串口连接;

3cf31c72-90dd-11ef-a511-92fbcf53809c.png

3、运行上位机,使用波形图控件读取下位机参数;

3c464060-90dd-11ef-a511-92fbcf53809c.png

三、滤波算法与效果

受限于MCU自身的ADC外设缺陷,其精度和稳定性通常较差,很多场景下需要采取滤波补偿。

滤波的作用就是减少噪声与干扰对数据测量的影响。

3.1、不添加滤波算法采样

直接采集3.3V的电压:

VOFA+读取到的数据:

3d0e4a56-90dd-11ef-a511-92fbcf53809c.png

上图借助VOFA+上位机可以清楚看出未使用滤波的ADC采样波动还是比较明显的,但是作者主观干啥F1系列的ADC确实好像比F4系列的ADC稳定些。(之所以不是4096可能是因为电源未达到3.3v)

四、滤波算法

4.1、一阶互补滤波

方法:取a=0~1,本次滤波结果=(1-a)本次采样值+a上次滤波结果

优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合

缺点:相位滞后,灵敏度低滞后程度取决于a值大小不能消除滤波频率高于采样频率的1/2的干扰信号

代码如下:

//一阶互补滤波
int firstOrderFilter(int newValue, int oldValue, float a)
{
    return a * newValue + (1-a) * oldValue;
}




ADC_value=HAL_ADC_GetValue(&hadc1);//获取ADC1的数值


//主函数
while(1){
    HAL_ADC_Start(&hadc1);            //开启ADC1,放置在while循环中
    Filtering_Value = firstOrderFilter(HAL_ADC_GetValue(&hadc1),ADC_value,0.3);    //滤波算法
    HAL_Delay(10);                //延迟函数,防止采样失效
    printf("ADC_value:%d
", ADC_value);
}

VOFA+软件的效果图:

3d35c19e-90dd-11ef-a511-92fbcf53809c.png

结论:

一阶互补滤波的局限性还是很大的,效果非常一般。

4.2、中位值滤波

方法:连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值

优点:能有效克服因偶然因素引起的波动干扰;对温度、液位等变化缓慢的被测参数有良好的滤波效果

缺点:对流量,速度等快速变化的参数不宜

代码如下:

//中值滤波算法
int middleValueFilter(int N)
{
      int value_buf[N];
      int i,j,k,temp;
      for( i = 0; i < N; ++i)
      {
        value_buf[i] = HAL_ADC_GetValue(&hadc1);  


      }


      for(j = 0 ; j < N-1; ++j)
      {
          for(k = 0; k < N-j-1; ++k)
          {
              //从小到大排序,冒泡法排序
              if(value_buf[k] > value_buf[k+1])
              {
                temp = value_buf[k];
                value_buf[k] = value_buf[k+1];
                value_buf[k+1] = temp;
              }
          }
      }


      return value_buf[(N-1)/2];
}

VOFA+软件的效果图:

3d4cd960-90dd-11ef-a511-92fbcf53809c.png

结论如下:

中值滤波对消除异常值和平稳化AD采样都具有十分有效的结果。

4.3、算术平均滤波

方法:连续取N个采样值进行算术平均运算;

N值较大时:信号平滑度较高,但灵敏度较低

N值较小时:信号平滑度较低,但灵敏度较高

N值的选取:一般流量,N=12;压力:N=4

优点:试用于对一般具有随机干扰的信号进行滤波。这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。

缺点:测量速度较慢或要求数据计算较快的实时控制不适用。

代码:

//算术平均值滤波
int averageFilter(int N)
{
     int sum = 0;
     short i;
     for(i = 0; i < N; ++i)
     {
        sum += HAL_ADC_GetValue(&hadc1);  
     }
     return sum/N;
}

VOFA+软件的效果图:

3d6e3fec-90dd-11ef-a511-92fbcf53809c.png

结论:

算术平均滤波表现出了一定的平稳性,同时具有波动的伴随性(合理选择N值可能达到很好的效果)。

4.4、滑动平均滤波

方法:把连续取N个采样值看成一个队列,队列的长度固定为N。每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则)。把队列中的N个数据进行算术平均运算,就可获得新的滤波结果。

N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4

优点:对周期性干扰有良好的抑制作用,平滑度高;试用于高频振荡的系统

缺点:灵敏度低;对偶然出现的脉冲性干扰的抑制作用较差,不适于脉冲干扰较严重的场合

比较浪费RAM(改进方法,减去的不是队首的值,而是上一次得到的平均值)

代码:

//平滑均值滤波
#define N 10
int value_buf[N];
int sum=0;
int curNum=0;


intmoveAverageFilter()
{
      if(curNum < N)
      {
          value_buf[curNum] = HAL_ADC_GetValue(&hadc1);
          sum += value_buf[curNum];
          curNum++;
          return sum/curNum;
      }
      else
      {
          sum -= sum/N;
          sum += HAL_ADC_GetValue(&hadc1);
          return sum/N;
      }
}

VOFA+软件的效果图:

3d99a20e-90dd-11ef-a511-92fbcf53809c.png

结论:

平滑均值滤波相较于普通的算术平均滤波,突出一个平滑特性。

可以从上述VOFA+的波形图看出,平滑滤波可以有效抵消AD采样的刺噪并稳定化采集(据作者同门实战反应平滑滤波的效果还是非常好的,尤其在控制方面)。

4.5、限幅平均滤波

方法:相当于“限幅滤波法”+“递推平均滤波法”

每次采样到的新数据先进行限幅处理再送入队列进行递推平均滤波处理

优点:对于偶然出现的脉冲性干扰,可消除有其引起的采样值偏差。

缺点:比较浪费RAM

代码如下:

//限幅平均滤波
#define A 50        //限制幅度阈值
#define M 12
int data[M];
int First_flag=0;


intLAverageFilter()
{
    int i;
    int temp,sum,flag=0;
    data[0] = HAL_ADC_GetValue(&hadc1);
    for(i=1;iA || ((data[i-1]-temp)>A))
      {
          i--;
          flag++;
      }
      else
      {
          data[i]=temp;
      }
    }


    for(i=0;i

VOFA+软件的效果图:

3c5c841a-90dd-11ef-a511-92fbcf53809c.png

结论:

限幅平均滤波类似于缝合怪,但是效果是非常显著的,它有效的解决了实际场景下突变噪声对AD采样的影响,但是消耗内存。

4.6、卡尔曼滤波

核心思想:根据当前的仪器"测量值" 和上一刻的 “预测量” 和 “误差”,计算得到当前的最优量,再预测下一刻的量。里面比较突出的是观点是:把误差纳入计算,而且分为预测误差和测量误差两种,通称为噪声。还有一个非常大的特点是:误差独立存在,始终不受测量数据的影响。

优点:巧妙的融合了观测数据与估计数据,对误差进行闭环管理,将误差限定在一定范围。适用性范围很广,时效性和效果都很优秀。

缺点:需要调参,参数的大小对滤波的效果影响较大。

代码如下:

//卡尔曼滤波
int KalmanFilter(int inData)
{
      static float prevData = 0;                                 //先前数值
      static float p = 10, q = 0.001, r = 0.001, kGain = 0;      // q控制误差  r控制响应速度 


      p = p + q;
      kGain = p / ( p + r );                                     //计算卡尔曼增益
      inData = prevData + ( kGain * ( inData - prevData ) );     //计算本次滤波估计值
      p = ( 1 - kGain ) * p;                                     //更新测量方差
      prevData = inData;
      return inData;                                             //返回滤波值
}

VOFA+软件的效果图:

3dcc9966-90dd-11ef-a511-92fbcf53809c.png

结论:

VOFA+显示的波形图开源看出卡尔曼滤波有一定的去噪稳定特性的,虽然效果不是特别优秀。

卡尔曼滤波的普适性很强,尤其在控制与多传感器融合方向,只要参数调整的好,效果出奇优秀。

五、实验总结

ADC作为嵌入式开发过程中必须掌握的外设,往往项目中是需要设置滤波器的。RC硬件滤波效果一般的话,可以用软件来凑。同时滤波算法各式各样,原理也各不相同,希望读者朋友在实际的工程项目中,不要盲目的追求各种牛逼的滤波算法,其实适合该工程的滤波就是好滤波。

来源:https://blog.csdn.net/black_sneak/article/details/129629485

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6027

    文章

    44463

    浏览量

    631311
  • adc
    adc
    +关注

    关注

    97

    文章

    6355

    浏览量

    543496
  • STM32
    +关注

    关注

    2263

    文章

    10850

    浏览量

    353971
  • 模数转换器
    +关注

    关注

    26

    文章

    3069

    浏览量

    126679
  • 滤波算法
    +关注

    关注

    2

    文章

    88

    浏览量

    13705

原文标题:STM32的ADC采样及各式滤波实现(HAL库,含VOFA+教程)

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    STM32ADC项目应用,用什么算法滤波和稳定数据抖动?

    STM32ADC项目应用,大家都用什么算法滤波和稳定数据抖动。 ADC数据的抖动有时候应用在项目上让人很是头疼,什么度娘十大
    发表于 04-17 08:20

    单片机采样ADC数值一般都是用的什么滤波算法

    单片机采样ADC数值一般都是用的什么滤波算法
    发表于 10-16 06:26

    STM32F30x 的ADC 采样的傅立叶变换

    STM32F30x 的ADC 采样的傅立叶变换
    发表于 12-07 18:16 58次下载

    STM32F30x 的ADC 采样的傅立叶变换

    STM32F30x 的ADC 采样的傅立叶变换
    发表于 12-07 18:16 0次下载

    基于重采样技术改进的粒子滤波算法

    基于重采样技术改进的粒子滤波算法_李小婷
    发表于 01-07 20:49 1次下载

    STM32的多个ADC模块如何同时采样转换详细应用实例说明

    同时工作,比方3个ADC模块同时采样转换。这时如果芯片内含有3个ADC模块,并支持同时采样转换就很方便。比方STM32F4系列、
    的头像 发表于 06-30 10:40 3.4w次阅读
    <b class='flag-5'>STM32</b>的多个<b class='flag-5'>ADC</b>模块如何同时<b class='flag-5'>采样</b>转换详细应用实例说明

    STM32F30x 的ADC 采样的傅立叶变换

    STM32F30x 的ADC 采样的傅立叶变换(理士国际电源技术有限公司)-本文目的是演示如何使用STM32F30x 内部的DSP 进行浮点快速傅立叶变换(FFT),为联系实际应用,使
    发表于 08-04 17:47 71次下载
    <b class='flag-5'>STM32</b>F30x 的<b class='flag-5'>ADC</b> <b class='flag-5'>采样</b>的傅立叶变换

    解决STM32单片机的ADC采样不准确偏移的问题

    项目场景:用STM32CubeMX生成的ADC采样测量电压。单片机:STM32G070MDK:V5.25问题描述:采样回来的数值Debug看
    发表于 11-16 20:36 19次下载
    解决<b class='flag-5'>STM32</b>单片机的<b class='flag-5'>ADC</b><b class='flag-5'>采样</b>不准确偏移的问题

    STM32: ADC采样频率及相应时间的确定

    STM32: ADC采样频率及相应时间的确定
    发表于 11-26 20:36 19次下载
    <b class='flag-5'>STM32</b>: <b class='flag-5'>ADC</b><b class='flag-5'>采样</b>频率及相应时间的确定

    STM32自带AD采样滤波方法

    STM32自带AD采样滤波方法本方法实测有效,可以提高转换精度。数据采集滤波求平均值的方法也可以用于其他专业AD转换芯片。如果转换要求高精度,必须注意REF参考源电压的稳定性。uint
    发表于 12-02 17:51 26次下载
    <b class='flag-5'>STM32</b>自带AD<b class='flag-5'>采样</b><b class='flag-5'>滤波</b>方法

    STM32 ADC采样技术

    STM32 ADC采样技术
    发表于 12-08 16:21 43次下载
    <b class='flag-5'>STM32</b> <b class='flag-5'>ADC</b> 过<b class='flag-5'>采样</b>技术

    STM32ADC多通道采样

    基于STM32Cube的ADC多通道采样STMCube+MDK用hal库写的好处就是可以不用进行配置IO口发步骤.也有良好的兼容性,更换芯片的时候改代码也简单.首先打开STM32Cub
    发表于 12-24 19:29 15次下载
    <b class='flag-5'>STM32</b>的<b class='flag-5'>ADC</b>多通道<b class='flag-5'>采样</b>

    AN2668_通过过采样来提高STM32ADC精度

    AN2668_通过过采样来提高STM32ADC精度
    发表于 11-21 17:06 10次下载
    AN2668_通过过<b class='flag-5'>采样</b>来提高<b class='flag-5'>STM32</b>的<b class='flag-5'>ADC</b>精度

    STM32的12位ADC采样实现16位分辨率

    采样技术是一种以牺牲采样速度来提高ADC分辨率的技术。部分STM32单片机是支持硬件过采样的,如STM
    的头像 发表于 10-12 10:19 7659次阅读
    <b class='flag-5'>STM32</b>的12位<b class='flag-5'>ADC</b>过<b class='flag-5'>采样</b><b class='flag-5'>实现</b>16位分辨率

    常用的ADC滤波算法有哪些

    ADC(模数转换器)滤波算法在信号处理中起着至关重要的作用,它们能够帮助我们提取出有用的信号,同时滤除噪声和干扰。以下是常用的ADC滤波
    的头像 发表于 10-08 14:35 164次阅读