# Reconstructing Sine wave using Fundamental frequency, Amplitude and zero crossing Points

21 views (last 30 days)
ragnor on 27 Apr 2021
Edited: ragnor on 27 Apr 2021
Hello Everyone
I am trying to construct a sine wave using the formula sinewave = amplitude*sin(2*pi*F*T) where i know the values of F and amplitude. I want to construct the signal such that it crosses over zero at points that i have precalculated. The main idea is i have PWM line to line voltages from inverter. I did a FFT to get the fundamental frequency and amplitude for one phase. I also calculated the zero crossing points of the PWM signals.
Now i want to create a sine wave from the above data. But my sine wave calculation seems not correct as i am not getting the appropriate amplitude.
Can someone please have a look and help me?
Kind regards
%%Script to convert data from <CSV
t = data{:,1};
x = data{:,2};
y = data{:,3};
z = data{:,4};
hFig1 = figure;
plot(t,x)
title('Line to Line Voltage')
xlabel('t (seconds)')
ylabel('Voltage(V)')
hold on
plot(t,y)
hold on
plot(t,z)
hold off
figure(hFig1);
ax = hFig1.Children;
ln = ax.Children;
xv = ln.XData;
yv = ln(1).YData;
phase=atan2(imag(Y),real(Y))*180/pi; %phase information(Y);
%Fast Fourier Tranform to get the Fundamental Frequency
Ts = mean(diff(xv)); % Sampling Interval
Fs = 1/Ts; % Sampling Frequency
Fn = Fs/2; % Nyquist Frequency
L = numel(xv); % Signal Length
Y = fft(yv)/L; % Fouriet Transform (Normalised)
%Y = fft(yv,[],2)./L; % Fouriet Transform (Normalised) TS
Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
Iv = 1:numel(Fv); % Index Vector
%Plotting the FFT for only one phase
figure(1);
subplot(2,1,1)
plot(Fv, abs(Y(1, Iv))*2)
grid on
title(' Spectrum Amp vs Freq');
xlabel('Frequency')
ylabel('Amplitude')
%Plotting one phase angle
subplot(2,1,2)
plot(Fv, phase(Iv))
grid on
xlim([0,50])
title(' Spectrum Phase vs Freq');
xlabel('Frequency(Hz)')
Ts = mean(diff(t)); % Sampling Interval
Fs = 1/Ts; % Sampling Frequency
NN = 4;
Wn = 0.005; % normalized to Nyquist frequency
[B,A] = butter(NN,Wn);
figure(2)
xs = filtfilt(B,A,x);
plot(t,x,t,xs);legend('Raw','Smoothed');
title(['Data samples at Fs = ' num2str(round(Fs)) ' Hz / Filtered with butterworth LP' ]);
grid on
% zero crossing detection => mesure cycle to cycle time intervals (and derive frequency from time intervals)
threshold = 0;
[t0_pos,s0_pos,t0_neg,s0_neg]= crossing_V7(xs,t,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
% t0 => corresponding time (x) values
% s0 => corresponding function (y) values , obviously they must be equal to "threshold"
figure(3)
plot(t,xs,t0_pos,s0_pos,'+r',t0_neg,s0_neg,'+g','linewidth',2,'markersize',12);grid on
legend('signal','positive slope crossing points','negative slope crossing points');
xlabel('Time (s)');
time_interval = diff(t0_pos); % cycle to cycle time intervals
%% Constructing sinus waveformn over the zero crossing points with Fundamental Frequency and Amplitude
% select crossing points for t > 0.05 s (don't bother with initial
% transient)
t0_pos2 = t0_pos(t0_pos>0.05);
t0_neg2 = t0_neg(t0_neg>0.05);
t0_all = unique(sort([t0_pos2 t0_neg2])); % merge all crossing points , sort them ascending order and keep only unique values
amplitude = 251.4; % Amplitude calculated by FFT analysis
sign = 1;
F = 12.64; %Fundamental frequency calulated above in FFT
for ci = 1:length(t0_all)-1
t_start = t0_all(ci);
t_end = t0_all(ci+1);
ind = find(t>=t_start & t<t_end);
tt = t(ind);
T = linspace(0,pi,length(ind));
xss_tmp = sign*amplitude*sin(2*pi*F*T);
sign = -1*sign; % alternate half wave sinus absolute phase
end
figure(3)
plot(t,x,T,xss_tmp,t0_pos,s0_pos,'+r',t0_neg,s0_neg,'+g','linewidth',2,'markersize',12);grid on
legend('signal','sinus approx','positive slope crossing points','negative slope crossing points');
xlabel('Time (s)');
function [t0_pos,s0_pos,t0_neg,s0_neg] = crossing_V7(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth,slope_sign) % older format
% CROSSING find the crossings of a given level of a signal
% ind = CROSSING(S) returns an index vector ind, the signal
% S crosses zero at ind or at between ind and ind+1
% [ind,t0] = CROSSING(S,t) additionally returns a time
% vector t0 of the zero crossings of the signal S. The crossing
% times are linearly interpolated between the given times t
% [ind,t0] = CROSSING(S,t,level) returns the crossings of the
% given level instead of the zero crossings
% ind = CROSSING(S,[],level) as above but without time interpolation
% [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
% par = {'none'|'linear'}.
% With interpolation turned off (par = 'none') this function always
% returns the value left of the zero (the data point thats nearest
% to the zero AND smaller than the zero crossing).
%
% [ind,t0,s0] = ... also returns the data vector corresponding to
% the t0 values.
%
% [ind,t0,s0,t0close,s0close] additionally returns the data points
% closest to a zero crossing in the arrays t0close and s0close.
%
% This version has been revised incorporating the good and valuable
% bugfixes given by users on Matlabcentral. Special thanks to
% Howard Fishman, Christian Rothleitner, Jonathan Kellogg, and
% Zach Lewis for their input.
% Steffen Brueckner, 2002-09-25
% Steffen Brueckner, 2007-08-27 revised version
% Copyright (c) Steffen Brueckner, 2002-2007
% brueckner@sbrs.net
% M Noe
% added positive or negative slope condition
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
% if no time vector is given, use the index vector as time
t = 1:length(S);
elseif length(t) ~= length(S)
% if S and t are not of the same length, throw an error
error('t and S must be of identical length!');
end
% check the level input
if nargin < 3
% set standard value 0, if level is not given
level = 0;
end
% check interpolation method input
if nargin < 4
imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S = S - level;
% first look for exact zeros
ind0 = find( S == 0 );
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind);
s0 = S(ind);
if strcmp(imeth,'linear')
% linear interpolation of crossing
for ii=1:length(t0)
%if abs(S(ind(ii))) > eps(S(ind(ii))) % MATLAB V7 et +
if abs(S(ind(ii))) > eps*abs(S(ind(ii))) % MATLAB V6 et - EPS * ABS(X)
% interpolate only when data point is not already zero
NUM = (t(ind(ii)+1) - t(ind(ii)));
DEN = (S(ind(ii)+1) - S(ind(ii)));
slope = NUM / DEN;
slope_sign(ii) = sign(slope);
t0(ii) = t0(ii) - S(ind(ii)) * slope;
s0(ii) = level;
end
end
end
% extract the positive slope crossing points
ind_pos = find(sign(slope_sign)>0);
t0_pos = t0(ind_pos);
s0_pos = s0(ind_pos);
% extract the negative slope crossing points
ind_neg = find(sign(slope_sign)<0);
t0_neg = t0(ind_neg);
s0_neg = s0(ind_neg);
end