云南俊发建设集团网站,新能源电动汽车哪个牌子的质量好,制作自己的个人网站,网络组建拓扑图前言#xff1a;本文为手把手教学ADC采样及各式滤波算法的教程#xff0c;本教程的MCU采用STM32F103ZET6。以HAL库的ADC采样函数为基础进行教学#xff0c;通过各式常见滤波的实验结果进行分析对比#xff0c;搭配VOFA工具直观的展示滤波效果。ADC与滤波算法都是嵌入式较为… 前言本文为手把手教学ADC采样及各式滤波算法的教程本教程的MCU采用STM32F103ZET6。以HAL库的ADC采样函数为基础进行教学通过各式常见滤波的实验结果进行分析对比搭配VOFA工具直观的展示滤波效果。ADC与滤波算法都是嵌入式较为常见的希望这篇博文能给读者朋友的工程项目给予些许帮助。文末代码开源 实验硬件STM32F103ZET6
实验效果图 一、ADC采样
1.1 ADC简介
单片机是数字芯片只认识由0和1组成的逻辑序列。但实际情况下生活中还有许多非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/40960.00122V。很明显分辨率越高采集到的信号越精确所以分辨率是衡量 ADC 的一个重要指标。 3采样时间当 ADC 在某时刻采集外部电压信号的时候此时外部的信号应该保持不变但实际上外部的信号是不停变化的。所以在 ADC 内部有一个保持电路保持某一时刻的外部信号这样 ADC 就可以稳定采集了保持这个信号的时间就是采样时间。 4采样率也就是在一秒的时间内采集多少次。很明显采样率越高越好当采样率不够的时候可能会丢失部分信息所以 ADC 采样率是衡量 ADC 性能的另一个重要指标详细参考信号处理方向书籍。 总之只要是需要模拟信号转为数字信号的场合那么肯定要用到 ADC。很多数字传感器内部会集成 ADC传感器内部使用 ADC 来处理原始的模拟信号最终给用户输出数字信号。
1.2 STM32的ADC
STM32 拥有 1~3 个 ADCSTM32F101/102 系列只有 1 个 ADCSTM32F103系列则有3个ADC和1个DAC这些 ADC 可以独立使用也可以使用双重模式提高采样率。STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。它有 18 个通道可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 特别说明 ADC 是12位逐次逼近型模数转换器输出数值范围是 0 ~ 2^12 -10 ~ 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_valueHAL_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 一阶互补滤波 方法取a0~1,本次滤波结果1-a本次采样值a上次滤波结果 优点对周期性干扰具有良好的抑制作用适用于波动频率较高的场合 缺点相位滞后灵敏度低滞后程度取决于a值大小不能消除滤波频率高于采样频率的1/2的干扰信号 //一阶互补滤波
int firstOrderFilter(int newValue, int oldValue, float a)
{return a * newValue (1-a) * oldValue;
}ADC_valueHAL_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[k1]){temp value_buf[k];value_buf[k] value_buf[k1];value_buf[k1] temp;}}}return value_buf[(N-1)/2];
}
VOFA软件的效果图 中值滤波对消除异常值和平稳化AD采样都具有十分有效的结果。 4.4 算术平均滤波 方法连续取N个采样值进行算术平均运算; N值较大时信号平滑度较高但灵敏度较低 N值较小时信号平滑度较低但灵敏度较高 N值的选取一般流量N12压力N4 优点试用于对一般具有随机干扰的信号进行滤波。这种信号的特点是有一个平均值信号在某一数值范围附近上下波动。 缺点测量速度较慢或要求数据计算较快的实时控制不适用。 //算术平均值滤波
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值的选取流量N12压力N4液面N4~12温度N1~4 优点对周期性干扰有良好的抑制作用平滑度高试用于高频振荡的系统 缺点灵敏度低对偶然出现的脉冲性干扰的抑制作用较差不适于脉冲干扰较严重的场合 比较浪费RAM改进方法减去的不是队首的值而是上一次得到的平均值 //平滑均值滤波
#define N 10
int value_buf[N];
int sum0;
int curNum0;
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_flag0;
int LAverageFilter()
{int i;int temp,sum,flag0;data[0]HAL_ADC_GetValue(hadc1);for(i1;iM;i){tempHAL_ADC_GetValue(hadc1);if((temp-data[i-1])A||((data[i-1]-temp)A)){i--;flag;}else{data[i]temp;}}for(i0;iM;i){sumdata[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文库
如果积分不够的朋友点波关注评论区留下邮箱作者无偿提供源码和后续问题解答。求求啦关注一波吧