Construction signal using zero-order-hold

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)): Created signal using for loop (plot(xZoh2)): 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);
• can you add your plots? That would save us needing to run your code to understand what's happening. Apr 16 '17 at 17:57
– WG-
Apr 16 '17 at 18:23
• sorta tl;dr (i'm too lazy to read code), but you plot looks correct for a ZOH. what's wrong?? Apr 16 '17 at 18:45
• @robertbristow-johnson I wanted to create the output using convolution not by the for-loop implementation.
– WG-
Apr 16 '17 at 18:53
• and you convolved with a rectangular pulse of the same width as your step? Apr 16 '17 at 18:55

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)); 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);
• 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
– WG-
Apr 16 '17 at 22:52
• 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.
– msm
Apr 16 '17 at 23:23
• I added a code based on conv. You can use something similar for FOH as well.
– msm
Apr 16 '17 at 23:42
• 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.
– WG-
Apr 17 '17 at 8:50
• 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.
– msm
Apr 17 '17 at 10:01