Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
GPA.cpp
- Committer:
- pmic
- Date:
- 2018-03-17
- Revision:
- 7:87b823282bf0
- Parent:
- 6:da0c9587ecae
- Child:
- 8:d68e177e2571
File content as of revision 7:87b823282bf0:
#include "GPA.h"
#include "mbed.h"
#include "math.h"
#define pi 3.1415927f
using namespace std;
GPA::GPA(float fMin, float fMax, int NfexcDes, int NperMin, int NmeasMin, float Ts, float Aexc0, float Aexc1)
{
this->NfexcDes = NfexcDes;
this->NperMin = NperMin;
this->NmeasMin = NmeasMin;
this->Ts = Ts;
// calculate logarithmic spaced frequency points
fexcDes = (float*)malloc(NfexcDes*sizeof(float));
fexcDesLogspace(fMin, fMax, NfexcDes);
// calculate coefficients for decreasing amplitude (1/fexc)
this->aAexcDes = (Aexc1 - Aexc0)/(1.0f/fexcDes[NfexcDes-1] - 1.0f/fexcDes[0]);
this->bAexcDes = Aexc0 - aAexcDes/fexcDes[0];
fnyq = 1/2.0f/Ts;
pi2 = 2.0f*pi;
pi2Ts = pi2*Ts;
piDiv2 = pi/2.0f;
sU = (float*)malloc(3*sizeof(float));
sY = (float*)malloc(3*sizeof(float));
reset();
}
GPA::~GPA() {}
void GPA::reset()
{
Nmeas = 0;
Nper = 0;
fexc = 0.0f;
fexcPast = 0.0f;
ii = 1; // iterating through desired frequency points
jj = 1; // iterating through measurement points w.r.t. reachable frequency
scaleG = 0.0f;
cr = 0.0f;
ci = 0.0f;
for(int i = 0; i < 3; i++) {
sU[i] = 0.0f;
sY[i] = 0.0f;
}
sinarg = 0.0f;
NmeasTotal = 0;
Aexc = 0.0f;
pi2Tsfexc = 0.0f;
}
float GPA::update(float inp, float out)
{
// a new frequency point has been reached
if(jj == 1) {
// get a new unique frequency point
while(fexc == fexcPast) {
// measurement finished
if(ii > NfexcDes) {
return 0.0f;
}
calcGPAmeasPara(fexcDes[ii - 1]);
// secure fexc is not higher or equal to nyquist frequency
if(fexc >= fnyq) {
fexc = fexcPast;
}
// no frequency found
if(fexc == fexcPast) {
ii += 1;
} else {
Aexc = aAexcDes/fexc + bAexcDes;
pi2Tsfexc = pi2Ts*fexc;
}
}
fexcPast = fexc;
// filter scaling
scaleG = 1.0f/sqrt((float)Nmeas);
// filter coefficients
cr = cos(pi2Tsfexc);
ci = sin(pi2Tsfexc);
// filter storage
for(int i = 0; i < 3; i++) {
sU[i] = 0.0f;
sY[i] = 0.0f;
}
}
// filter step for signal su
sU[0] = scaleG*inp + 2.0f*cr*sU[1] - sU[2];
sU[2] = sU[1];
sU[1] = sU[0];
// filter step for signal sy
sY[0] = scaleG*out + 2.0f*cr*sY[1] - sY[2];
sY[2] = sY[1];
sY[1] = sY[0];
// measurement of frequencypoint is finished
if(jj == Nmeas) {
jj = 1;
ii += 1;
// calculate the one point dft
float Ureal = 2.0f*scaleG*(cr*sU[1] - sU[2]);
float Uimag = 2.0f*scaleG*ci*sU[1];
float Yreal = 2.0f*scaleG*(cr*sY[1] - sY[2]);
float Yimag = 2.0f*scaleG*ci*sY[1];
// calculate magnitude and angle
float Umag = sqrt(Ureal*Ureal + Uimag*Uimag);
float Ymag = sqrt(Yreal*Yreal + Yimag*Yimag);
float absGyu = Ymag/Umag;
float angGyu = atan2(Yimag, Yreal) - atan2(Uimag, Ureal);
float absGye = Ymag/Aexc;
float angGye = (atan2(Yimag, Yreal) + piDiv2);
// user info
if(ii == 1) {
printLine();
printf(" fexc[Hz] |Gyu| ang(Gyu) |Gye| ang(Gye) |E| |U| |Y|\r\n");
printLine();
}
printf("%11.2e %10.2e %10.2e %10.2e %10.2e %10.2e %10.2e %10.2e\r\n", fexc, absGyu, angGyu, absGye, angGye, Aexc, Umag, Ymag);
} else {
jj += 1;
}
sinarg = fmod(sinarg + pi2Tsfexc, pi2);
NmeasTotal += 1;
return Aexc*sin(sinarg);
}
void GPA::fexcDesLogspace(float fMin, float fMax, int NfexcDes)
{
// calculate logarithmic spaced frequency points
float Gain = log10(fMax/fMin)/((float)NfexcDes - 1.0f);
float expon = 0.0f;
for(int i = 0; i < NfexcDes; i++) {
fexcDes[i] = fMin*pow(10.0f, expon);
expon += Gain;
}
}
void GPA::calcGPAmeasPara(float fexcDes_i)
{
// Nmeas has to be an integer
Nper = NperMin;
Nmeas = (int)floor((float)Nper/fexcDes_i/Ts + 0.5f);
// secure that the minimal number of measurements is fullfilled
int Ndelta = NmeasMin - Nmeas;
if(Ndelta > 0) {
Nper = (int)ceil((float)NmeasMin*fexcDes_i*Ts);
Nmeas = (int)floor((float)Nper/fexcDes_i/Ts + 0.5f);
}
// evaluating reachable frequency
fexc = (float)Nper/(float)Nmeas/Ts;
}
void GPA::printLine()
{
printf("-----------------------------------------------------------------------------------------\r\n");
}
void GPA::printGPAfexcDes()
{
printLine();
for(int i = 0; i < NfexcDes; i++) {
printf("%9.4f\r\n", fexcDes[i]);
}
}
void GPA::printGPAmeasPara()
{
printLine();
printf(" fexcDes[Hz] fexc[Hz] Aexc Nmeas Nper\r\n");
printLine();
for(int i = 0; i < NfexcDes; i++) {
calcGPAmeasPara(fexcDes[i]);
if(fexc == fexcPast || fexc >= fnyq) {
fexc = 0.0f;
Nmeas = 0;
Nper = 0;
Aexc = 0;
} else {
Aexc = aAexcDes/fexc + bAexcDes;
fexcPast = fexc;
}
NmeasTotal += Nmeas;
printf("%12.2e %9.2e %10.2e %7i %6i \r\n", fexcDes[i], fexc, Aexc, Nmeas, Nper);
}
printGPAmeasTime();
reset();
}
void GPA::printGPAmeasTime()
{
printLine();
printf(" number of data points: %9i\r\n", NmeasTotal);
printf(" measurment time in sec: %9.2f\r\n", (float)NmeasTotal*Ts);
}