在线算法(在线计算或递推计算)能够在不存储全部数据的情况下逐步更新信号的特征信息,非常适合资源受限的单片机应用场景。
用途:单片机边采集ADC边计算,最终将采集的信号特征计算结果。平台通过长期监控信号特征来确定采集的设备工作正常。用途机台长期监控。
以下是几种常见的信号特征信息计算及其对应的在线算法:
1. 均值(Mean)
递推均值公式
mean
n
=
(
n
−
1
)
⋅
mean
n
−
1
+
x
n
n
\text{mean}_n = \frac{(n-1) \cdot \text{mean}_{n-1} + x_n}{n}
meann=n(n−1)⋅meann−1+xn
其中,( n ) 是当前采样点的数量,( x_n ) 是第 ( n ) 个采样值,( \text{mean}_{n-1} ) 是前 ( n-1 ) 个采样值的均值。
2. 均方根(RMS, Root Mean Square)
递推 RMS 公式:
RMS
n
=
(
n
−
1
)
⋅
(
RMS
n
−
1
)
2
+
x
n
2
n
\text{RMS}_n = \sqrt{\frac{(n-1) \cdot (\text{RMS}_{n-1})^2 + x_n^2}{n}}
RMSn=n(n−1)⋅(RMSn−1)2+xn2
3. 方差(Variance)
递推方差公式:
var
n
=
(
n
−
1
)
⋅
var
n
−
1
+
(
x
n
−
mean
n
)
(
x
n
−
mean
n
−
1
)
n
\text{var}_n = \frac{(n-1) \cdot \text{var}_{n-1} + (x_n - \text{mean}_n)(x_n - \text{mean}_{n-1})}{n}
varn=n(n−1)⋅varn−1+(xn−meann)(xn−meann−1)
4. 标准差(Standard Deviation)
标准差是方差的平方根:
stddev
n
=
var
n
\text{stddev}_n = \sqrt{\text{var}_n}
stddevn=varn
5. 峰峰值(Peak-to-Peak Value)
更新最大值和最小值:
if (x_n > max) max = x_n;
if (x_n < min) min = x_n;
峰峰值计算公式:
peak-to-peak
=
max
−
min
\text{peak-to-peak} = \text{max} - \text{min}
peak-to-peak=max−min
6. 平均绝对偏差(Mean Absolute Deviation, MAD)
递推平均绝对偏差公式:
MAD
n
=
(
n
−
1
)
⋅
MAD
n
−
1
+
∣
x
n
−
mean
n
∣
n
\text{MAD}_n = \frac{(n-1) \cdot \text{MAD}_{n-1} + |x_n - \text{mean}_n|}{n}
MADn=n(n−1)⋅MADn−1+∣xn−meann∣
7. 信号功率(Power)
递推信号功率公式:
power
n
=
(
n
−
1
)
⋅
power
n
−
1
+
x
n
2
n
\text{power}_n = \frac{(n-1) \cdot \text{power}_{n-1} + x_n^2}{n}
powern=n(n−1)⋅powern−1+xn2
8. 信号能量(Energy)
信号能量是所有样本平方的累加和:
energy
n
=
energy
n
−
1
+
x
n
2
\text{energy}_n = \text{energy}_{n-1} + x_n^2
energyn=energyn−1+xn2
示例代码更新
以下是使用递推算法计算上述信号特征信息的示例代码:
#include "stm32f0xx_hal.h"
#include <math.h>
// 全局变量
volatile uint32_t count = 0;
volatile float mean = 0;
volatile float variance = 0;
volatile float stddev = 0;
volatile float max = -FLT_MAX;
volatile float min = FLT_MAX;
volatile float mad = 0;
volatile float power = 0;
volatile float energy = 0;
volatile uint8_t trigger_active = 0;
// ADC 和定时器句柄
ADC_HandleTypeDef hadc;
TIM_HandleTypeDef htim;
// 初始化 ADC
void ADC_Init(void) {
__HAL_RCC_ADC1_CLK_ENABLE();
hadc.Instance = ADC1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.ScanConvMode = DISABLE;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_TRGO;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc);
// 配置 ADC 通道
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
HAL_ADC_ConfigChannel(&hadc, &sConfig);
}
// 初始化定时器
void TIM_Init(void) {
__HAL_RCC_TIM1_CLK_ENABLE();
htim.Instance = TIM1;
htim.Init.Prescaler = 8000 - 1; // 1 MHz 时钟,1 kHz 采样率
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = 1000 - 1; // 1 kHz
htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim);
// 配置定时器触发 ADC
TIM_MasterConfigTypeDef sMasterConfig = {0};
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig);
}
// ADC 转换完成中断服务函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if (trigger_active) {
uint32_t adc_value = HAL_ADC_GetValue(hadc);
float x_n = (float)adc_value;
// 更新样本计数
count++;
// 计算均值
float old_mean = mean;
mean = ((count - 1) * mean + x_n) / count;
// 计算方差
variance = ((count - 1) * variance + (x_n - mean) * (x_n - old_mean)) / count;
stddev = sqrt(variance);
// 更新最大值和最小值
if (x_n > max) max = x_n;
if (x_n < min) min = x_n;
// 计算平均绝对偏差
mad = ((count - 1) * mad + fabs(x_n - mean)) / count;
// 计算信号功率
power = ((count - 1) * power + x_n * x_n) / count;
// 计算信号能量
energy += x_n * x_n;
}
}
// 触发信号检测函数
void check_trigger_signal(void) {
if (/* 检测到触发信号 */) {
trigger_active = 1;
HAL_ADC_Start_IT(&hadc);
HAL_TIM_Base_Start(&htim);
} else {
trigger_active = 0;
HAL_ADC_Stop_IT(&hadc);
HAL_TIM_Base_Stop(&htim);
}
}
// 主函数
int main(void) {
HAL_Init();
ADC_Init();
TIM_Init();
while (1) {
check_trigger_signal();
// 其他处理
}
}
在这个示例代码中,我们展示了如何使用递推算法来计算多个信号特征信息,包括均值、方差、标准差、最大值、最小值、平均绝对偏差、信号功率和能量。这些算法在每次新的采样点到达时更新,无需存储所有数据,适用于单片机环境。