在单片机系统中进行信号采样和相似度计算,特别是在给出触发信号后,以1kHz的速率采样并保存数据作为标准数据,然后在下次触发周期采集数据并进行对比,可以使用交叉相关(Cross-Correlation)方法来对齐信号,并计算相似度。以下是对该过程的详细描述和示例代码:
步骤概述
- 首次触发采集标准数据:在第一次触发信号后,以1kHz的速率采集并保存标准数据。
- 再次触发采集新数据:在后续触发信号后,再次以1kHz的速率采集数据。
- 对齐信号:使用交叉相关方法对齐新采集的数据和标准数据。
- 计算相似度:使用皮尔逊相关系数或其他相似度度量方法计算对齐后的信号相似度。
如何计算相似度以及公式
在信号处理领域,相似度度量通常用于评估两个信号之间的相似性程度。最常用的方法之一是计算皮尔逊相关系数(Pearson Correlation Coefficient),它量化了两个信号之间的线性相关性。以下是计算相似度的详细步骤和公式。
皮尔逊相关系数
皮尔逊相关系数的公式如下:
r = ∑ i = 1 N ( x i − x ‾ ) ( y i − y ‾ ) ∑ i = 1 N ( x i − x ‾ ) 2 ∑ i = 1 N ( y i − y ‾ ) 2 r = \frac{\sum_{i=1}^N (x_i - \overline{x})(y_i - \overline{y})}{\sqrt{\sum_{i=1}^N (x_i - \overline{x})^2} \sqrt{\sum_{i=1}^N (y_i - \overline{y})^2}} r=∑i=1N(xi−x)2∑i=1N(yi−y)2∑i=1N(xi−x)(yi−y)
其中:
- ( r ) 是皮尔逊相关系数,取值范围为 -1 到 1。
- ( x_i ) 和 ( y_i ) 分别是信号 ( x ) 和 ( y ) 在第 ( i ) 个样本点的值。
- ( \overline{x} ) 和 ( \overline{y} ) 分别是信号 ( x ) 和 ( y ) 的均值。
步骤概述
- 计算信号的均值:首先计算两个信号的均值。
- 计算分子:计算每对信号值与其均值的差的乘积的总和。
- 计算分母:分别计算两个信号值与其均值的差的平方和,然后取平方根,再将结果相乘。
- 计算相似度:将分子除以分母得到皮尔逊相关系数。
代码实现
详细步骤和代码示例
1. 首次触发采集标准数据
假设信号长度为 N
,以数组 standard_signal
保存标准数据。
#define N 1000
float standard_signal[N];
// 在第一次触发信号后采集标准数据
void collect_standard_data() {
for (int i = 0; i < N; i++) {
standard_signal[i] = read_adc(); // read_adc() 是一个假设的函数,用于从ADC读取采样数据
delay(1); // 延时1ms,对应1kHz采样率
}
}
2. 再次触发采集新数据
假设以数组 new_signal
保存新采集的数据。
float new_signal[N];
// 在后续触发信号后采集新数据
void collect_new_data() {
for (int i = 0; i < N; i++) {
new_signal[i] = read_adc();
delay(1);
}
}
3. 对齐信号
计算交叉相关,并找到最佳对齐位置。
float correlation[2 * N - 1];
void cross_correlation(float signal1[], float signal2[], float correlation[]) {
int i, j;
for (i = 0; i < 2 * N - 1; i++) {
correlation[i] = 0;
for (j = 0; j < N; j++) {
if (i - j >= 0 && i - j < N) {
correlation[i] += signal1[j] * signal2[i - j];
}
}
}
}
int find_max_correlation_index(float correlation[]) {
int max_index = 0;
float max_value = correlation[0];
for (int i = 1; i < 2 * N - 1; i++) {
if (correlation[i] > max_value) {
max_value = correlation[i];
max_index = i;
}
}
return max_index;
}
void align_signals(float signal1[], float signal2[], float aligned_signal2[], int shift) {
int i;
if (shift > 0) {
for (i = 0; i < N - shift; i++) {
aligned_signal2[i] = signal2[i + shift];
}
for (i = N - shift; i < N; i++) {
aligned_signal2[i] = 0;
}
} else {
for (i = 0; i < -shift; i++) {
aligned_signal2[i] = 0;
}
for (i = -shift; i < N; i++) {
aligned_signal2[i] = signal2[i + shift];
}
}
}
4. 计算相似度
使用皮尔逊相关系数计算对齐后的信号相似度。
float calculate_similarity(float signal1[], float signal2[]) {
float mean1 = 0, mean2 = 0;
for (int i = 0; i < N; i++) {
mean1 += signal1[i];
mean2 += signal2[i];
}
mean1 /= N;
mean2 /= N;
float numerator = 0, denominator1 = 0, denominator2 = 0;
for (int i = 0; i < N; i++) {
numerator += (signal1[i] - mean1) * (signal2[i] - mean2);
denominator1 += pow(signal1[i] - mean1, 2);
denominator2 += pow(signal2[i] - mean2, 2);
}
return numerator / sqrt(denominator1 * denominator2);
}
主程序
整合以上步骤,实现信号采集、对齐和相似度计算的完整流程。
#include <stdio.h>
#include <math.h>
#define N 1000
float standard_signal[N];
float new_signal[N];
float correlation[2 * N - 1];
float aligned_signal2[N];
// 假设有个读取ADC的函数
float read_adc() {
// 模拟读取ADC数据
return (float)(rand() % 1024) / 1024.0;
}
// 模拟延时函数
void delay(int ms) {
// 简单的延时模拟
for (volatile int i = 0; i < ms * 1000; i++);
}
// 首次触发采集标准数据
void collect_standard_data() {
for (int i = 0; i < N; i++) {
standard_signal[i] = read_adc();
delay(1);
}
}
// 再次触发采集新数据
void collect_new_data() {
for (int i = 0; i < N; i++) {
new_signal[i] = read_adc();
delay(1);
}
}
// 交叉相关函数、找到最大相关性位置、对齐信号、计算相似度的函数前面已定义
int main() {
// 第一次触发,采集标准数据
collect_standard_data();
// 模拟后续触发事件
while (1) {
// 再次触发,采集新数据
collect_new_data();
// 计算交叉相关
cross_correlation(standard_signal, new_signal, correlation);
// 找到最大相关性的位置
int shift = find_max_correlation_index(correlation) - N + 1;
// 对齐信号
align_signals(standard_signal, new_signal, aligned_signal2, shift);
// 计算相似度
float similarity = calculate_similarity(standard_signal, aligned_signal2);
printf("Shift: %d, Similarity: %f\n", shift, similarity);
// 模拟等待下一次触发
delay(1000);
}
return 0;
}
解释
- 计算均值:通过遍历信号数组计算每个信号的均值。
- 计算分子和分母:使用循环计算公式中的分子和分母部分。
- 计算相似度:最终将分子除以分母得到相似度,即皮尔逊相关系数。
总结
该程序模拟了一个在单片机系统中采集和处理信号的过程,包括信号采集、交叉相关计算、信号对齐以及相似度计算。可以根据实际的硬件环境和具体需求进行调整和优化。
皮尔逊相关系数提供了一种简单而有效的方法来量化两个信号之间的相似度。当信号完全线性相关时,相关系数为 1 或 -1;当信号完全不相关时,相关系数为 0。该方法在信号处理和数据分析中广泛应用,可以用于各种相似度测量场景。