Qt平台使用fft解析肌电传感器信号

这篇博客介绍如何在Qt环境下使用fftw3库解析肌电传感器信号,并通过qcustomplot库展示波形。内容涵盖关键文件如.pro、graph.h、mainwindow.h、qcustomplot.h、serial.h等,以及解析和显示信号的cpp源码。
摘要由CSDN通过智能技术生成

备注:该程序在串口解析时偶尔还会出现问题

.pro

#-------------------------------------------------
#
# Project created by QtCreator 2021-03-09T09:33:42
#
#-------------------------------------------------

QT       += core gui serialport printsupport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = untitled
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        graph.cpp \
        main.cpp \
        mainwindow.cpp \
        qcustomplot.cpp \
        resolver.cpp \
        serial.cpp

HEADERS += \
        fftw3.h \
        graph.h \
        mainwindow.h \
        qcustomplot.h \
        resolver.h \
        serial.h

FORMS += \
        mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

LIBS += -L$$PWD/./ -llibfftw3-3
INCLUDEPATH += $$PWD/.
DEPENDPATH += $$PWD/.

fftw3.h是fftw的自带头文件,工程中需要包含

graph.h

#ifndef GRAPH_H
#define GRAPH_H

#include <QMainWindow>
#include "qcustomplot.h"



#endif // GRAPH_H

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "serial.h"
#include "graph.h"
#include "resolver.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    QVector<double> x,y0,y1;

signals:
    void start_resolver();

public slots:
    void slot_graph();

private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();
    void readyRead_slot(QByteArray data);
    void on_actionserial_triggered(bool checked);
    void on_dockWidget_visibilityChanged(bool visible);

    void on_pushButton_3_clicked();

private:
    Ui::MainWindow *ui;
    serial *myserial;
    resolver *m_resolver;
    QThread *m_thread;

    void graph_init();
    void customplot1_add_graph(void);
    void customplot2_add_graph(void);
};

#endif // MAINWINDOW_H

qcustomplot.h是Qt中用来显示波形的外部库qcustomplot的头文件

resolver.h 

#ifndef RESOLVER_H
#define RESOLVER_H

#include <QObject>
#include <QThread>
#include "fftw3.h"

#define N 256
#define UART_BUF_SIZE   200

class resolver : public QObject
{
    Q_OBJECT
public:
    explicit resolver(QObject *parent = nullptr);
    ~resolver();

signals:
    void start_graph();

public slots:
    void do_resolver();

private:
    void do_fft();
    void do_resolver2(char *char_data,uint8_t len);
};

struct channel_data
{
    uint16_t average_value;
    uint16_t current_value;
    uint16_t power;
    uint16_t Shredded;
};

#endif // RESOLVER_H

serial.h

#ifndef SERIAL_H
#define SERIAL_H

#include <QObject>
#include <QSerialPort>
#include <QSerialPortInfo>
#include "qserialport.h"
#include "QString"


class serial:public QObject
{
    Q_OBJECT

public:
    serial(QObject *o=0);
    ~serial();
    bool openPort(QString portName,qint32 baudRate,QSerialPort::DataBits dataBits,
                  QSerialPort::Parity parity,QSerialPort::StopBits stopBits,
                  QSerialPort::FlowControl flowControl);
    bool isOpen();
    void closePort();
    QStringList getAvailablePortNameList();

    void write(QString str);
    void write(const char *data, qint64 len);
    QString ByteArrayToHexString(QByteArray data);

signals:
    void readyRead(QByteArray data);

private:
    QSerialPort *m_port;

    void readyRead_slot();



};

#endif // SERIAL_H

graph.cpp

#include "graph.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVector>
#include <stdio.h>

extern fftw_complex *in, *out;

/*-------------------------------------------*/
//画动态曲线时,传入数据采用addData,通过定时器多次调用,并在之后调用ui->widget->replot();
//动态曲线可以通过另一种设置坐标的方法解决坐标问题:
//setRange ( double  position, double  size, Qt::AlignmentFlag  alignment  )
//参数分别为:原点,偏移量,对其方式,有兴趣的读者可自行尝试,欢迎垂询
/*-------------------------------------------*/

void MainWindow::graph_init()
{
    x.resize(N);
    for(int i=0;i<N;i++)
    {
        x[i]=i;
    }
    y0.resize(N);
    y1.resize(N);

        //设定背景为黑色
        //ui->widget->setBackground(QBrush(Qt::black));
        //设置X轴文字标注
        ui->widget->xAxis->setLabel("time");
        ui->widget_2->xAxis->setLabel("time");
        //设置Y轴文字标注
        ui->widget->yAxis->setLabel("short HbO2");
        ui->widget_2->yAxis->setLabel("short HbO2");
        //设置X轴坐标范围
        ui->widget->xAxis->setRange(0,N);
        ui->widget_2->xAxis->setRange(0,N/2);
        //设置Y轴坐标范围
        ui->widget->yAxis->setRange(0,3000);
        ui->widget_2->yAxis->setRange(0,3000);
        //在坐标轴右侧和上方画线,和X/Y轴一起形成一个矩形
        //ui->widget->axisRect()->setupFullAxesBox();
        //设置基本坐标轴(左侧Y轴和下方X轴)可拖动、可缩放、曲线可选、legend可选、设置伸缩比例,使所有图例可见
        ui->widget->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes |
                                          QCP::iSelectLegend | QCP::iSelectPlottables);
        ui->widget_2->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes |
                                          QCP::iSelectLegend | QCP::iSelectPlottables);
        //设定右上角图形标注可见
        //ui->widget->legend->setVisible(true);
        //设定右上角图形标注的字体
        //ui->widget->legend->setFont(QFont("Helvetica", 9));

        /*曲线0*/
        customplot1_add_graph();
        customplot2_add_graph();

        //draw test
//        for(int i=0;i<100;i++)
//        {
//            y0[0] = 2*i+1;
//            ui->widget->graph(0)->addData(x,y0);
//            x[0]=i;
//        }
}

void MainWindow::customplot1_add_graph()
{
    //添加图形
    ui->widget->addGraph();
    //设置画笔
    QPen pen0(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
    ui->widget->graph(0)->setPen(pen0);
    //ui->widget->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ScatterShape::ssPlus,5));
    //设置画刷,曲线和X轴围成面积的颜色
    //ui->widget->graph(0)->setBrush(QBrush(QColor(255,255,0)));
    //设置右上角图形标注名称
    ui->widget->graph(0)->setName("曲线");
    //传入数据,setData的两个参数类型为double
    //ui->widget->graph(0)->setLineStyle(QCPGraph::lsLine);//lsNone/lsLine/lsStepLeft/lsStepRight/lsStepCenter/lsImpulse
    //ui->widget->graph(0)->addData(x,y);
//    y0[0]=0;
//    ui->widget->graph(0)->setData(x,y0);
    //根据图像最高点最低点自动缩放坐标轴
    //Y轴
    //ui->widget->graph(0)->rescaleValueAxis(true);
    //X轴
    //ui->widget->graph(0)->rescaleKeyAxis(true);
    //X、Y轴
    //ui->widget->graph(0)->rescaleAxes(true);
}

void MainWindow::customplot2_add_graph()
{
    //添加图形
    ui->widget_2->addGraph();
    //设置画笔
    QPen pen0(Qt::blue, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
    ui->widget_2->graph(0)->setPen(pen0);
    //ui->widget->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ScatterShape::ssPlus,5));
    //设置画刷,曲线和X轴围成面积的颜色
    //ui->widget->graph(0)->setBrush(QBrush(QColor(255,255,0)));
    //设置右上角图形标注名称
    ui->widget_2->graph(0)->setName("曲线");
}

void MainWindow::slot_graph()
{
    for(int i=0;i<N;i++)
    {
        y0[i]=in[i][0];
        y1[i]=out[i][0];
    }

    ui->widget->graph(0)->setData(x,y0);
    ui->widget->replot();

    ui->widget_2->graph(0)->setData(x,y1);
    ui->widget_2->replot();
}

main.cpp不做解释

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"

char uart_buf[UART_BUF_SIZE];
uint16_t uart_buf_point=0;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    myserial(new serial)
{
    ui->setupUi(this);

    QStringList baudRate;
    baudRate<<"115200"<<"9600";
    ui->comboBox_2->addItems(baudRate);

    m_thread=new QThread;
    connect(m_thread,&QThread::started,this,
            [this]
    {
        qDebug()<<"thread started";
    },Qt::UniqueConnection);
    connect(m_thread,&QThread::finished,this,
            [this]
    {
        qDebug()<<"thread finished";
    },Qt::UniqueConnection);
    connect(m_thread,&QThread::destroyed,this,
            [this]
    {
        qDebug()<<"thread destroyed";
    },Qt::UniqueConnection);
    m_resolver=new resolver();
    m_resolver->moveToThread(m_thread);
    connect(m_thread, &QThread::finished, this, &QObject::deleteLater,Qt::UniqueConnection);
    connect(m_thread, &QThread::finished, m_thread, &QObject::deleteLater,Qt::UniqueConnection);
    connect(this,&MainWindow::start_resolver,m_resolver,&resolver::do_resolver,Qt::UniqueConnection);
    connect(m_resolver,&resolver::start_graph,this,&MainWindow::slot_graph,Qt::UniqueConnection);
    m_thread->start();
    emit start_resolver();

    //初始化graph
    graph_init();
}

MainWindow::~MainWindow()
{
    delete ui;
    delete myserial;
    delete m_resolver;
    m_thread->quit();
    m_thread->wait();
    delete m_thread;
}

/*搜索串口*/
void Main
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值