目录
1.前言
最近一直在做振动监测,把传感器采集到的振动信号数据转换成电压值,然后通过QT的QCharts绘制出时域图形,接着利用C++的线性库Armadillo中FFT()将时域信号转换成频域信号,绘制出响应的频谱图。QT中配Armadillo我之前写过一篇文章记录过,就不再详细说了。
QT中配置C++运算库Armadillo_唔肯木工的博客-CSDN博客
2.时域
2.1简介
时域(Time Domain)是信号处理中的一个概念,用于描述信号在时间上的变化和演化。在时域中,信号被表示为时间的函数,可以看作是信号在时间轴上的波形图。
时域分析主要关注信号的时序特征,包括信号的振幅、频率、相位和持续时间等。通过对信号在时域上的分析,可以获得信号的时域特征,如峰值,裕度,峭度,脉冲宽度、周期性、瞬态特性等,从而对信号的时序行为进行研究和理解。
在时域分析中,常用的工具和技术包括:
-
时域图形表示:将信号绘制成波形图,以可视化信号在时间上的变化。常见的时域图形包括时序图、波形图、折线图等。
-
时域参数:通过计算信号的各种统计量和时域参数,如均值、方差、峰值、峰峰值、波形因子等,来描述信号的时域特征。
-
自相关函数:用于衡量信号在不同时间点上的自相关性。自相关函数可以揭示信号的周期性和重复性特征。
-
瞬态响应:瞬态响应描述系统对突变输入的响应,可以通过观察信号在时域上的变化来分析系统的瞬态特性。
时域分析在信号处理、通信系统、控制系统等领域具有重要的应用。通过分析信号在时间上的特性,帮助我们理解信号的动态行为、检测故障和异常、设计滤波器和控制系统等。此外,时域分析通常与频域分析相结合,以全面了解信号的特性和行为。
2.2时域信号分析
我是通过W5500以太网芯片利用TCP或者WebSocket协议将采集到的振动信号传输给QT上位机,将上位机作为服务器端,把传输过来的信号进行转换之后绘制出来时域和频域。我对时域特征值也进行了提取,这里就先不介绍了。
void Server::StrConvert(QString str)
{
QVector<double> dataCh4;
QVector<double> dataCh2;
QVector<double> dataCh3;
QVector<double> dataCh1;
colvec matdc4(50);
colvec matdc2(50);
colvec matdc3(50);
colvec matdc1(50);
QString hex = "7FFFFF";
QStringList splitData = str.split("\r");
for(int i = 0;i < splitData.length()-1;i++)
{
QString Qch4 = splitData.value(i).mid(18,6);
double ch4 = 2.5*Qch4.toInt(nullptr,16)/hex.toInt(nullptr,16);
QString Qch2 = splitData.value(i).mid(6,6);
double ch2 = 2.5*Qch2.toInt(nullptr,16)/hex.toInt(nullptr,16);
QString Qch3 = splitData.value(i).mid(12,6);
double ch3 = 2.5*Qch3.toInt(nullptr,16)/hex.toInt(nullptr,16);
QString Qch1 = splitData.value(i).mid(0,6);
double ch1 = 2.5*Qch1.toInt(nullptr,16)/hex.toInt(nullptr,16);
dataCh4.append(ch4);
dataCh2.append(ch2);
dataCh3.append(ch3);
dataCh1.append(ch1);
}
for (int i = 0; i < 50; i++)
{
matdc1.row(i)=dataCh1.at(i);
matdc2.row(i)=dataCh2.at(i);
matdc3.row(i)=dataCh3.at(i);
matdc4.row(i)=dataCh4.at(i);
}
matdc1.save("matdc1.txt",raw_ascii);
matdc2.save("matdc2.txt",raw_ascii);
matdc3.save("matdc3.txt",raw_ascii);
matdc4.save("matdc4.txt",raw_ascii);
return;
}
void CompInfo1_1::Primitive()
{
static bool flag = true;
dc1.load("matdc1.txt");
dc2.load("matdc2.txt");
dc3.load("matdc3.txt");
dc4.load("matdc4.txt");
chart6->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60));
chart6->axisX()->setMax(QDateTime::currentDateTime().addSecs(0));
if ((!dc1.is_empty())&&(!dc2.is_empty())&&(!dc3.is_empty())&&(!dc4.is_empty()))
{
for(int i = 0; i < 50; i++)
{
NlineSeries1->append(QDateTime::currentDateTime().toMSecsSinceEpoch(),dc1(i));
NlineSeries2->append(QDateTime::currentDateTime().toMSecsSinceEpoch(),dc2(i));
NlineSeries3->append(QDateTime::currentDateTime().toMSecsSinceEpoch(),dc3(i));
NlineSeries4->append(QDateTime::currentDateTime().toMSecsSinceEpoch(),dc4(i));
}
}
else
{
if(flag)
{
flag = false;
QMessageBox::information(this,"Tip","请连接服务器!");
}
}
return;
}
上面把转换好的信号存放到矩阵中,并保存下来,绘制时域图时使用Armadillo中加载矩阵的方法读取出来。
3.频域
3.1简介
频域(Frequency Domain)是信号处理中的一个概念,用于描述信号在频率上的特征和变化。在频域中,信号被表示为频率的函数,可以看作是信号在频率轴上的能量分布。
频域分析主要关注信号的频率成分和频谱特性,包括信号的频率内容、频域幅度、相位和频域分布等。通过对信号在频域上的分析,可以获得信号的频域特征,如频谱形状、频率成分的强度和分布等,从而对信号的频率特性进行研究和理解。
在频域分析中,常用的工具和技术包括:
-
傅里叶变换:傅里叶变换是频域分析的基础工具,将信号从时域转换到频域。傅里叶变换可以将信号表示为频率成分的叠加,提供了信号在频域上的幅度和相位信息。
-
频谱分析:通过对信号进行频谱分析,可以将信号在频域上的能量分布可视化为频谱图。常见的频谱分析方法包括功率谱密度(PSD)、频谱图、频谱瀑布图等。
-
频域滤波:频域滤波利用信号的频率特性进行滤波操作。通过在频域上调整信号的频率成分,可以实现去除噪声、滤波和频率选择等功能。
-
快速傅里叶变换(FFT):FFT是一种高效的算法,用于计算离散信号的傅里叶变换。FFT可以快速地将信号从时域转换到频域,常用于频谱分析和频域滤波等应用。
-
频域参数:通过计算信号在频域上的统计量和参数,如频域均值、频域方差、频域峰值等,来描述信号的频域特征。
频域分析可以帮助我们理解信号的频率内容、提取频率特征、设计滤波器、频率调制和解调等。
3.2频域信号分析
在这里面我使用4096个采样点,采样频率为fs = 10000Hz,对信号进行处理,使用linspace计算得到一个频率序列。通过应用fft()函数,取复数的绝对值得到幅值。并且在频域中,频率为0对应的值表示直流分量需要减去。最后,将频率和幅值组合成一个矩阵,并返回该矩阵。
double cacl_mean(vec src)
{
return mean(src);
}
mat calc_pri(vec src, double fs)
{
vec subSrc = src.subvec(0,4095);
subSrc = subSrc-cacl_mean(subSrc);
int n = subSrc.n_elem;
vec freq = linspace(0, n-1,n/2)*fs/n;
vec amps = abs(fft(subSrc,n)*2/n);
amps = amps(span(0,n/2-1));
mat matrix;
matrix = mat(join_rows(freq, amps));
return matrix;
}
void CompInfof1_1::Draw_pr()
{
static bool flag = true;
fdc1.load("matdc1.txt",raw_ascii);
fdc2.load("matdc2.txt",raw_ascii);
fdc3.load("matdc3.txt",raw_ascii);
fdc4.load("matdc4.txt",raw_ascii);
fx1 = FDomain->calc_pri(fdc1,10000);
fx2 = FDomain->calc_pri(fdc2,10000);
fx3 = FDomain->calc_pri(fdc3,10000);
fx4 = FDomain->calc_pri(fdc4,10000);
if ((!fdc1.is_empty())&&(!fdc2.is_empty())&&(!fdc3.is_empty())&&(!fdc4.is_empty()))
{
for(int i=0;i<fx1.n_rows;i++)
{
PRlineSeries1->append(fx1(i,0),fx1(i,1));
PRlineSeries2->append(fx2(i,0),fx2(i,1));
PRlineSeries3->append(fx3(i,0),fx3(i,1));
PRlineSeries4->append(fx4(i,0),fx4(i,1));
}
}
else
{
if(flag)
{
flag = false;
QMessageBox::information(this,"Tip","请连接服务器!");
}