0
$\begingroup$

I have a signal $x(t) = \sin(2\pi t)$ with $t \in [0,1]$. The signal $x_s(t)$ is the sampled signal with a sampling period of $T_s = 0.05$. Now I want to compute the reconstructed $x_r(t)$ signal using a zero-order-hold.

The ZOH has the following impulse response

$$h_{\mathrm{ZOH}}(t,T_s)\,= \frac{1}{T_s} \mathrm{rect} \left(\frac{t}{T_s}-\frac{1}{2} \right)$$

This I implemented in Matlab:

zohImpl = @(t,Ts) 1/Ts*rectangularPulse(t/Ts - 1/2);

Now I simply did a convolution between the impulse response $h_{\mathrm{ZOH}}$ and the sampled signal $x_s(t)$

xZoh = conv(zohImpl(t,Ts),xSampled);

However I do not get the result expected, the reconstructed signal. I get a sinus with a higher amplitude and in the convolution, xZoh gets signal points padded which are 0.

What am I doing wrong here? I would namely expect the same results as which I obtain using...

k = 0;
for i = 1:length(t) 
    if k*Ts <= t(i) && t(i) < (k + 1)*Ts    
        k = k + 1;
    end
    xZoh(i) = xSampled(k);
end

Full code:

clear all;
close all;
clc;

% Impulse ZOH 
zohImpl     = @(t,Ts) 1/Ts*rectangularPulse(t/Ts - 1/2);

% Impulse FOH
fohImpl     = @(t,Ts) 1/Ts*triangularPulse(t/Ts);

% Impulse FOH delayed
fohDelayImp = @(t,Ts) 1/Ts*triangularPulse((t - Ts)/Ts);

% Impulse FOH predictive
fohPreImp   = @(t,Ts) 1/Ts*(rectangularPulse(t/Ts - 1/2) - ...
                            rectangularPulse(t/Ts - 3/2) + ...
                             triangularPulse(t/Ts - 1));

% Time domain
tStart = 0;
tStep  = 1e-4;
tEnd   = 1;
t      = tStart:tStep:tEnd;

% Original signal
x = @(t)(sin(2*pi*t));

% Sampling period
Ts = 5e-2;

% Samples
nSamples = tEnd/Ts; 
samples  = 0:nSamples;

% Sampled signal
xSampled = x(samples*Ts);

% Convolution with impulse response
xZoh1 = conv(zohImpl(t,Ts),xSampled);

% Plot
figure(4);
hold all;
plot(t,x(t));
stem(samples*Ts,xSampled);
% plot(t,xZoh1); does not work

k = 0;
for i = 1:length(t) 
    if k*Ts <= t(i) && t(i) < (k + 1)*Ts    
        k = k + 1;
    end
    xZoh2(i) = xSampled(k);
end

plot(t,xZoh2);

Created signal using convolution (plot(xZoh1)): enter image description here

Created signal using for loop (plot(xZoh2)): enter image description here

latest code

clear all;
close all;
clc;

% Time domain
tStart = 0;
tStep  = 1e-4;
tEnd   = 1;
t      = tStart:tStep:tEnd;
beta   = 0.2;

% Original signal
x = @(t)(sin(2*pi*t));

% Sampling period
Ts = 5e-2;

% Impulse ZOH 
zohImpl     = @(t,Ts) 1/Ts*rectangularPulse(t/Ts - 1/2);

% Impulse FOH
fohImpl     = @(t,Ts) 1/Ts*triangularPulse(t/Ts);

% Impulse FOH delayed
fohDelayImp = @(t,Ts) 1/Ts*triangularPulse((t - Ts)/Ts);

% Impulse FOH predictive
fohPreImp   = @(t,Ts) 1/Ts*(rectangularPulse(t/Ts - 1/2) - ...
                            rectangularPulse(t/Ts - 3/2) + ...
                             triangularPulse(t/Ts - 1));

% Impulse FOH fractional
fohFractImp = @(t,Ts,beta) 1/Ts*(rectangularPulse(t/Ts - 1/2) - ...
                            beta*rectangularPulse(t/Ts - 3/2) + ...
                            beta* triangularPulse(t/Ts - 1));

tt = -1:1e-4:1;                       
figure(1);
subplot(5,1,1);
plot(tt,zohImpl(tt,Ts));
grid on; box on; axis tight;
subplot(5,1,2);
plot(tt,fohImpl(tt,Ts));
grid on; box on; axis tight;
subplot(5,1,3);
plot(tt,fohDelayImp(tt,Ts));
grid on; box on; axis tight;
subplot(5,1,4);
plot(tt,fohPreImp(tt,Ts));
grid on; box on; axis tight;
subplot(5,1,5);
plot(tt,fohFractImp(tt,Ts,beta));
grid on; box on; axis tight;   

% Samples
nSamples = tEnd/Ts; 
samples  = 0:nSamples;

% Sampled signal
xSampled = zeros(1,length(t));
xSampled(1:Ts/tStep:end) = x(samples*Ts);

% Convolution with impulse response
xZoh         = conv(zohImpl(t,Ts),xSampled);
xFoh         = conv(fohImpl(t-t(Ts/tStep),Ts),xSampled);
xFohDelayImp = conv(fohDelayImp(t,Ts),xSampled);
xFohPreImp   = conv(fohPreImp(t,Ts),xSampled);
xFohFractImp = conv(fohFractImp(t,Ts,beta),xSampled);

xZoh         = xZoh(1:length(t))         / nSamples;
xFoh         = xFoh(1:length(t))         / nSamples;
xFohDelayImp = xFohDelayImp(1:length(t)) / nSamples;
xFohPreImp   = xFohPreImp(1:length(t))   / nSamples;
xFohFractImp = xFohFractImp(1:length(t)) / nSamples;

% Plot
figure(2);
hold all;
plot(t,x(t));
% stem(t,xSampled);
plot(t,xZoh);
plot(t-t(Ts/tStep),xFoh);
plot(t,xFohDelayImp);
plot(t,xFohPreImp);
plot(t,xFohFractImp);
$\endgroup$
  • $\begingroup$ can you add your plots? That would save us needing to run your code to understand what's happening. $\endgroup$ – Marcus Müller Apr 16 '17 at 17:57
  • $\begingroup$ @MarcusMüller added. $\endgroup$ – WG- Apr 16 '17 at 18:23
  • $\begingroup$ sorta tl;dr (i'm too lazy to read code), but you plot looks correct for a ZOH. what's wrong?? $\endgroup$ – robert bristow-johnson Apr 16 '17 at 18:45
  • $\begingroup$ @robertbristow-johnson I wanted to create the output using convolution not by the for-loop implementation. $\endgroup$ – WG- Apr 16 '17 at 18:53
  • $\begingroup$ and you convolved with a rectangular pulse of the same width as your step? $\endgroup$ – robert bristow-johnson Apr 16 '17 at 18:55
3
$\begingroup$

There are a few issues:

  • The type of impulse we need here is not a discrete delta but a Dirac delta.

  • The type of convolution we need is a continuous not a discrete one.

  • If you want to implement this on a computer, the rectangular pulse should also be sampled with a sampling rate higher than $1/T_s$ (e.g. 1/tStep).

An easy way to address the above issues is to use kron function and sample the rectangular pulse with an appropriate rate. Simply replace the line

xZoh1 = conv(zohImpl(t,Ts),xSampled); 

with the following

xZoh1 = kron(xSampled, ones(1,Ts/tStep)); 

% Clip it to adjust the length
xZoh1 = xZoh1(1:length(t));

enter image description here

Note that the scaling by $T_s$ in the formula you provided is due to time-scaling the Dirac delta function and is dropped here.

If you want to use conv, then the code should be changed into something like

clear all;
close all;
clc;

% Time domain
tStart = 0;
tStep  = 1e-4;
tEnd   = 1;
t      = tStart:tStep:tEnd;

% Original signal
x = @(t)(sin(2*pi*t));

% Sampling period
Ts = 5e-2;

% Impulse ZOH 
zohImpl     = ones(1,Ts/tStep);

% Samples
nSamples = tEnd/Ts; 
samples  = 0:nSamples;

% Sampled signal
xSampled = zeros(1,length(t));
xSampled(1:Ts/tStep:end) = x(samples*Ts);

% Convolution with impulse response
xZoh1 = conv(zohImpl,xSampled);

xZoh1 = xZoh1(1:length(t));

% Plot
figure(4);
hold all;
plot(t,x(t));
stem(t,xSampled);
plot(t,xZoh1); 
| improve this answer | |
$\endgroup$
  • $\begingroup$ I use a 'higher' sampling rate, see tStep and Ts, Ts is the sample rate for the sampling the sinusoid and tStep is used to create the "original" sinusoid. I also use it on the convolution for the impulse response. Also I would prefer to use conv because I also wanted to zohImpl, fohImpl, et cetera. However, am I to understand that this is not possible? It is not clear to me why not. Currently, I have the feeling that I am using rectangularPulse incorrect, see my comment towards @robert bristow-johnson $\endgroup$ – WG- Apr 16 '17 at 22:52
  • $\begingroup$ I see what you do. You can also use conv (maybe it is a little more tricky). In such case, You should stuff enough zeros in between the samples (i.e. in xSampled) and also sample the rectangular pulse with rate 1/tStep. Just make sure you understand the points in my answer. $\endgroup$ – msm Apr 16 '17 at 23:23
  • $\begingroup$ I added a code based on conv. You can use something similar for FOH as well. $\endgroup$ – msm Apr 16 '17 at 23:42
  • $\begingroup$ Still not what I wanted, because I want to use the zohImpl. You are now just shifting your first solution more or less. However, based on your solution I altered my code. It is now working for all methods, accept for the basic FOH. This is because it is acasual. So therefor I shifted the time signal in both the xFoh = conv(fohImpl(t-t(Ts/tStep),Ts),xSampled); and the plot(t-t(Ts/tStep),xFoh);. I am not sure however if this is actually also correct because it is actually simply equal to the xFohDelayImp but shifted manually. $\endgroup$ – WG- Apr 17 '17 at 8:50
  • $\begingroup$ The FOH impulse is [linspace(0,1,Ts/tStep-tStep) linspace(1,0,Ts/tStep)];. If you want to implement the non-causal FOH, you should compensate a duration of one $T_s$ at the beginning of xSampled. Then it becomes just like the others. $\endgroup$ – msm Apr 17 '17 at 10:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.