Diode Circuit Analysis

From Wikimization

Jump to: navigation, search

function [vl Cdmax Cdmin Cdmed] = diodeMap(vi, Rs, Rl, verbose, fundfreq, Fs, precision)  %from Convex Optimization & Euclidean Distance Geometry
   mp.Digits(precision);  %Advanpix MCT
   k   = 1.380649e-23;    %boltzmann constant  % https://www.nist.gov/si-redefinition/kelvin-boltzmann-constant
   T   = 298;             %temperature kelvin  %Neudeck p.5                
   q   = 1.602176634e-19; %electron charge     %NIST
   is  = 76.9e-12;        %circuitlab diodeInduced
   eta = 1.45;            %circuitlab diodeInduced
   tau = 4.32e-6;         %transport time. max exponent (observed) e-4. Increasing capacitance observes more nonlinearity in vL FFT.
   Rd  = 0.042;           %diode internal resistance
   nVt = eta*k*T/q;       %[V] thermal voltage for particular diode characterized by eta
   isR = is*(Rs*Rl/(Rs + Rl) + Rd);

   dvd = 1000*randn(size(vi));  %perturbation of derivative proves that iteration converges to same median capacitance
   for i=1:5  %3 iterations will introduce randomness into mean impedance calculation
      Lw = exp((isR + vi*Rl/(Rl + Rs))/nVt)*isR.*(1 + tau*dvd/nVt)/nVt;
      vd = isR - nVt*Lambert_W(Lw) + vi*Rl/(Rl + Rs);
      dvd = [vd(2)-vd(end); vd(3:end)-vd(1:end-2); vd(1)-vd(end-1)]/2;  %approximate the derivative first time around, otherwise dvd becomes near 0. Assumes periodicity.   
      if verbose
         Cd = tau*is*exp(vd/nVt)/nVt;
         Cdmed = median(Cd);
         disp([num2eng(Cdmed,false,false,false,16) ' farad']);
      end
   end
   if verbose
      Cdmax = max(Cd);
      Cdmin = min(Cd);

      figure(20); plot(0:numel(Cd)-1, Cd);
      title('Cd over time'); xlabel('sample number'); ylabel('Farad'); set(get(gca,'ylabel'),'rotation',0);
      drawnow
   else
      Cd = tau*is*exp(vd/nVt)/nVt;
   end
   iC = Cd.*dvd*Fs;            %diffusion capacitor current. Normalization by Fs makes current independent of sample rate
   id = is*(exp(vd/nVt) - 1);  %ideal Shockley equation.  This is already independent of Fs.
   vl = (id + iC)*Rd + vd;

   if verbose
      figure(21); plot(0:numel(iC)-1, iC);
      title('Cd current'); xlabel('sample number'); ylabel('Amp'); set(get(gca,'ylabel'),'rotation',0);
      figure(22); plot(0:numel(id)-1, id);
      title('diode current'); xlabel('sample number'); ylabel('Amp'); set(get(gca,'ylabel'),'rotation',0);
      idx = find(iC ~= 0);
      disp(['mean   capacitor  impedance  = ' num2str(orosumvec(vd(idx)./iC(idx),1)/numel(idx),'%3.4e')])
%       disp(['mean capacitor |impedance| = ' num2str(orosumvec(abs(vd(idx)./iC(idx)),1)/numel(idx),'%3.4e')])
      t = median(vd./iC);
      if t < 0, spc=[]; else spc=' '; end
      disp(['median capacitor  impedance  =' spc num2str(t)])  %median impedance is always far smaller than mean despite mp.Digits precision
      medcapimp = median(abs(vd./iC));  
      disp(['median capacitor |impedance| = ' num2str(medcapimp,'%3.4e')])
      disp(['empirical constant c = ' num2str(medcapimp*(2*pi*fundfreq*Cdmed),'%3.15e')])

      figure(23);
      histogram(Cd,50,'Normalization','probability');                    %for book illustration
   %    histogram(Cd,round(3.25*48000));  %for counting smallest diffusion capacitors
      title('histogram C_d'); xlabel('bin'); ylabel('relative count'); %set(get(gca,'ylabel'),'rotation',0);
      drawnow
   end
end

% https://www.mathworks.com/matlabcentral/fileexchange/43419-the-lambert-w-function
function w = Lambert_W(x,branch)
% Lambert_W  Functional inverse of x = w*exp(w).
% w = Lambert_W(x), same as Lambert_W(x,0)
% w = Lambert_W(x,0)  Primary or upper branch, W_0(x)
% w = Lambert_W(x,-1)  Lower branch, W_{-1}(x)
%
% See: http://blogs.mathworks.com/cleve/2013/09/02/the-lambert-w-function/

   % Effective starting guess
   if nargin < 2 || branch ~= -1
      w = ones(size(x));     % Start above -1
   else  
      w = -2*ones(size(x));  % Start below -1
   end
   v = inf*w;

   % Halley's method
   c = 0;
   limit = 100;
   while any(abs(w - v)./abs(w) > 1e-15) && c < limit  %changed magic tolerance. Was 1e-8. -JonD
      v = w;
      e = exp(w);
      f = w.*e - x;  % Iterate, to make this quantity zero
      w = w - f./((e.*(w+1) - (w+2).*f./(2*w + 2)));
      c = c + 1;
   end
   if c >= limit
      disp('%%%%%%%%%%%%%%%%%%%%%% Warning: Lambert limit reached %%%%%%%%%%%%%%%%%%%%%')
   end
end
Personal tools