#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include < QDial >
#include < QSerialPort >
#include < QSerialPortInfo >
#include < QMainWindow >
#include "filterlpf.h"
#include "stat_proc.h"
#include "frequency_dom.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
// Port opening global. vars ..
QSerialPort *esp32;
filterLPF* LPF;
stat_proc* HIST;
stat_proc* HIST2;
frequency_dom* FFT;
QByteArray serialData;
QString serialBuffer;
QVector ti,s; // time, signal
QVector x_vec,y_vec; // processed time signal ...
QVector y_hist; // probability vector
QVector xf, yf; //
QVector x_b, y_b, t_b; // buffered measurement
// ESP32 specific IDENTIFICATION
static const int ESP32_VENDOR = 4292;
static const int ESP32_PID = 60000;
private slots:
int on_sliderMoved();
void on_submitPresets();
// serial related::
void scan_ports();
void read_serial_data();
void stop_serial_connection();
// plotting related::
void plot_rt_input(QVector, QVector);
void plot_rt_input_processed(QVector, QVector);
void plot_rt_hist(QVector,QVector);
void plot_rt_hist_2(QVector,QVector);
// action control
void interrupter();
// label setter
void set_hist_labels(double, double, double);
void on_pushButton_released();
};
#endif // MAINWINDOW_H
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->hSliderBaud->setMinimum(1);
ui->hSliderBaud->setMaximum(8);
ui->hSliderBaud->setValue(8);
//|||||||| Set Default Baud Rate to 115200
ui->lblBitRate->setText(QString("%1").arg(115200));
ui->edtBufferSize->setText("1800");
ui->edtVectorSize->setText("250");
ui->listWidget->addItem("Application ready... ");
// set dB slider
ui->dialSGain->setMinimum(-30);
ui->dialSGain->setMaximum(30);
ui->dialSGain->setValue(0);
//||| Initialize serial port...
//||| PLOT SETUPS
// setup the plot_1
ui->plot_1->addGraph(0);
ui->plot_1->graph(0)->setPen(QPen(Qt::darkBlue, 0.8));
ui->plot_2->addGraph(0);
ui->plot_2->graph(0)->setPen(QPen(Qt::darkRed, 0.7));
// MEASUREMENT SECTION
//BUFFERING
int BSize = ui->edtBufferSize->text().toInt(); // take the value from edit window
ui->pBarBuffering->setMinimum(0);
ui->pBarBuffering->setMaximum(BSize);
ui->radLPF->setAutoExclusive(false);
ui->radPP->setAutoExclusive(false);
ui->radHist->setAutoExclusive(false);
//|||||CONNECTIONS
connect(ui->hSliderBaud, SIGNAL(valueChanged(int)), SLOT(on_sliderMoved()));
connect(ui->cmdSubmit, SIGNAL(clicked()), SLOT(on_submitPresets()));
connect(ui->cmdStopSerial, SIGNAL(clicked()), SLOT(stop_serial_connection()));
}// end of constructor
MainWindow::~MainWindow()
{
delete ui;
delete esp32;
delete LPF;
delete FFT;
}
//[1] baud rate ..
int MainWindow::on_sliderMoved()
{
ui->listWidget->takeItem(ui->listWidget->currentRow());
// baud rate presets:
// {9600, 14400, 19200, 38400, 57600, 115200};
/*
QSerialPort::Baud1200 1200 1200 baud.
QSerialPort::Baud2400 2400 2400 baud.
QSerialPort::Baud4800 4800 4800 baud.
QSerialPort::Baud9600 9600 9600 baud.
QSerialPort::Baud19200 19200 19200 baud.
QSerialPort::Baud38400 38400 38400 baud.
QSerialPort::Baud57600 57600 57600 baud.
QSerialPort::Baud115200 115200 115200 baud.
*/
int baud[] = {1200, 2400, 4800, 9600, 19200, 38400, 57600,115200};
// reading baud rate from slider ..
int w = ui->hSliderBaud->value();
ui->lblBitRate->setText(QString("%1").arg(baud[w-1]));
int baudRate = baud[w-1];
// output to application window ...
QString output = "Baud rate has been set to: " + QString::number(baudRate) + " bits/s";
ui->listWidget->addItem(output);
return baud[w-1];
}
//[2] ... when serial setup is pressed ..
void MainWindow::on_submitPresets()
{
QString bufferSize = ui->edtBufferSize->text();
QString VectorSize = ui->edtVectorSize->text();
ui->listWidget->takeItem(ui->listWidget->currentRow());
QString output = "Number of symbols in a buffer: " + bufferSize+ " (signs)\n";
output +="Size of vector: " + VectorSize;
ui->listWidget->clear();
ui->listWidget->addItem(output);
on_sliderMoved();
scan_ports();
}
//[3] ... san the ports
void MainWindow::scan_ports()
{
qInfo()<<"ports scanning.. ";
/*
* TESTING CODE FOR OPEN PORTS
*/
qDebug() << "Descirption available ports:" << QSerialPortInfo::availablePorts().length() <<"\n";
foreach(const QSerialPortInfo& serialPortInfo, QSerialPortInfo::availablePorts() )
{
qDebug() << "||||||||||||||||||||||||||||||||||||||||Serial ports information: \n";
qDebug() << "No.of available ports:" << QSerialPortInfo::availablePorts().length();
qDebug() << "Has vendor ID :" << serialPortInfo.hasVendorIdentifier();
qDebug() << "Vendor ID :" << serialPortInfo.vendorIdentifier();
qDebug() << "Has Product ID :" << serialPortInfo.hasProductIdentifier();
qDebug() << "Product ID :" << serialPortInfo.productIdentifier();
}
QString port_info = "No. Available ports: " +QString::number( QSerialPortInfo::availablePorts().length());
foreach(const QSerialPortInfo& serialPortInfo, QSerialPortInfo::availablePorts() )
{
port_info += "\nHas vendor ID \t: " + QString::number( serialPortInfo.hasVendorIdentifier()) ;
port_info += "\nVendor \t: " + QString::number( serialPortInfo.vendorIdentifier());
port_info += "\nHas Product ID\t: " + QString::number( serialPortInfo.hasProductIdentifier());
port_info += "\nProduct ID\t: " + QString::number( serialPortInfo.productIdentifier());
}
ui->listWidget->addItem(port_info);
//|||| DETECT THE ESP32 MODEL
bool esp32_available =false;
QString espPortName;
// for each available of serial ports
foreach(const QSerialPortInfo& serialPortInfo, QSerialPortInfo::availablePorts())
{
if(serialPortInfo.hasProductIdentifier() && serialPortInfo.hasVendorIdentifier())
{ // if hardvare has vendor and product id
if(serialPortInfo.productIdentifier() == ESP32_PID && serialPortInfo.vendorIdentifier() == ESP32_VENDOR)
{ // confirm there is ESP 32 at the port
esp32_available = true;
qDebug() << "\t\t ESP 32 ... microcontroller found";
espPortName = serialPortInfo.portName();
qDebug() << "\t\t At the active port:" << espPortName;
ui->listWidget->addItem("ESP32 Found at port: " + espPortName);
}
}
}
//||| IF ESP32 HAS BEEN DETECTED
if(esp32_available)
{
// now open and configure ESP32 port ...
qDebug()<< "Found ESP port .. \n ";
int BRATE = on_sliderMoved();
qInfo()<<"Baud Rate : " << BRATE;
esp32 = new QSerialPort();
esp32->setPortName(espPortName);
esp32->open(QSerialPort::ReadOnly);
switch (BRATE)
{
case 1200: esp32->setBaudRate(QSerialPort::Baud1200);
break;
case 2400: esp32->setBaudRate(QSerialPort::Baud2400);
break;
case 4800: esp32->setBaudRate(QSerialPort::Baud4800);
break;
case 9600: esp32->setBaudRate(QSerialPort::Baud9600);
break;
case 19200: esp32->setBaudRate(QSerialPort::Baud19200);
break;
case 38400: esp32->setBaudRate(QSerialPort::Baud38400);
break;
case 57600: esp32->setBaudRate(QSerialPort::Baud57600);
break;
case 115200: esp32->setBaudRate(QSerialPort::Baud115200);
break;
default:
esp32->setBaudRate(QSerialPort::Baud115200);
break;
}
esp32->setDataBits(QSerialPort::Data8);
esp32->setFlowControl(QSerialPort::NoFlowControl);
esp32->setParity(QSerialPort::NoParity);
esp32->setStopBits(QSerialPort::OneStop);
//|||NOW START READING DATA
QObject::connect(esp32, SIGNAL(readyRead()), this, SLOT(read_serial_data())); //| this is where you call readSerial()
LPF = new filterLPF();
//LPF->pingMe();
// histogram processing
HIST = new stat_proc();
HIST2 = new stat_proc();
ui->plot_3->addGraph();
ui->plot_3->addGraph();
ui->plot_4->addGraph();
// this par was never utilized ...
FFT = new frequency_dom();
}
else
{
qDebug() << "Could not find the correct port for esp \n ";
QMessageBox::information(this, "Serial Port Error", "Couldn't open seral port of a device ... ");
}
} //:: end of fn
//[4] Real- time processing
//|||||||||||||
//|||||||||||||
//|||||||||||||
//|||||||||||||
//|||||||||||||
void MainWindow::read_serial_data()
{
// PRESETS
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// SET LABEL TO Input processing plot
if(ui->radPP->isChecked()){ ui->lblInputProc->setText("ON");}
else if( !ui->radLPF->isChecked()){ui->lblInputProc->setText("OFF");}
// RED THE GAIN
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
double gain = ui->dialSGain->value(); //| gain in dB
ui->lblGain->setText(QString::number(gain)); //| set the user input to the screen
clock_t c1, c2; // start the clock
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//|||| Buffer size is set in UI and here is to be read again ...
QString b_size = ui->edtBufferSize->text();
int BUFFER_SIZE = b_size.toDouble();
//||| int CLR_L= ui->lblValuesBuffer->text().toInt(); // when to pop front the value from the vectro
QString clr_l = ui->edtVectorSize->text();
int clear_size = clr_l.toInt();
serialData = esp32->readAll();
serialBuffer += QString::fromStdString(serialData.toStdString()); //| accumulating to buffer
static int i = 0; //| static counter of buffers
static int j = 0; //| static counter of index values in a buffer
c1 = clock(); // sart clock
//|||| BUFFERING TO BUFFER SIZE
if(serialBuffer.size()>BUFFER_SIZE)
{ i++; // count the buffers in total
QStringList li = serialBuffer.split("*"); // splitting sign
// read how many symbols are in the buffer and plot to UI
ui->lblBuffer->setText(QString::number(serialBuffer.length()));
ui->lblValuesBuffer->setText(QString::number(li.length()));
ui->lblCountBuffers->setText(QString::number(i));
// Push the values from the list to vectors
for(int k = 0; k < li.length(); k++)
{
double value = li[k].toDouble();
//=========================================================================================
//| POST PROCESSING CHAIN
//|........................................................................................
//|
//| o----->| GAIN | o----> | Sampling FREQ| o----> | LPF | o---> | STAT |
//|
//=========================================================================================
if(ui->radPP->isChecked())
{
//|| "X -Axis"
//|| IF TIME DOMAIN ON/OFF ...
if(ui->radTimSignal->isChecked())
{
ui->lblDom->setText("time");
double dt = 1/ ui->edtFS->text().toDouble();
x_vec.push_back((double)j*dt);
}else if(ui->radTimSignal->isCheckable())
{
ui->lblDom->setText("samples");
x_vec.push_back((double)j);
}
//|| "Y - Axis"
//|| FOR SIGNAL Filtering ...
//|| checek weather checke: if filter is on ... and if cutoff frequency is provided
double gain_db = ui->dialSGain->value();
ui->lcdRead->display(QString::number(gain_db));
double GAIN = pow(10,gain_db/10.0);
// FILTER LPF
if(ui->radLPF->isChecked() &&
ui->edtFC->text().isEmpty() == false &&
ui->edtFS->text().isEmpty()==false)
{
double fc, fs, f_value;
// pick up the value from the UI
fc = ui->edtFC->text().toDouble();
// entered by the user ...
fs = ui->edtFS->text().toDouble();
// filtering of a signal
LPF->setCoeffs(fc, fs);
f_value = LPF->filter(value, fc, fs);
y_vec.push_back( LPF->gain(f_value,GAIN));
//|| - STATISTICAL MEASUREMENT PROCESSING ...
//||
//|| FOR STAT PROCESSING:: UI - Inputs taken
//||
//||=========================================================================================
double min, max, N;
// show the inputs ..........................................
N = ui->edtStatN->text().toDouble();
min = ui->edtStatMIN->text().toDouble();
max = ui->edtStatMAX->text().toDouble();
// show the inputs to parameter labels
ui->lbl_stat_classes->setText(QString::number(N));
ui->lbl_stat_min->setText(QString::number(min));
ui->lbl_stat_max->setText(QString::number(max));
// calculate class and step 'd'
double span = max - min;
double d = span/N;
// show class and step to parameter labels
ui->lblHSpan ->setText(QString::number(span));
ui->lblCWidth->setText(QString::number(d));
//||=========================================================================================
//|| do statistics on filtered values ...
double val = LPF->gain(f_value,GAIN);
ui->lblBuffFull->setText(QString::number(HIST->x.size()));
if(ui->radHist->isChecked())
{
set_hist_labels(N, min, max);
double buff_max = ui->edtSamples->text().toDouble(); // buffer maximum
ui->pBarBuffering->setMaximum(buff_max);
//HIST->hist(val, ui->edtStatN->text().toDouble(), min, max);
HIST2->hist(val, ui->edtStatN->text().toDouble(), min, max);
ui->pBarBuffering->setValue(HIST2->x.size());
if(buff_max == HIST2->x.length())
{
interrupter();
}
else if(HIST2->x.length() > buff_max) // if number exceeds the given size .. clean hist vector "NAsty error !"
{
HIST2->x.clear();
HIST2->h.clear();
}
}else if(ui->radHist->isCheckable()) // when measurement turned off , clean histogram vectors
{
HIST2->x.clear();
HIST2->h.clear();
}
}
else
{
//|| Only processing is on ...ie. GAIN/ NO FILTERING
//||
//||=========================================================================================
y_vec.push_back( value*GAIN);
//|| take the user values from UI
double N = ui->edtStatN->text().toDouble(); // take number of bins
double min = ui->edtStatMIN->text().toDouble(); // take minimum
double max = ui->edtStatMAX->text().toDouble(); // take maximum
double buff_max = ui->edtSamples->text().toDouble(); // buffer maximum
set_hist_labels(N, min, max); // set them around the plot_3
if(ui->radHist->isChecked())
{
HIST->hist(value*GAIN, N, min, max);
ui->lblBuffFull->setText(QString::number(HIST->x.size()));
ui->pBarBuffering->setMaximum(buff_max);
ui->pBarBuffering->setValue(HIST->x.size());
// when buffer is filled
if(buff_max == HIST->x.length())
{
// interrupt all, to plot and clear vectors
// reconnect.. then proceed
interrupter();
}
else if(HIST->x.length() > buff_max)
{
HIST->x.clear();
HIST->h.clear();
}
}
else if(ui->radHist->isCheckable())
{
HIST->x.clear();
HIST->h.clear();
}
}
// CLEAN VECTORS WHEN FULL
if(x_vec.length()>clear_size && y_vec.length()>clear_size)
{
x_vec.pop_front();
y_vec.pop_front();
}
}
else if(ui->radPP->isCheckable())
{
// if pre-processing has been turned off ...
ui->lblDom->setText("samples");
}
//=========================================================================================
// NON PROCESSED VALUES
//=========================================================================================
s.push_back(value);
j++; // push the signal value to the vector 's'
ti.push_back((double)j); // write an index to the time vector
if(s.length()>clear_size && ti.length()>clear_size)
{
s.pop_front();
ti.pop_front();
}
}// end of vector manipulations ...
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//||| BUFFER CLEANING
serialBuffer.clear();
li.clear();
//||| CLOCK measurment end/ time for a buffer ...
c2 = clock();
double t_buffer = (double)(c2-c1)/CLOCKS_PER_SEC;
ui->lblBtime->setText(QString::number(t_buffer));
//||| Plotting the results to plot_1
plot_rt_input(ti, s);
// if radio button is checked .. plot either same inputs
// either processed rt inputs ...
if( ui->radPP->isChecked()){
plot_rt_input_processed(x_vec,y_vec);
}else if(!ui->radPP->isChecked())
{
plot_rt_input_processed(ti,s);
}
}
}
//||| CLOSE SERIAL CONNECTION
void MainWindow::stop_serial_connection()
{
esp32->close(); // close the port
if(HIST != nullptr)
{
delete HIST;
qInfo()<< "Histogram deleted...";
}
if(HIST2 != nullptr)
{
delete HIST2;
qInfo()<< "Histogram 2 deleted...";
}
if(LPF!= nullptr)
{
qInfo()<< "LPF deleted";
delete LPF;
}
if(esp32 != nullptr)
{
qInfo()<< "port deleted";
delete esp32;
}
if(FFT != nullptr)
{
qInfo()<<"frequency domain object deleted ... ";
delete FFT;
}
ti.clear();
s.clear();
ui->listWidget->clear();
ui->listWidget->addItem("Serial connection stopped... ");
}
// INTERRUPTER OF MEASUREMENT ...
void MainWindow::interrupter()
{
esp32->close();
if(!HIST->x.isEmpty()) // ako je histogram 1 pun, isplotaj, pobrisi ga
{
//qInfo()<<"Highest histogram value is befor plotting :" << HIST->histMaxVal();
plot_rt_hist(HIST->x, HIST->h);
HIST->x.clear();
HIST->h.clear();
}
if(! HIST2->x.isEmpty())
{ // HIST 2 has been used
//plot_rt_hist_2(HIST->x, HIST->h);
plot_rt_hist_2(HIST2->x, HIST2->h);
HIST->x.clear();
HIST->h.clear();
}
scan_ports();
}
// PLOTTING FUNCTIONS void MainWindow::plot_rt_input(QVectorti, QVector s) { ui->plot_1->graph(0)->setData(ti, s); ui->plot_1->xAxis2->setVisible(true); ui->plot_1->xAxis2->setTickLabels(false); ui->plot_1->yAxis2->setVisible(true); ui->plot_1->yAxis2->setTickLabels(false); ui->plot_1->yAxis->setLabel("Input: x"); ui->plot_1->xAxis->setLabel("[sample] "); ui->plot_1->rescaleAxes(); double max_val = *std::max_element(s.constBegin(), s.constEnd()); ui->plot_1->yAxis->setRange(-3*max_val, 3*max_val); ui->plot_1->replot(); ui->plot_1->update(); } void MainWindow::plot_rt_hist(QVector x, QVector h ) { ui->plot_3->graph(0)->setData(x, h); ui->plot_3->graph(0)->setLineStyle((QCPGraph::LineStyle)2); ui->plot_3->xAxis2->setVisible(true); ui->plot_3->xAxis2->setTickLabels(false); ui->plot_3->yAxis2->setVisible(true); ui->plot_3->yAxis2->setTickLabels(false); ui->plot_3->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); ui->plot_3->legend->setVisible(false); ui->plot_3->yAxis->setLabel("Histogram"); ui->plot_3->xAxis->setLabel(" "); ui->plot_3->rescaleAxes(); ui->plot_3->yAxis->setRange(-0.1*HIST->histMaxVal(), HIST->histMaxVal()*1.2); ui->plot_3->replot(); ui->plot_3->update(); } void MainWindow:: plot_rt_hist_2(QVector x,QVector h) { ui->plot_4->graph(0)->setPen(QPen(Qt::red)); ui->plot_4->graph(0)->setData(x, h); ui->plot_4->graph(0)->setLineStyle((QCPGraph::LineStyle)2); ui->plot_4->xAxis2->setVisible(true); ui->plot_4->xAxis2->setTickLabels(false); ui->plot_4->yAxis2->setVisible(true); ui->plot_4->yAxis2->setTickLabels(false); ui->plot_4->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); ui->plot_4->legend->setVisible(false); ui->plot_4->yAxis->setLabel("Histogram"); ui->plot_4->xAxis->setLabel(" "); ui->plot_4->rescaleAxes(); ui->plot_4->yAxis->setRange(-0.1*HIST2->histMaxVal(), HIST2->histMaxVal()*1.2); ui->plot_4->replot(); ui->plot_4->update(); } void MainWindow::plot_rt_input_processed(QVector x, QVector y) { ui->plot_2->graph(0)->setData(x, y); ui->plot_2->xAxis2->setVisible(true); ui->plot_2->xAxis2->setTickLabels(false); ui->plot_2->yAxis2->setVisible(true); ui->plot_2->yAxis2->setTickLabels(false); ui->plot_2->yAxis->setLabel("Output: y"); ui->plot_2->xAxis->setLabel(ui->lblDom->text()+"[s]"); double max_val = *std::max_element(s.constBegin(), s.constEnd()); ui->plot_2->rescaleAxes(); ui->plot_2->yAxis->setRange(-3*max_val, 3*max_val); ui->plot_2->replot(); ui->plot_2->update(); } void MainWindow::set_hist_labels(double N, double min, double max) { double span = max - min; ui->lblHSpan->setText(QString::number(span)); ui->lbl_stat_classes->setText(QString::number(N)); ui->lbl_stat_min->setText(QString::number(min)); ui->lbl_stat_max->setText(QString::number(max)); ui->lblCWidth->setText(QString::number(span/N)); } void MainWindow::on_pushButton_released() { MainWindow::close(); }
#ifndef FILTERLPF_H
#define FILTERLPF_H
#include < Object >
#include < QDebug >
// filter coefficients for BIQUAD type
struct Coeff
{
double a1,a2;
double b0,b1,b2;
};
// difference equation of a filter ...
struct DEQ
{
//set up the coefficients
double b0,b1,b2;
double a1,a2;
// set up the x[n-1], x[n-2] ...
double x1,x2;
double y0,y1,y2;
double process(const Coeff& fltCoeff, double x0)
{
// read in the coefficients
b0 = fltCoeff.b0;
b1 = fltCoeff.b1;
b2 = fltCoeff.b2;
a1 = fltCoeff.a1;
a2 = fltCoeff.a2;
y0 = b0*x0 + b1*x1 + b2*x2 - a1*y1 -a2*y2;
x2 = x1;
x1 = x0;
y2 = y1;
y1 = y0;
return y0;
}
};
// filterLPF called from the heap ...
class filterLPF : public QObject
{
Q_OBJECT
private:
#define PI 3.14159265358979323846;
double a1,a2;
double b0,b1,b2;
public:
explicit filterLPF(QObject *parent = nullptr); // constructor
Coeff coeff; // has one structure of coefficients
DEQ diffEq; // has one difference equation biquad system
Coeff LPF_butter(double, double); // returns full filter structure
void setCoeffs(double, double); // sets coefficients
void getCoeffs(); // types the coefficients to console
// run the difference equation
double gain(double x0, double gain); // gain the signal after filtering
double filter(double x0, double, double); // utilize the whole filter
};
/* inside of MAIN thread ... use this as follows
* Application note...
*
* #include "filterlpf.h"
*
*
* // create somwhere ...
filterLPF* LPF = new FilteLPF();
LPF->setCoeffs(10, 1e3);
LPF->getCoeffs(); // if to be noticed
some loop ...should take place for utilizing difference equation ...
while()
{
double x = sin(12*PI*f*dt);
double y1 = LPF-> filter(x, 10, 1e3); fitler the signal
double y2 = LPF->gain(f_value,GAIN); amplify the stuff ..
}
delete LPF;
*/
#endif // FILTERLPF_H
#include "filterLPF.h"
#include < cmath >
filterLPF::filterLPF(QObject *parent) : QObject(parent)
{
qInfo()<< "Filter Object has been created";
}
//||||| Calculate coefficients for the butterworth filter
Coeff filterLPF::LPF_butter(double fc, double fs)
{
Coeff LPF;
const double ita =1.0/ tan(M_PI*fc/fs);
const double q=sqrt(2.0);
LPF.b0 = 1.0 / (1.0 + q*ita + ita*ita);
LPF.b1 = 2*LPF.b0;
LPF.b2 = LPF.b0;
LPF.a1 = -2.0 * (ita*ita - 1.0) * LPF.b0;
LPF.a2 = (1.0 - q*ita + ita*ita) * LPF.b0;
return LPF;
}
//||||| Set cofficients
void filterLPF::setCoeffs(double fc, double fs)
{
Coeff K = LPF_butter( fc, fs);
a1 = K.a1;
a2 = K.a2;
b0 = K.b0;
b1 = K.b1;
b2 = K.b2;
}
// GET Coefficients
void filterLPF::getCoeffs()
{
qInfo()<< "a1" << this->a1;
qInfo()<< "a2" << this->a2;
qInfo()<< "b0" << this->b1;
qInfo()<< "b1" << this->b1;
qInfo()<< "b2" << this->b2;
}
// LPF utilization
double filterLPF::filter(double x0, double fc, double fs)
{
return diffEq.process(LPF_butter(fc,fs), x0);
}
// GAINs the signal ...
double filterLPF::gain(double x0, double factor)
{
double y0 = x0*factor;
return y0;
}
#ifndef STAT_PROC_H
#define STAT_PROC_H
#include < QObject >
// now push the value throught the whole class ...
// and count the correspondent number within each
/*
* histogram builder .. .
i=0, 0-1 : * | bin_l = 0 | bin_h = 1 | d = 1 |
1-2 : **** | bin_l = 1 | bin_h = 2 | d = 1 |
2-3 : *********
3-4 : ***************
4-5 : ******************
i*d, 5-6 : *******************
6-7 : ***************
7-8 : ********
8-9 : ****
i=N, 9-10: *
*
*/
class stat_proc : public QObject
{
Q_OBJECT
public:
QVector<double > // histogram values ...
QVector<double > x; // bin centers ..
double min, max, d, N;
explicit stat_proc(QObject *parent = nullptr);
void sayHello(); // ping and prove class exists ..
void hist(double,
int,
double,
double); // return histogram values to the
double histMaxVal(); // return maximum value of histogram
void typeHist(); // put the results into console...
};
#endif // STAT_PROC_H
#include "stat_proc.h"
#include < QDebug >
#include < iostream >
stat_proc::stat_proc(QObject *parent) : QObject(parent)
{
x.clear();
h.clear();
}
void stat_proc::sayHello()
{
qInfo() << "Stat processor has been initialized.... ";
}
// histogram of values given to the ...
void stat_proc::hist(double val, int N, double min, double max)
{
double span = max - min;
double d = span/N;
this->min = min;
this->max = max;
this->d = d;
this->N = N;
// fill the global vector h with zeros ..
for(int i = 0; i < N; i++)
{
h.push_back(0.00);
}
double bin_l, bin_h, cbin;
for(int i = 0; i < N; i++)
{
bin_l = min + i*d; // bin lower edge
bin_h = bin_l +d; // bin higher edge
cbin = (bin_h +bin_l) /2.0; // cbin .. center of bins ...
x.push_back(cbin);
if(val >= bin_l && val< bin_h)
{
h[i] += 1;
}
}
}
// type histogram from ...
void stat_proc::typeHist()
{
double bin_h,bin_l, cbin;
static int q = 0;
q++;
if(q==1)
{
qInfo() << "-------------------------------------------------";
qInfo() << "N :" << this->N ;
qInfo() << "min :" << this->min;
qInfo() << "max :" << this->max;
qInfo() << "step:" << this->d;
qInfo() << "-------------------------------------------------";
}
for(int i = 0; isayHello();
HIST->hist(2.8, 20, -5, 5);
HIST->hist(2.6, 20, -5, 5);
HIST->hist(2.67, 20, -5, 5);
HIST->hist(4.77, 20, -5, 5);
HIST->typeHist();
*
*
*
Stat processor has been initialized....
After streaming ::
-------------------------------------------------
N : 20
min : -5
max : 5
step: 0.5
-------------------------------------------------
-------------------------------------------------
1 | -5 : -4.5 || -4.75 3 ||
2 | -4.5 : -4 || -4.25 3 ||
3 | -4 : -3.5 || -3.75 3 ||
4 | -3.5 : -3 || -3.25 2 ||
5 | -3 : -2.5 || -2.75 3 ||
6 | -2.5 : -2 || -2.25 4 ||
7 | -2 : -1.5 || -1.75 18 ||
8 | -1.5 : -1 || -1.25 202 ||
9 | -1 : -0.5 || -0.75 711 ||
10 | -0.5 : 0 || -0.25 1552 ||
11 | 0 : 0.5 || 0.25 1880 ||
12 | 0.5 : 1 || 0.75 1333 ||
13 | 1 : 1.5 || 1.25 417 ||
14 | 1.5 : 2 || 1.75 74 ||
15 | 2 : 2.5 || 2.25 10 ||
16 | 2.5 : 3 || 2.75 7 ||
17 | 3 : 3.5 || 3.25 8 ||
18 | 3.5 : 4 || 3.75 3 ||
19 | 4 : 4.5 || 4.25 9 ||
20 | 4.5 : 5 || 4.75 5 ||
*/
(Reason: single thread cannot handle it anymore, it chockes the process .. )
#ifndef FREQUENCY_DOM_H
#define FREQUENCY_DOM_H
#include < QObject >
#include < complex >
#include < iostream >
#include < valarray >
#include < vector >
#include < cmath >
using namespace std;
class frequency_dom : public QObject
{
Q_OBJECT
public:
explicit frequency_dom(QObject *parent = nullptr);
const double PI_ = 3.141592653589793238460;
QVector < double > f;
QVector < double > y;
void dft();
};
#endif // FREQUENCY_DOM_H
#include "frequency_dom.h"
#include < QDebug >
frequency_dom::frequency_dom(QObject *parent) : QObject(parent)
{
}
void frequency_dom::dft()
{
// defintely need FFT here ... something fast
// non of three procedure here has been working fast enough .. what to do ... threads ?
// see here: FFT Candidates
// ( that did not pass the test ... and I did not use timers ! :< )
}