基于STM32的ADC采样及各式滤波实现(HAL库,含VOFA+教程)

news2024/11/20 20:18:08

        前言:本文为手把手教学ADC采样各式滤波算法的教程,本教程的MCU采用STM32F103ZET6。以HAL库ADC采样函数为基础进行教学,通过各式常见滤波的实验结果进行分析对比,搭配VOFA+工具直观的展示滤波效果。ADC滤波算法都是嵌入式较为常见的,希望这篇博文能给读者朋友的工程项目给予些许帮助。(文末代码开源!

      实验硬件:STM32F103ZET6;

实验效果图:

一、ADC采样

1.1 ADC简介

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

ADCAnalog 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 性能的另一个重要指标(详细参考信号处理方向书籍)。

总之,只要是需要模拟信号转为数字信号的场合,那么肯定要用到 ADC。很多数字传感器内部会集成 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 个通道组:规则通道组注入通道组。规则通道相当于正常运行的程序,而注入通道呢,就相当于中断打断式通道选择。在程序正常执行的时候,中断是可以打断程序执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。

关于 ADC 的模式配置可选择性很高,一般无需太多了解,详情可以参考《STM32 参考手册的》第 155 页,第 11 章。

二、VOFA+教学

2.1 VOFA+简介

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

VOFA+特点概览:

平台支持:Windows、Linux、MacOS;
接口支持:串口(超高波特率,稳定支持)、网口(TCP客户端/服务端,UDP);
协议支持:协议为插件,已开源,人人可编写。目前已支持CSV风格的字符串协议,和十六进制浮点数组形式的字节流协议;
控件支持:控件为插件,已开源,人人可编写。目前已支持波形图、按钮、状态灯、图片、滑动条、3D立方控件(可更换模型)等;
数据维度自由化:2维度与3维,一个也不能拉下;
自主研发的波形控件:支持每通道百万采样点的绘制,性能强劲;
自主研发的波形控件:无缝嵌入了实时直方统计和点数可设置的傅里叶变换,可以使用VOFA+进行数据分析。

Vofa+网址:VOFA+ | VOFA+

2.2 VOFA+使用方法

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

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

将鼠标放到FireWater协议上,可以很贴心的得到使用格式帮助。如上图所示,我们使用printf("simples:%f, %f\n", 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\n", sin(t1), sin(t2)); 		
		HAL_Delay(100);  
  }
  /* USER CODE END 3 */
}

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

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

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

补充:

不难看出VOFA+的使用是非常简单快捷的,其自由度也是相当的高,关键还是免费的PID调参无人机的姿态3D显示等等都可以借助VOFA+实现, 希望该软件可以给读者朋友的日常嵌入式开发提供便捷与帮助。

三、CubeMX配置

1、RCC配置外部高速晶振(精度更高)——HSE;

2、SYS配置:Debug设置成Serial Wire否则可能导致芯片自锁);

3、UART1配置:使用串口通讯UART1与VOFA+上位机进行通讯显示;

4、ADC1配置:利用ADC1的通道IN1进行AD采样,保持独立模式;

5、时钟树配置:

6、工程配置:

四、滤波算法与效果

受限于MCU自身的ADC外设缺陷,其精度和稳定性通常较差,很多场景下需要采取滤波补偿。
滤波的作用就是减少噪声与干扰对数据测量的影响。

4.1 未添加滤波算法

重写printf函数:

#include "stdio.h"
//重定义
int fputc(int c,FILE *stream)
{
	uint8_t ch[1]={c};
	HAL_UART_Transmit(&huart1,ch,1,0xFFFF);
	return c;
}

main函数: 

while(1){	
    HAL_ADC_Start(&hadc1);						//开启ADC1,放置在while循环中
	ADC_value=HAL_ADC_GetValue(&hadc1);			//获取ADC1的数值
	HAL_Delay(10);								//延迟函数,防止采样失效
	printf("ADC_value:%d\n", ADC_value);
}

VOFA+读取到的数据:

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

4.2 一阶互补滤波

方法:取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\n", ADC_value);
}

VOFA+软件的效果图:

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

4.3 中位值滤波

方法:连续采样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+软件的效果图:

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

4.4 算术平均滤波

方法:连续取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+软件的效果图:

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

4.5 滑动平均滤波

方法:把连续取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;
int moveAverageFilter()
{
    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+软件的效果图:

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

4.6 限幅平均滤波

方法:相当于“限幅滤波法”+“递推平均滤波法”
每次采样到的新数据先进行限幅处理再送入队列进行递推平均滤波处理
优点:对于偶然出现的脉冲性干扰,可消除有其引起的采样值偏差。
缺点:比较浪费RAM

//限幅平均滤波
#define A 50        //限制幅度阈值
#define M 12
int data[M];
int First_flag=0;
int LAverageFilter()
{
  int i;
  int temp,sum,flag=0;
  data[0]=HAL_ADC_GetValue(&hadc1);
	for(i=1;i<M;i++)
	{
		temp=HAL_ADC_GetValue(&hadc1);
		if((temp-data[i-1])>A||((data[i-1]-temp)>A))
		{
		  i--;flag++;
		}
		else
		{
			data[i]=temp;
		}
	}
  for(i=0;i<M;i++)
  {
    sum+=data[i];
  } 
  return  sum/M;
}

VOFA+软件的效果图:

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

4.7 卡尔曼滤波 

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

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

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

//卡尔曼滤波
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+软件的效果图:

作者本人是非常喜欢卡尔曼滤波的,VOFA+显示的波形图开源看出卡尔曼滤波有一定的去噪稳定特性的,虽然效果不是特别优秀。卡尔曼滤波的普适性很强,尤其在控制与多传感器融合方向,只要参数调整的好,效果出奇优秀。

五、实验总结

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

六、代码开源

代码地址: 基于STM32的ADC采样及各式滤波实现(HAL库)-嵌入式文档类资源-CSDN文库

如果积分不够的朋友点波关注评论区留下邮箱,作者无偿提供源码和后续问题解答。求求啦关注一波吧 !!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/591074.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL进阶- Linux安装 和 索引

目录 Linux安装索引索引的概述索引的结构索引结构的介绍BtreeBtreeHash 索引的分类索引的语法&#xff08;创建&#xff0c;查看&#xff0c;删除等&#xff09;SQL性能分析SQL的执行频率&#xff08;查看SQL的执行频率&#xff09;慢查询日志show profilesexplain执行计划 索引…

video标签学习 xgplayer视频播放器分段播放mp4

文章目录 学习链接目标video标签自带视频和制作的视频区别video标签的src属性本地视频文件前端代码播放效果 服务器视频文件示例1后端代码前端代码播放效果 示例2后端代码前端代码播放效果 示例3后端配置前端代码播放效果 video对象video对象创建和获取video的属性video的方法v…

chatgpt赋能python:Python模块安装方法全解析

Python模块安装方法全解析 Python是一种功能强大的编程语言&#xff0c;拥有大量的开源库&#xff0c;这些库是在各种应用程序中使用的重要组件&#xff0c;它们能加速开发过程。不管你是初学者、中级者还是高级者&#xff0c;总会遇到需要安装第三方库的情况。但是安装库是一…

《Java并发编程实战》课程笔记(四)

互斥锁 原子性问题到底该如何解决呢&#xff1f; “同一时刻只有一个线程执行”这个条件非常重要&#xff0c;我们称之为互斥。如果我们能够保证对共享变量的修改是互斥的&#xff0c;那么&#xff0c;无论是单核 CPU 还是多核 CPU&#xff0c;就都能保证原子性了。 锁模型 …

Python连接达梦数据库

python如果想连接达梦数据库&#xff0c;必须要安装dmPython。 简介&#xff1a;dmPython 是 DM 提供的依据 Python DB API version 2.0 中 API 使用规定而开发的数据库访问接口。dmPython 实现这些 API&#xff0c;使 Python 应用程序能够对 DM 数据库进行访问。 dmPython 通…

数据库服务器

数据库服务器&#xff0c;联系Web服务器与DBMS的中间件是负责处理所有的应用程序服务器&#xff0c;包括在web服务器和后台的应用程序或数据库之间的事务处理和数据访问。 基本信息 中文名 数据库服务器 外文名 database server 功能 数据库服务器建立在数据库系统基础上&a…

系统漏洞利用与提权

任务二&#xff1a;系统漏洞利用与提权 任务环境说明&#xff1a; 服务器场景&#xff1a;PYsystem0033 服务器场景操作系统&#xff1a;Ubuntu 服务器场景用户名:未知 密码&#xff1a;未知 1.使用nmap扫描靶机系统&#xff0c;将靶机开放的端口号按从小到大的顺序作为F…

解决Vmware上的kali找不到virtualbox上的靶机的问题

解决kali找不到靶场ip问题的完整方法 1.配置靶机2.配置kali的虚拟网络3.配置kali中的eth0网络 1.配置靶机 靶机部署在Virtualbox上对其进行网络配置&#xff0c;选择连接方式为仅主机&#xff08;Host-Only&#xff09;网络。 2.配置kali的虚拟网络 在编辑中选择虚拟网络配…

chatgpt赋能python:Python中浮点数的表示方法

Python中浮点数的表示方法 在Python中&#xff0c;浮点数是一种数字类型&#xff0c;用于表示带有小数点的数值。但是&#xff0c;由于计算机在表示浮点数时存在精度限制&#xff0c;因此需要特别注意。本文将介绍Python中浮点数的表示方法及其可能导致的错误。 Python中浮点…

陕西发布!陕西省重点实验室申报条件类别、认定程序要求

本文整理了陕西省重点实验室申报条件&#xff0c;认定材料等相关内容&#xff0c;感兴趣的朋友快跟小编一起来看看吧&#xff01; 一、总体思路 本次省重点实验室布局建设工作以填补我省优势学科领域下无省级及以上科学与工程研究类科技创新基地的空白为主,同时兼顾前沿、新兴、…

MySQL基础- 多表查询 和 事务

目录 多表查询多表关系多表查询概述多表查询的分类内连接外连接自连接联合查询union&#xff0c;union all子查询标量子查询列子查询行子查询表子查询 综合练习小结 事务事务简介事务的操作四大特性ACID并发事务问题事务的隔离级别小结 多表查询 之前的SQL语句里的DQL只能进行…

数字图像学笔记 —— 18. 图像抖动算法

文章目录 为什么需要图像抖动图像抖动算法实现的基本思路常见图像抖动算法实现Floyd-Steinberg 抖动算法Atkinson 抖动算法算法实现 为什么需要图像抖动 在数字图像中&#xff0c;为了表示数字图像的细节&#xff0c;像素的颜色深度信息最少也是8位&#xff0c;即 0 − 256 0…

Linux:centos:周期性计划任务管理《crontab》

crontab常用基础属性 -e 编辑计划任务 -l 查看计划任务 -r 删除计划任务 -u 指定用户的计划任务 首先创建一个名为test的用户名 crontab时间规定 格式&#xff1a;分钟 小时 日期 月份 星期 命令 分钟-- 0-59整数 小时 -- 0-23整数 日期 -- 1--31 整数 月份 -- 1-12 整数 星期…

C++ queue类成员介绍

目录 &#x1f914;queue模板介绍&#xff1a; &#x1f914;queue特点&#xff1a; &#x1f914;queue内存图解&#xff1a; &#x1f914; queue的成员函数 &#x1f50d;queue构造函数&#xff1a; &#x1f50d;queue赋值函数&#xff1a; &#x1f50d;queue判断函…

黑马Redis视频教程实战篇(三)

目录 一、优惠券秒杀 1.1 全局唯一ID 1.2 Redis实现全局唯一ID 1.3 添加优惠卷 1.4 实现秒杀下单 1.5 库存超卖问题分析 1.6 代码实现乐观锁解决超卖问题 1.7 优惠券秒杀-一人一单 1.8 集群环境下的并发问题 二、分布式锁 2.1 基本原理和实现方式对比 2.2 Redis分布…

js常见面试笔试题

一.js实现距离最近的回文数 给定一个整数 n &#xff0c;你需要找到与它最近的回文数&#xff08;不包括自身&#xff09;。 “最近的”定义为两个整数差的绝对值最小。 示例 1: 输入: "123" 输出: "121" function findNearestPalindrome…

Jenkins+Python自动化测试之持续集成详细教程

前言 今天呢笔者想和大家来聊聊JenkinsPython自动化测试持续集成&#xff0c;废话呢就不多说了哟咱们直接进入主题哟。 一、Jenkins安装 ​ Jenkins是一个开源的软件项目&#xff0c;是基于java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供…

I.MX RT1170加密启动详解(2):Authenticated HAB认证原理

文章目录 1 基础2 使能过程3 Boot flow 1 基础 HAB认证是基于RSA或ECDSA算法的公钥密码学&#xff0c;它用一系列的私钥对image进行加密&#xff0c;然后BootROM在上电后用对应的公钥验证加密的镜像是否被修改。这个密钥结构就是PKI(Public Key Infrastructure)树 (1)normal …

chatgpt赋能python:Python中画笔颜色的函数介绍

Python中画笔颜色的函数介绍 在Python中&#xff0c;我们可以使用turtle模块来绘制图形&#xff0c;其中画笔颜色是非常重要的一部分。画笔颜色可以决定图形的风格和色调&#xff0c;是图形表现的关键因素之一。Python中提供了几种方法来设置画笔颜色。 1. 设置画笔颜色的函数…

ENU、EPSG坐标系科普(三维重建)

ENU和EPSG实际上代表了两个不同的概念&#xff0c;这两者并不是直接对比的。 1. ENU坐标系&#xff1a;ENU坐标系是一种本地切面坐标系&#xff0c;用于表示与地理位置相关的空间数据。在ENU坐标系中&#xff0c;E代表东&#xff08;East&#xff09;&#xff0c;N代表北&…