Added parameter numPeriod so that the user can select the number of fundamental frequency periods used in the detection of the fundamental frequency and its harmonics. This is usefull when trying to recover the fundamental frequency and its harmonics from a noisy signal, like the output of a DCDC converter
This commit is contained in:
parent
b1f215149e
commit
04507a637d
|
|
@ -23,7 +23,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
|
||||||
|
|
||||||
|
|
||||||
static char *pnum(double num);
|
static char *pnum(double num);
|
||||||
static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Value,
|
static int CKTfour(int ndata, int numFreq, int numPeriod, double *thd, double *Time, double *Value,
|
||||||
double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag,
|
double FundFreq, double *Freq, double *Mag, double *Phase, double *nMag,
|
||||||
double *nPhase);
|
double *nPhase);
|
||||||
|
|
||||||
|
|
@ -32,8 +32,8 @@ static int CKTfour(int ndata, int numFreq, double *thd, double *Time, double *Va
|
||||||
#define DEF_FOURGRIDSIZE 200
|
#define DEF_FOURGRIDSIZE 200
|
||||||
|
|
||||||
|
|
||||||
/* CKTfour(ndata, numFreq, thd, Time, Value, FundFreq, Freq, Mag, Phase, nMag, nPhase)
|
/* CKTfour(ndata, numFreq, numPeriod, thd, Time, Value, FundFreq, Freq, Mag, Phase, nMag, nPhase)
|
||||||
* len 10 ? inp inp inp out out out out out
|
* len 10 1 ? inp inp inp out out out out out
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -42,7 +42,7 @@ fourier(wordlist *wl, struct plot *current_plot)
|
||||||
struct dvec *time, *vec;
|
struct dvec *time, *vec;
|
||||||
struct pnode *pn, *names;
|
struct pnode *pn, *names;
|
||||||
double fundfreq, *data = NULL;
|
double fundfreq, *data = NULL;
|
||||||
int nfreqs, fourgridsize, polydegree;
|
int nfreqs, nperiods, fourgridsize, polydegree;
|
||||||
double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */
|
double *freq, *mag, *phase, *nmag, *nphase; /* Outputs from CKTfour */
|
||||||
double thd, *timescale = NULL;
|
double thd, *timescale = NULL;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
@ -68,6 +68,8 @@ fourier(wordlist *wl, struct plot *current_plot)
|
||||||
|
|
||||||
if (!cp_getvar("nfreqs", CP_NUM, &nfreqs, 0) || nfreqs < 1)
|
if (!cp_getvar("nfreqs", CP_NUM, &nfreqs, 0) || nfreqs < 1)
|
||||||
nfreqs = 10;
|
nfreqs = 10;
|
||||||
|
if (!cp_getvar("nperiods", CP_NUM, &nperiods, 0) || nperiods < 1)
|
||||||
|
nperiods = 1;
|
||||||
if (!cp_getvar("polydegree", CP_NUM, &polydegree, 0) || polydegree < 0)
|
if (!cp_getvar("polydegree", CP_NUM, &polydegree, 0) || polydegree < 0)
|
||||||
polydegree = 1;
|
polydegree = 1;
|
||||||
if (!cp_getvar("fourgridsize", CP_NUM, &fourgridsize, 0) || fourgridsize < 1)
|
if (!cp_getvar("fourgridsize", CP_NUM, &fourgridsize, 0) || fourgridsize < 1)
|
||||||
|
|
@ -112,14 +114,16 @@ fourier(wordlist *wl, struct plot *current_plot)
|
||||||
|
|
||||||
if (polydegree) {
|
if (polydegree) {
|
||||||
double *dp, d;
|
double *dp, d;
|
||||||
|
/* Get fourgridsize points per period */
|
||||||
|
fourgridsize = fourgridsize * nperiods;
|
||||||
/* Build the grid... */
|
/* Build the grid... */
|
||||||
timescale = TMALLOC(double, fourgridsize);
|
timescale = TMALLOC(double, fourgridsize);
|
||||||
data = TMALLOC(double, fourgridsize);
|
data = TMALLOC(double, fourgridsize);
|
||||||
dp = ft_minmax(time, TRUE);
|
dp = ft_minmax(time, TRUE);
|
||||||
/* Now get the last fund freq... */
|
/* Now get the last fund freq... */
|
||||||
d = 1 / fundfreq; /* The wavelength... */
|
d = nperiods / fundfreq; /* The wavelength... */
|
||||||
if (dp[1] - dp[0] < d) {
|
if (dp[1] - dp[0] < d) {
|
||||||
fprintf(cp_err, "Error: wavelength longer than time span\n");
|
fprintf(cp_err, "Error: (%d * wavelength) longer than time span\n", nperiods);
|
||||||
goto done;
|
goto done;
|
||||||
} else if (dp[1] - dp[0] > d) {
|
} else if (dp[1] - dp[0] > d) {
|
||||||
dp[0] = dp[1] - d;
|
dp[0] = dp[1] - d;
|
||||||
|
|
@ -143,7 +147,7 @@ fourier(wordlist *wl, struct plot *current_plot)
|
||||||
timescale = time->v_realdata;
|
timescale = time->v_realdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = CKTfour(fourgridsize, nfreqs, &thd, timescale,
|
err = CKTfour(fourgridsize, nfreqs, nperiods, &thd, timescale,
|
||||||
data, fundfreq, freq, mag, phase, nmag,
|
data, fundfreq, freq, mag, phase, nmag,
|
||||||
nphase);
|
nphase);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
|
|
@ -153,9 +157,10 @@ fourier(wordlist *wl, struct plot *current_plot)
|
||||||
|
|
||||||
fprintf(cp_out, "Fourier analysis for %s:\n", vec->v_name);
|
fprintf(cp_out, "Fourier analysis for %s:\n", vec->v_name);
|
||||||
fprintf(cp_out,
|
fprintf(cp_out,
|
||||||
" No. Harmonics: %d, THD: %g %%, Gridsize: %d, Interpolation Degree: %d\n\n",
|
" No. Harmonics: %d, THD: %g %%, Gridsize: %d, Interpolation Degree: %d,"
|
||||||
|
" No. Periods: %d\n\n",
|
||||||
nfreqs, thd, fourgridsize,
|
nfreqs, thd, fourgridsize,
|
||||||
polydegree);
|
polydegree, nperiods);
|
||||||
/* Each field will have width cp_numdgt + 6 (or 7
|
/* Each field will have width cp_numdgt + 6 (or 7
|
||||||
* with HP-UX) + 1 if there is a - sign.
|
* with HP-UX) + 1 if there is a - sign.
|
||||||
*/
|
*/
|
||||||
|
|
@ -288,6 +293,7 @@ static int
|
||||||
CKTfour(int ndata, /* number of entries in the Time and
|
CKTfour(int ndata, /* number of entries in the Time and
|
||||||
Value arrays */
|
Value arrays */
|
||||||
int numFreq, /* number of harmonics to calculate */
|
int numFreq, /* number of harmonics to calculate */
|
||||||
|
int numPeriod, /* number of periods for detection */
|
||||||
double *thd, /* total harmonic distortion (percent)
|
double *thd, /* total harmonic distortion (percent)
|
||||||
to be returned */
|
to be returned */
|
||||||
double *Time, /* times at which the voltage/current
|
double *Time, /* times at which the voltage/current
|
||||||
|
|
@ -313,10 +319,10 @@ CKTfour(int ndata, /* number of entries in the Time and
|
||||||
* The arrays must all be allocated by the caller.
|
* The arrays must all be allocated by the caller.
|
||||||
* The Time and Value array must be reasonably distributed over at
|
* The Time and Value array must be reasonably distributed over at
|
||||||
* least one full period of the fundamental Frequency for the
|
* least one full period of the fundamental Frequency for the
|
||||||
* fourier transform to be useful. The function will take the
|
* fourier transform to be useful. The function will take
|
||||||
* last period of the frequency as data for the transform.
|
* numPeriod periods of the frequency as data for the transform.
|
||||||
*
|
*
|
||||||
* We are assuming that the caller has provided exactly one period
|
* We are assuming that the caller has provided exactly numPeriod periods
|
||||||
* of the fundamental frequency. */
|
* of the fundamental frequency. */
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
@ -331,10 +337,10 @@ CKTfour(int ndata, /* number of entries in the Time and
|
||||||
Phase[i] = 0;
|
Phase[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ndata; i++)
|
for (i = 0; i < ndata ; i++)
|
||||||
for (j = 0; j < numFreq; j++) {
|
for (j = 0; j < numFreq; j++) {
|
||||||
Mag[j] += Value[i] * sin(j*2.0*M_PI*i/((double)ndata));
|
Mag[j] += Value[i] * sin(j*2.0*M_PI*numPeriod*i/((double)ndata));
|
||||||
Phase[j] += Value[i] * cos(j*2.0*M_PI*i/((double)ndata));
|
Phase[j] += Value[i] * cos(j*2.0*M_PI*numPeriod*i/((double)ndata));
|
||||||
}
|
}
|
||||||
|
|
||||||
Mag[0] = Phase[0]/ndata;
|
Mag[0] = Phase[0]/ndata;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue