Code covered by the BSD License  

Highlights from
res_meas

image thumbnail

res_meas

by

 

16 May 2007 (Updated )

GUI for resonator measurement and data download from Signal Analyzers and Oscilloscopes

retval=bandqf(datares,verbose);
function retval=bandqf(datares,verbose);
% BANDQF determines the Q and center frequency by fitting to the data using
%  the "universal oscillator" equation (2nd order system).
% RETVAL = BANDQF(DATARES,VERBOSE)
%
% DATARES is a resonator frequency sweep measurement data structure, such
%   as returned by measure_res.
% VERBOSE is the message level. 0 for silence, 2 for all messages.
%
% RETVAL will have three fields:
% retval = 
%          Q: % the Q value estimated by the "best" fit (minimum sum of
%             %  squares error)
%        f_0: % the center frequency- the maximum value of the fitted curve
%     params: % the final values used for the best fit to the data
%
% Examples:
%
% Acquire a resonator measurement using measure_res:
%
%   res = measure_res(tools, 0, 1000);
%
% Then, use bandqf to determine the Q using by fitting:
%
%   rfit = bandqf(res);
%
%
%
% M.A. Hopcroft
%      hopcroft at mems.stanford.edu
%
% MH JAN2007  based on code from Cyril Vancura
% v1.1 accepts res structure for input; single file for two functions
% v1.0 use a loop to stop fitting after the results have stopped changing
%

%%%% constants
% stop iterating when the answers are changing by less
%  than mindiff or when maxit iterations have occured
mindiff = 1e-4; maxit = 10;
% initial search parameters- guesses for the fitting algorithm. Actually,
% [1 1 1] works pretty well, but occasionally gives warnings. Better
% choices mean fewer iterations required.
init_fit = [1e7 -1e6 -100];

if nargin < 2
    verbose = 2;
end

% extract the data from the res structure
data(:,1)=datares.trace1.x; % frequency
data(:,2)=datares.trace1.y; % amplitude
data(:,3)=datares.trace2.y; % phase

if verbose >=2, fprintf(1,'bandqf: initial search: [%g %g %g]\n', init_fit); end
% perform and initial fit
%  the initial conditions could certainly be optimized for certain data
%  sets (given an expected center frequency, etc).
F=fminsearch(@f_omega_dB,init_fit,[],data);

% use fminsearch to do the fitting- keep trying until the results are the
%  same each time
diff=1; k=0;
while diff > mindiff && k < maxit
    k=k+1;

    if verbose >=2, fprintf(1,'bandqf: fminsearch %d; ',k); end
    F1=fminsearch(@f_omega_dB,F,[],data);
    
    diff = sum(F) - sum(F1);
    fprintf(1,'diff: %f\n',diff);
    
    F=F1;
end
if verbose >=1 && k>=10, fprintf(1,'bandqf: Warning maxmimum searches used (%d)\n; ',k); end

retval.Q = abs(F(2)/(2*F(3)));
retval.f_0 = sqrt(F(2)^2-2*F(3)^2);
retval.params=F;

% plot the results (optional)
try
    chi_sqr_dB_plot(F,data);
catch
    if verbose >=2, fprintf(1,'bandqf: plotting not available (requires CHI_SQR_DB_PLOT)\n'); end
end

return


function output=f_omega_dB(parameters,Data)
% F_OMEGA_DB compares resonator sweep data to a line determined by fitting
%  to the 2nd order system equation and returns the sum of differences squared
%  (the error in the fit).
% MH JAN2007  based on code from Cyril Vancura
% v1.0

Vin=sqrt(50); % 50 ohm impedance assumed % 242
% we have three fitting factors
Ampl=parameters(1);   % the "amplitude", i.e., the mass term
omega0=parameters(2); % resonant frequency
gamma=parameters(3);  % damping factor

% convert from dB  
Data(:,4)=Vin*10.^(Data(:,2)/20);
% fit to the oscillator amplitude function
%  note that omega may be negative because of the ^2
A=Ampl./sqrt((omega0^2-Data(:,1).^2).^2+((2*gamma*Data(:,1)).^2));

Diff_sqr=(Data(:,4)-A).^2;
output=sum(Diff_sqr);

return

Contact us