【宝藏系列】模/数转换十大常用滤波算法

【宝藏系列】模/数转换十大常用滤波算法


在这里插入图片描述

文章目录

    • 【宝藏系列】模/数转换十大常用滤波算法
    • 👨‍🏫ADC(Analog-to-Digital Converter,模数转换器)
    • 1️⃣限幅滤波法
    • 2️⃣中位值滤波法
    • 3️⃣算术平均滤波法
    • 4️⃣递推平均滤波法
    • 5️⃣中位值平均滤波法
    • 6️⃣限幅平均滤波法
    • 7️⃣一阶滞后滤波法
    • 8️⃣加权递推平均滤波法
    • 9️⃣消抖滤波法
    • 1️⃣0️⃣限幅消抖滤波法


👨‍🏫ADC(Analog-to-Digital Converter,模数转换器)


ADC,即模拟数字转换器(Analog-to-Digital Converter),是一种电子设备,它可以将模拟信号转换为数字信号。这种转换对于数字电路处理模拟信号至关重要,因为数字电路无法直接处理模拟信号。以下是ADC的一些基本特性和工作原理:

工作原理:

采样:ADC在特定的时间间隔内对模拟信号进行采样,即测量信号在这些时间点的瞬时值。
量化:将采样得到的连续幅度值映射到有限数量的状态。这个过程涉及到将连续的信号幅度划分为离散的级别。
编码:将量化后的值转换为数字代码,通常是二进制形式,以便数字系统可以处理。

类型:

逐次逼近型ADC(Successive Approximation ADC):通过逐次逼近的方式确定模拟信号的数字值,具有较快的转换速度。
并行ADC(Parallel or Flash ADC):同时比较所有可能的量化级别,转换速度非常快,但成本和复杂性随着分辨率的增加而增加。
积分型ADC:通过积分模拟信号与参考电压的差异,然后通过计数器测量所需的时间来确定数字值。
Δ-Σ(Delta-Sigma)ADC:使用噪声整形技术,通过过采样和数字滤波来提高分辨率和信噪比。

性能参数:

分辨率:ADC能够区分的最小信号变化,通常以位(bit)来衡量,例如12位ADC可以提供2^12(4096)个量化级别。
采样率:ADC每秒可以采样的次数,单位是赫兹(Hz)。
精度:转换结果与真实模拟信号值之间的差异。
信噪比(SNR):信号功率与背景噪声功率的比值,通常用来衡量ADC的性能。
输入范围:ADC能够处理的模拟信号的最大和最小幅度。

应用领域:

音频处理:将模拟声音信号转换为数字信号,以便进行存储、处理或传输。
图像处理:在数字相机中将光信号转换为数字图像数据。
数据采集系统:在科研和工业领域收集传感器数据。
控制系统:在自动化系统中转换传感器信号,用于控制和监测。

🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

1️⃣限幅滤波法


限幅滤波法(Amplitude Limiting Filter),也称为程序判断滤波法,是一种简单的数字滤波技术,主要用于消除模拟信号中的脉冲噪声或异常值。以下是限幅滤波法的基本原理和实现方法:

基本原理:

限幅滤波法通过设定一个允许的最大偏差值(通常称为阈值或限幅值),来判断每次采样值是否有效。具体步骤如下:

  • 设定阈值:根据经验或系统要求,确定一个允许的最大偏差值。
  • 比较采样值:每次采样后,将新采样值与前一次采样值进行比较。
  • 判断有效性:如果新采样值与前一次采样值的差值小于或等于阈值,则认为新采样值有效;否则,认为新采样值无效,用前一次采样值代替。

实现方法:

根据经验判断两次采样允许的最大偏差值(设为A)
每次检测到新值时判断:

  • a. 如果本次值与上次值之差<=A,则本次值有效
  • b. 如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值
/* A值根据实际调,Value有效值,new_Value当前采样值,程序返回有效的实际值 */
#define A 10
char Value;
char filter()
{char new_Value;new_Value = get_ad(); // 获取采样值if( abs(new_Value - Value) > A)   return Value;     // abs()取绝对值函数return new_Value;
}

优点:

简单易实现:算法简单,容易在硬件或软件中实现。
有效抑制脉冲噪声:对于偶然出现的脉冲性干扰,能够有效地抑制其影响。

缺点:

无法抑制周期性干扰:对于周期性出现的干扰信号,限幅滤波法效果有限。
平滑度差:由于直接丢弃超出阈值的采样值,可能导致输出信号的平滑度较差。

应用场景:

限幅滤波法适用于那些需要快速响应且主要受到偶然性干扰影响的场合。例如:

  • 工业控制系统:在某些工业传感器信号处理中,可能会受到偶然的电磁干扰。
  • 医疗设备:在某些医疗监测设备中,需要快速响应并抑制偶然的信号干扰。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

2️⃣中位值滤波法


中位值滤波法是一种常用的数字滤波技术,主要用于去除数据集中的异常值或脉冲噪声,它通过选择一组数据中的中位数作为滤波结果,从而实现对信号的平滑处理。以下是中位值滤波法的基本原理和实现方法:

基本原理:

中位值滤波法的核心思想是从连续的采样数据中,去除极端值(最大值和最小值),然后取剩余数据的中位数作为滤波结果。这种方法对于去除偶然出现的脉冲干扰非常有效。

实现方法:

连续采样:设定一个采样次数N(通常是奇数),连续采集N个数据点。
数据排序:将采集到的数据按照大小进行排序。
选择中位数:排序后,选择位于中间位置的数据点作为中位数。
滤波输出:中位数即为本次滤波的输出结果。

#define N 5  // 采样次数,N为奇数int medianFilter(int *values) {int i, j, temp;// 复制数组以避免改变原始数据int sorted[N];for (i = 0; i < N; i++) {sorted[i] = values[i];}// 冒泡排序for (j = 0; j < N - 1; j++) {for (i = 0; i < N - j - 1; i++) {if (sorted[i] > sorted[i + 1]) {temp = sorted[i];sorted[i] = sorted[i + 1];sorted[i + 1] = temp;}}}// 返回中位数return sorted[(N - 1) / 2];
}// 使用方法:
// int values[N]; // 假设已经填充了采样值
// int filtered_value = medianFilter(values);

优点:

有效去噪:对于含有异常值或脉冲噪声的信号,中位值滤波法能有效去除这些干扰。
简单易实现:算法逻辑简单,容易在硬件或软件中实现。

缺点:

对快速变化敏感度低:由于中位值滤波法需要对一定数量的采样值进行排序,它对信号的快速变化响应较慢。
资源消耗:排序操作需要一定的计算资源,特别是在大数据集或高采样率的应用中。

应用场景:

中位值滤波法适用于那些信号中偶尔出现异常值,但整体变化趋势相对平稳的场景,例如:

  • 环境监测:在空气质量监测或水质监测中去除偶然的极端测量值。
  • 工业自动化:在传感器数据采集中去除由于干扰造成的异常读数。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

3️⃣算术平均滤波法


算术平均滤波法是一种基本且广泛使用的数字滤波技术,它通过对一定数量的连续采样值进行算术平均来平滑信号。以下是算术平均滤波法的基本原理和实现方法:

基本原理:

算术平均滤波法通过对连续N个采样点的模拟信号值进行平均,以减少随机噪声的影响。这种方法假设信号是平稳的,并且噪声是随机分布的。

实现方法:

初始化:设定一个采样次数N,初始化一个数组或队列来存储最近的N个采样值。
连续采样:连续采集N个数据点。
计算平均:将这N个数据点相加,然后除以N,得到平均值。
更新结果:将计算出的平均值作为滤波结果输出。
滑动更新:在下一次滤波时,移除最旧的采样值,加入新的采样值,并重新计算平均值。

#define N 5  // 采样次数int averageFilter(int *samples) {int sum = 0;for (int i = 0; i < N; i++) {sum += samples[i];}return sum / N;  // 计算平均值
}// 使用方法:
// int samples[N]; // 假设已经填充了采样值
// int filtered_value = averageFilter(samples);

优点:

简单易实现:算术平均滤波法的算法简单,容易在硬件或软件中实现。
平滑效果好:对于随机噪声,算术平均滤波法能有效平滑信号。

缺点:

时间延迟:由于需要采集一定数量的样本后才能计算平均值,因此存在一定的时间延迟。
对快速变化响应慢:对于信号的快速变化,算术平均滤波法可能无法及时响应。
资源消耗:如果采样次数N较大,可能需要较多的存储空间和计算时间。

应用场景:

算术平均滤波法适用于信号相对平稳,且主要受随机噪声影响的场景,例如:

  • 环境监测:在温度或湿度监测中平滑短时间内的波动。
  • 音频处理:在音频信号处理中减少背景噪声。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

4️⃣递推平均滤波法


递推平均滤波法(Recursive Averaging Filter),也称为滑动平均滤波法(Sliding Averaging Filter),是一种在数字信号处理中常用的滤波技术。它适用于需要实时处理信号的场景,因为它不需要存储所有采样值,而是只存储最近的N个采样值。以下是递推平均滤波法的基本原理和实现方法:

基本原理:

递推平均滤波法通过在每个新的采样点上更新平均值来实现滤波。这种方法使用一个固定大小的队列来存储最近的N个采样值,并在每个新采样到来时,移除最旧的采样值,加入新的采样值,并重新计算平均值。

实现方法:

初始化:设定一个采样次数N,初始化一个数组或队列来存储最近的N个采样值,并初始化一个变量来存储当前平均值。
第一个采样:当第一个采样到来时,将其作为初始平均值。
连续采样:对于每个新的采样点,执行以下操作:

  • 移除队列中最旧的采样值。
  • 将新的采样值添加到队列中。
  • 更新平均值:将新采样值加到当前平均值上,然后减去刚刚移除的采样值,并除以N。
  • 输出结果:每次更新后的平均值即为滤波输出。
#define N 5  // 采样次数
#define MAX_VALUE 1023  // 假设采样值的最大可能值int filter[N];  // 存储采样值的数组
int sum = 0;    // 存储采样值总和的变量
int head = 0;   // 队列头部索引float recursiveAverageFilter(int newSample) {// 移除最旧的采样值sum -= filter[head];// 添加新的采样值filter[head] = newSample;sum += newSample;// 更新队列头部索引,实现循环队列head = (head + 1) % N;// 计算并返回平均值return (float)sum / N;
}// 使用方法:
// int new_sample; // 假设这是新采集的样本值
// float filtered_value = recursiveAverageFilter(new_sample);

优点:

实时性好:适合实时信号处理,因为不需要等待所有采样完成。
计算效率:只需要存储最近的N个采样值,计算量相对较小。

缺点:

对快速变化响应慢:由于是平均值,可能无法快速响应信号的突变。
存储空间限制:虽然只需要存储N个值,但对于大数据集,N的选择可能受限于内存。

应用场景:

递推平均滤波法适用于需要连续处理数据并减少随机噪声的场景,例如:

  • 传感器数据平滑:在温度、压力等传感器信号处理中平滑噪声。
  • 音频信号处理:在音频信号中减少背景噪声。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

5️⃣中位值平均滤波法


中位值平均滤波法(Median Averaging Filter),有时也称为防脉冲干扰平均滤波法,是一种结合了中位值滤波和算术平均滤波思想的数字滤波技术。它旨在通过去除数据集中的极值(最大值和最小值),然后对剩余的数据进行平均,以减少脉冲噪声或异常值的影响。以下是中位值平均滤波法的基本原理和实现方法:

基本原理:

连续采样:首先,从信号中连续采集N个数据点,其中N通常选择为大于2的奇数,以确保中位数的存在。
排序:将采集到的N个数据点按照大小进行排序。
去除极值:从排序后的数据中去除一个最大值和一个最小值。如果去除的极值相同,则只去除一个。
计算平均:对剩余的N-2个数据点进行算术平均,得到滤波结果。

实现方法:

初始化一个数组来存储最近的N个采样值。
每当有新的采样值到来时,将该值加入数组,并移除最早采集的值(先进先出)。
对数组中的N个值进行排序。
去除排序后的第一个元素(最小值)和最后一个元素(最大值)。
对剩余的N-2个元素计算算术平均值。

#define N 5  // 采样次数,N为奇数void sortArray(int *arr, int size) {int i, j, temp;for (i = 0; i < size - 1; i++) {for (j = 0; j < size - i - 1; j++) {if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}int medianAveragingFilter(int newSample, int *samples) {static int sum = 0;  // 用于存储剩余元素的总和int i, temp, medianAverage = 0;// 移除最旧的样本,并添加新的样本samples[N-1] = newSample;// 计算总和并更新sum -= samples[0] + samples[N-2];sum += newSample + samples[N-1];// 排序数组sortArray(samples, N);// 去除极值for (i = 1; i < N - 1; i++) {medianAverage += samples[i];}// 计算平均值return medianAverage / (N - 2);
}// 使用方法:
// int samples[N]; // 假设samples数组已经初始化
// int new_sample; // 假设这是新采集的样本值
// int filtered_value = medianAveragingFilter(new_sample, samples);

优点:

有效去噪:通过去除极值,能有效减少脉冲噪声或异常值的影响。
平滑效果:对剩余数据进行平均,进一步平滑信号。

缺点:

计算复杂度:需要对数据进行排序,计算复杂度较高。
资源消耗:排序操作需要较多的计算资源,尤其是在大数据集或高采样率的应用中。

应用场景:

中位值平均滤波法适用于那些信号中偶尔出现异常值,但整体变化趋势相对平稳的场景,例如:

  • 环境监测:在空气质量监测或水质监测中去除偶然的极端测量值。
  • 工业自动化:在传感器数据采集中去除由于干扰造成的异常读数。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

6️⃣限幅平均滤波法


限幅平均滤波法(Clamping or Limiting Averaging Filter)是一种结合了限幅滤波和算术平均滤波的数字滤波技术。它旨在通过限制采样值在一个合理的范围内,并在此基础上计算平均值,以减少异常值或突变噪声的影响。以下是限幅平均滤波法的基本原理和实现方法:

基本原理:

限幅平均滤波法通过以下步骤实现滤波:

  • 限幅:为每次采样设定一个最大值和最小值(限幅值),如果采样值超出这个范围,则将其限制在范围内。
  • 平均:在限幅后的采样值基础上,计算这些值的算术平均。

实现方法:

初始化一个数组来存储最近的N个采样值,以及两个变量来存储最大值和最小值。
每当有新的采样值到来时,首先进行限幅处理:

  • 如果采样值小于最小限幅值,则将其设置为最小限幅值。
  • 如果采样值大于最大限幅值,则将其设置为最大限幅值。

将处理后的采样值加入数组,并移除最早的采样值(先进先出)。
对数组中的N个值计算算术平均值。

#define N 5  // 采样次数
#define MAX_LIMIT 100
#define MIN_LIMIT 0int clampValue(int sample, int min, int max) {return (sample < min) ? min : (sample > max) ? max : sample;
}int limitingAveragingFilter(int newSample, int *samples) {static int sum = 0;  // 用于存储采样值的总和int clampedSample = clampValue(newSample, MIN_LIMIT, MAX_LIMIT);// 移除最旧的样本,并添加新的限幅样本sum -= samples[N-1];samples[N-1] = clampedSample;sum += clampedSample;// 计算平均值return sum / N;
}// 使用方法:
// int samples[N]; // 假设samples数组已经初始化
// int new_sample; // 假设这是新采集的样本值
// int filtered_value = limitingAveragingFilter(new_sample, samples);

优点:

抑制异常值:通过限幅处理,可以有效抑制由于传感器故障或外部干扰导致的异常值。
平滑信号:在限幅后的值上计算平均,进一步平滑信号。

缺点:

可能引入偏差:如果限幅值设置不当,可能会引入系统偏差。
计算资源:虽然计算量不大,但在高采样率下,连续的限幅和平均计算可能会占用一定计算资源。

应用场景:

限幅平均滤波法适用于那些信号中可能出现异常值,但整体变化相对平稳的场景,例如:

  • 传感器数据采集:在工业自动化或环境监测中,用于去除传感器读数中的突变噪声。
  • 音频信号处理:在音频信号中减少突发的噪声尖峰。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

7️⃣一阶滞后滤波法


一阶滞后滤波法(First-Order Lag Filter),也称为指数移动平均滤波(Exponential Moving Average, EMA)或一阶低通滤波器,是一种时间加权的移动平均滤波技术。这种滤波法给予最新的数据更高的权重,同时保留旧数据的一定影响,适用于需要平滑数据且对最近数据变化敏感的应用场景。以下是一阶滞后滤波法的基本原理和实现方法:

基本原理:

一阶滞后滤波法使用以下公式来计算滤波后的输出值:

filtered_value=𝛼×new_sample+(1−𝛼)×previous_filtered_value

其中,α 是一个介于 0 到 1 之间的常数,用于加权新采样值和前一次滤波值。

实现方法:

初始化滤波器状态,通常将第一次采样值作为滤波器的初始输出。
对于每个新的采样值,使用上述公式计算新的滤波值。
更新滤波器状态,将新的滤波值作为下一次滤波的输入。

float alpha = 0.3;  // 0 < alpha <= 1,alpha的值越小,滤波器越平滑,但响应越慢
float previous_filtered_value = 0;  // 初始滤波值float firstOrderLagFilter(float new_sample) {return alpha * new_sample + (1 - alpha) * previous_filtered_value;
}// 使用方法:
// float new_sample; // 假设这是新采集的样本值
// float filtered_value = firstOrderLagFilter(new_sample);
// previous_filtered_value = filtered_value; // 更新滤波器状态

优点:

平滑效果:能够平滑数据,减少随机噪声的影响。
快速响应:相比简单的算术平均滤波,一阶滞后滤波对数据变化的响应更快。

缺点:

相位延迟:由于滤波器的平滑特性,输出信号会有一定的相位延迟。
参数选择:需要根据应用场景调整参数 α,以达到最佳的滤波效果。

应用场景:

一阶滞后滤波法适用于多种应用,包括:

  • 传感器数据平滑:在温度、湿度、压力等传感器数据采集中,减少噪声。
  • 金融分析:在股票价格或指数的趋势分析中,平滑短期波动。
  • 控制系统:在需要平滑输入信号的控制系统中,提高系统的稳定性。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

8️⃣加权递推平均滤波法


加权递推平均滤波法(Weighted Recursive Averaging Filter)是一种对递推平均滤波法的改进,它通过给予不同采样值不同的权重来实现滤波。这种方法特别适用于那些需要对最近的数据点给予更多关注的应用场景,同时又能平滑噪声。以下是加权递推平均滤波法的基本原理和实现方法:

基本原理:

加权递推平均滤波法的核心思想是,越新的采样数据对于当前状态的反映更为准确,因此应该赋予更大的权重。滤波器的状态更新可以表示为:
在这里插入图片描述
其中,sample[i] 是第 i 个采样值,𝑤𝑖是对应的权重系数,N 是考虑的采样点数。

实现方法:

初始化一个数组来存储最近的N个采样值,以及对应的权重系数数组。
为每个采样值分配权重,通常最近采样值的权重更高。
当新的采样值到来时,将其加入数组,并计算新的加权平均值:

  • 将新采样值乘以对应的权重,并累加到总和中。
  • 更新总权重和。
  • 计算新的加权平均值,即总和除以总权重和。

移除最旧的采样值及其权重,为下一次更新做准备。

#define N 5  // 采样次数
#define W_N 1  // 最新采样的权重int weights[N] = {1, 2, 3, 2, 1};  // 权重数组,可以根据需要自定义
int sum_weights = 15;  // 权重数组的和float weightedRecursiveAverageFilter(float new_sample, float *samples) {float filtered_value = 0;int i;// 移除最旧的样本值和权重for (i = 0; i < N - 1; i++) {filtered_value += samples[i] * weights[i];sum_weights -= weights[i];}// 加入新的样本值和权重samples[N - 1] = new_sample;filtered_value += new_sample * W_N;sum_weights += W_N;// 计算加权平均值return filtered_value / sum_weights;
}// 使用方法:
// float samples[N]; // 假设samples数组已经初始化
// float new_sample; // 假设这是新采集的样本值
// float filtered_value = weightedRecursiveAverageFilter(new_sample, samples);

优点:

灵活性高:通过调整权重,可以控制滤波器对新旧数据的敏感度。
实时性好:适合实时数据处理,因为只需要考虑最近的N个数据点。

缺点:

权重选择:需要根据具体应用场景合理选择权重,这可能需要一定的经验和试验。
计算量:相比于简单的递推平均滤波,加权递推平均滤波的计算量略大。

应用场景:

加权递推平均滤波法适用于需要根据数据时效性进行不同处理的场景,例如:

  • 金融分析:在股票价格分析中,可能需要对最新的价格变动给予更多关注。
  • 传感器数据平滑:在某些传感器数据处理中,可能需要对最新的读数反应更快。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

9️⃣消抖滤波法


消抖滤波法(Debounce Filtering)是一种用于数字信号处理的简单技术,主要用于消除按键或传感器等数字输入的抖动(即快速的电平变化)。这种滤波法可以避免因信号的不稳定而导致的误触发或错误读取。以下是消抖滤波法的基本原理和实现方法:

基本原理:

消抖滤波法通过设置一个特定的时间阈值(称为消抖时间),在这个时间内,即使输入信号发生变化,也不立即更新输出。只有当输入信号在消抖时间之后仍然保持稳定时,输出才会更新。这种方法可以有效避免因噪声或机械振动导致的误触发。

实现方法:

初始化:设置一个消抖时间阈值,通常以毫秒为单位。
读取输入:在每个时间点,读取数字输入的状态。
状态比较:将当前状态与上一状态进行比较。
状态稳定检查:如果状态发生变化,重置计时器并开始计时。
消抖逻辑:如果状态在消抖时间阈值内保持不变,则更新输出状态。
输出更新:只有当状态在消抖时间之后仍然稳定时,才更新输出。

#include <stdint.h>
#include <stdbool.h>#define DEBOUNCE_DELAY_MS 50  // 消抖时间阈值,例如50毫秒bool debounce(bool current_state, bool last_state, uint32_t *last_debounced_time) {static uint32_t last_time = 0;  // 上次稳定状态的时间戳uint32_t current_time = get_current_millis();  // 获取当前时间戳if (current_state != last_state) {// 如果状态改变,重置时间戳last_time = current_time;}if ((current_time - last_time) >= DEBOUNCE_DELAY_MS) {// 如果状态在消抖时间阈值内保持不变,则认为稳定*last_debounced_time = current_time;return !last_state;  // 返回新的状态}return last_state;  // 返回上一次稳定的输出状态
}// 使用方法:
// bool current_state; // 假设这是从传感器或按键读取的当前状态
// bool last_state = false; // 上一次的状态
// uint32_t last_debounced_time = 0;
// bool debounced_state = debounce(current_state, last_state, &last_debounced_time);

优点:

简单易实现:消抖滤波法的逻辑简单,容易实现。
有效消除抖动:对于消除快速的电平变化非常有效。

缺点:

引入延迟:由于需要等待消抖时间阈值,因此会引入一定的延迟。
时间阈值选择:时间阈值的选择需要根据应用场景进行调整,以避免过长的延迟或过早的触发。

应用场景:

消抖滤波法适用于需要稳定读取数字信号的场景,例如:

  • 按键输入:在用户界面中,用于稳定按键的读取,避免误操作。
  • 传感器信号:在某些传感器信号处理中,用于消除因机械振动或环境噪声导致的抖动。
🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈🙈

1️⃣0️⃣限幅消抖滤波法


限幅消抖滤波法(Clamped or Limited Debounce Filtering)是一种结合了限幅滤波和消抖滤波的数字信号处理技术。它不仅能够消除按键或传感器输入的抖动,还能够限制输入信号在一定的范围内,防止异常值或极端情况的发生。以下是限幅消抖滤波法的基本原理和实现方法:

基本原理:

限幅消抖滤波法通过以下两个主要步骤来处理信号:

  • 限幅:首先检查输入值是否在预设的最大值和最小值范围内。如果输入值超出这个范围,将其限制在范围内。
  • 消抖:在限幅后的值上应用消抖逻辑,通过设定一个时间阈值来确保输入值在该时间内保持稳定,从而避免因噪声或机械振动导致的误触发。

实现方法:

初始化:设置最大值、最小值和消抖时间阈值。
限幅处理:读取输入值,并检查它是否在最大值和最小值之间。如果不在,将其设置为范围内的最近极限值。
消抖逻辑:使用一个计时器来跟踪输入值的稳定时间。如果输入值在消抖时间阈值内没有变化,则认为它是稳定的,并更新输出值。
输出更新:只有当输入值稳定后,才更新输出值。

#define MAX_VALUE 100
#define MIN_VALUE 0
#define DEBOUNCE_DELAY_MS 50bool is_input_stable(int current_input, int *last_input, uint32_t *last_debounced_time) {static uint32_t last_time = 0;uint32_t current_time = get_current_millis(); // 假设这是获取当前时间的函数// 限幅处理if (current_input < MIN_VALUE) {current_input = MIN_VALUE;} else if (current_input > MAX_VALUE) {current_input = MAX_VALUE;}// 消抖逻辑if (*last_input != current_input) {*last_input = current_input;*last_debounced_time = current_time; // 重置时间return false; // 输入尚未稳定}if ((current_time - *last_debounced_time) >= DEBOUNCE_DELAY_MS) {return true; // 输入稳定}return false;
}// 使用方法:
// int current_input; // 假设这是从传感器或按键读取的当前输入值
// int last_input = 0; // 上一次稳定的输入值
// uint32_t last_debounced_time = 0; // 上一次稳定输入的时间
// if (is_input_stable(current_input, &last_input, &last_debounced_time)) {
//     // 处理稳定的输入值
// }

优点:

稳定性好:结合限幅和消抖,提高了信号的稳定性。
适用范围广:适用于多种需要稳定输入信号的应用场景。

缺点:

可能限制有效信号:限幅可能会限制有效信号的范围,特别是在信号变化较大时。
延迟:消抖引入的延迟可能对某些实时性要求高的应用造成影响。

应用场景:

限幅消抖滤波法适用于需要稳定且在一定范围内的输入信号的场景,例如:

  • 工业控制:在工业自动化中,用于稳定传感器输入并防止异常值。
  • 用户界面:在按钮或触摸界面中,用于消除误触发和抖动。

在这里插入图片描述

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

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

相关文章

PLC通过IGT-SER系列智能网关快速实现WebService接口调用案例

IGT-SER系列智能网关支持PLC设备数据对接到各种系统平台&#xff0c;包括SQL数据库&#xff0c;以及MQTT、HTTP协议的数据服务端&#xff1b;通过其边缘计算功能和脚本生成的工具软件&#xff0c;非常方便快速实现PLC、智能仪表与WebService服务端通信。 本文是通过智能网关读取…

Ubuntu 22.04.4 LTS (linux) GoAccess 分析 Nginx 日志

1 安装goaccess sudo apt-get update sudo apt-get install goaccess 2 控制台运行 goaccess -a -d -f /usr/local/openresty/nginx/logs/access.log -p /etc/goaccess/goaccess.conf #sudo vim /etc/goaccess/goaccess.conf time-format %H:%M:%S date-format %d/%b…

van-dialog 组件调用报错

报错截图 报错原因 这个警告表明 vue 在渲染页面时遇到了一个未知的自定义组件 <van-dialog>&#xff0c;并且提示可能是由于未正确注册该组件导致的。在 vue 中&#xff0c;当我们使用自定义组件时&#xff0c;需要先在 vue 实例中注册这些组件&#xff0c;以便 vue 能…

Emacs之解决无法输入中文问题(一百四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列…

基于YOLO8的目标检测系统:开启智能视觉识别之旅

文章目录 在线体验快速开始一、项目介绍篇1.1 YOLO81.2 ultralytics1.3 模块介绍1.3.1 scan_task1.3.2 scan_taskflow.py1.3.3 target_dec_app.py 二、核心代码介绍篇2.1 target_dec_app.py2.2 scan_taskflow.py 三、结语 在线体验 基于YOLO8的目标检测系统 基于opencv的摄像头…

Provisional headers are shown Learn more

Provisional headers are shown Learn more 目录 Provisional headers are shown Learn more 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医…

什么情况下的网站要使用CDN加速呢?

CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。 CDN的通俗理解就是网站加速&#xff0c;CPU均衡负载&#xff0c;可以解决跨运营商&#xff0c;跨地区&#xff0c;服务器负载能力过低&#xff0c;带宽过少等带来的网站打开速度慢等问题。 原理就是在客户端…

如何解除maven打包编译的警告日志:[WARNING] 未与 -source 21 一起设置系统模块的位置

在用jdk较高的版本进行maven项目的打包编译时&#xff0c;经常遇到类似“[WARNING] 未与 -source 21 一起设置系统模块的位置”这样的警告日志&#xff0c;如下&#xff1a; 网上大量搜索该问题的解决方案&#xff0c;却未果&#xff0c;无耐去看了官网的用法&#xff0c;才获得…

Java项目中整合多个pdf合并为一个pdf

一、Java项目中整合多个pdf合并为一个pdf gitee笔记路径&#xff1a;https://gitee.com/happy_sad/drools一、依赖导入 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.6</version> …

ts 下使用 interactjs 的时候,事件类型该如何定义 InteractEvent

ts 下使用 interactjs 的时候&#xff0c;事件类型该如何定义 InteractEvent 一、问题 interactjs 是一个很好用的给元素添加拖动事件的插件&#xff0c;它可以实现如下的效果。 其官网是 https://interactjs.io/ vitetsvue3 项目中用到了 interactjs 这个库&#xff0c;但在…

事务、函数和索引

M y S Q L 事 务 什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 特点&#xff1a;一个事务中如果有一个数据库操作…

【Android】数据存储方案——文件存储、SharedPreferences、SQLite数据库用法总结

文章目录 文件存储存储到文件读取文件 SharedPreferences存储存储获取SharedPreferences对象Context 类的 getSharedPreferences() 方法Activity 类的 getPreferences() 方法PreferenceManager 类中的 getDefaultSharedPreferences() 方法 示例 读取记住密码的功能 SQLite数据库…

学习OCR具体使用

暂时找了三种&#xff0c;有一些问题待解决 Tesseract-OCR1. 安装库&#xff1a;2. 安装Tesseract-OCR&#xff1a;3. 安装中文语言包&#xff1a;4. Python代码&#xff1a;5. 运行结果 cnOCR1. 安装cnOCR&#xff1a;2. 使用cnOCR进行OCR&#xff1a;3. 运行结果 PaddleOCR1.…

vue 实战 区域内小组件元素拖拽 示例

<template><div><el-button type"primary" click"showDialog true">快捷布局</el-button><el-dialog title"快捷布局配置" :visible.sync"showDialog"><el-row :gutter"20"><el-co…

柯达sd卡数据丢失怎么办?分享有效数据恢复方法

随着科技的进步&#xff0c;数码相机已成为我们生活中不可或缺的一部分&#xff0c;而柯达作为摄影界的知名品牌&#xff0c;其相机及配件更是广受欢迎。然而&#xff0c;在日常使用中&#xff0c;难免会遇到数据丢失的情况&#xff0c;特别是SD卡中的数据丢失&#xff0c;常常…

大模型技术:发展历程、经典模型、微调与应用[更新中...]

文章目录 一、预训练语言模型发展历程二、经典的Pre-trained任务2.1 Masked Language Modeling2.2 Next Sentence Prediction 三、Task-specific Fine-tuning 任务3.1 Single-text Classification (单句分类)3.2 Sentence-pair Classification (句子匹配/成对分类)3.3 Span Tex…

Java3-final,singleInstance,enum

final可以用来修饰类、方法、变量 public static final -- 修饰常量 singleInstance-单例&#xff1b;一个类永远只存在一个对象 1、饿汉单例&#xff1b; --通过类获取单例对象的时候&#xff0c;对象已经提前做好了 --实现&#xff1a; 2、懒汉单例 --通过类获取单例对象…

C++第二十七弹---优先级队列的高级应用:结合仿函数优化性能

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1 priority_queue的介绍和使用 1.1 priority_queue的介绍 1.2 priority_queue的使用 2 仿函数的介绍和使用 2.1 仿函数的介绍 2.2 仿函数的…

Java的类加载机制

Java的类加载机制是指将类的字节码文件&#xff08;.class文件&#xff09;加载到JVM中并将其转换为Class对象的过程。这个过程由类加载器&#xff08;ClassLoader&#xff09;完成。Java的类加载机制具有动态性和灵活性&#xff0c;使得Java能够支持动态加载类、实现模块化开发…

C++ 八股(2)

1.函数调用的参数是以什么顺序压栈的&#xff0c;为什么&#xff1f; 从右向左压栈的。因为C, C支持可变参函数。 可变参函数就是参数个数可变的函数&#xff0c;如printf()就是可变参函数 void func(int a,...){} 2.有一个函数 在main函数中通过&#xff1a;string s fun…