Skip to content

Instantly share code, notes, and snippets.

@MartinBloedorn
Created August 7, 2018 20:53
Show Gist options
  • Save MartinBloedorn/22fbb077dc1306b35712840fed95d214 to your computer and use it in GitHub Desktop.
Save MartinBloedorn/22fbb077dc1306b35712840fed95d214 to your computer and use it in GitHub Desktop.
function [ y, r, c ] = spwm( f1, fc, varargin )
%SPWM Generates sine-wave modulated bipolar PWM.
% Will produce the closest possible to a single period of f1.
% [ y, t, c ] = spwm( f1, fc, varargin )
%
% f1 Base harmonic frequency.
% fc Carrier frequency.
% 'NSamples' [100] Samples per 1/fc period.
% 'Method' ['left'] 'left', 'right' or 'center'.
% 'ModIndex' [1] Modulation index.
% 'OutAmpl' [0.5] Output PWM amplitude.
% 'ThiPWM' [false] Enable third harmonic injection
% 'Unipolar' [false] Enable unipolar signal.
% 'Phase' [0] Phase offset (rad)
%
% y PWM Signal.
% r Reference sine wave used.
% c Carrier wave.
% Parse input
p = inputParser;
defltMethod = 'left';
validMethod = {'left','center','right'};
checkMethod = @(x) any(validatestring(x,validMethod));
p.addOptional('NSamples', 100, @isnumeric);
p.addOptional('ModIndex', 1, @isnumeric);
p.addOptional('Method', defltMethod, checkMethod);
p.addOptional('ThiPWM', false, @islogical);
p.addOptional('Unipolar', false, @islogical);
p.addOptional('OutAmpl', 0.5, @isnumeric);
p.addOptional('Phase', 0, @isnumeric);
p.parse(varargin{:});
% Get if THIPWM is enabled
thipwm = p.Results.ThiPWM;
method = p.Results.Method;
% Get samples per period
n = p.Results.NSamples;
% Define counter based on method
switch method
case 'left'
u = linspace(-1, 1, n);
case 'right'
u = linspace(1, -1, n);
case 'center'
u = linspace(1, -1, ceil(n/2 + 1));
u = [linspace(u(end-1), u(2), floor(n/2 - 1)) u];
otherwise
error('Please supply a valid method')
end
% Amounnt of carrier cycles
q = ceil(fc/f1);
% Output signal amplitude: -1/2 to 1/2
k = p.Results.OutAmpl;
% Offset if signal is unipolar
o = (k)*p.Results.Unipolar;
% Carrier wave with unit amplitude
%c = (1/p.Results.ModIndex)*repmat(u, 1, q);
c = repmat(u, 1, q);
% Frequency input
%w = (2*pi/(q*n))*(1:(q*n));
w = linspace(0, 2*pi, q*n);
% Reference signal, in the -1/2 to 1/2 range
if ~thipwm
r = sin(w + p.Results.Phase);
else
r = (2/sqrt(3))*(sin(w + p.Results.Phase) + (1/6)*sin(3*w));
end
% Set reference waveform's amplitude to produce desired ModIndex
r = r*(p.Results.ModIndex);
% Use definition, but fix cases where r-c = 0, and sign = 0
y = k*(sign(r-c) + (sign(r).*((r-c)==0))) + o;
% Update output waveforms
r = k*r + o;
c = k*c + o;
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment