I need to design a filter able to take a measurement of alternate current and shift the phase of the input by 90°.

The filter should work between 40 and 60Hz and at this range should have unity gain. Outside this range I don`t care about the gain or phase.

I research about Hilbert filter and sounds that this kind of filter is what I need, but I don`t know how to use.

Let me paste my matlab code (fixed afther Matt recomendation):

%     close all
clear all

Fs = 1000; %sample frequency

fl = 40;   %lower frequency 


b = firpm(40,[f_min (1-f_min)],[1 1],'h');   % Bandpass Hilbert
%     fvtool(b)

t = 0:1/Fs:1.2;

%input signal Frequency

%Generate AC signal (input)- at 40hz (lower limit)
y1 = sin(2*pi*f*t);

%Generate filtered signal-40hz
y1 = [zeros(1,(length(b)-1)/2), y1(1:end-(length(b)-1)/2)];

%Generate AC signal (input)- at 60Hz (upper limit)
y2 = sin(2*pi*f*t);

%Generate filtered signal-60hz
y2 = [zeros(1,(length(b)-1)/2), y2(1:end-(length(b)-1)/2)];

hold on


hold off

axis([max(t)-t_window max(t) -1.1 1.1])


I was expecting that my signal yf is 90° shifted, but this doesn`t work.

Someone have some idea about how to solve this issue and what is wrong at my code?

Part 2 - Thanks Hilmar and Richard. Let me fix my code and use your code and show what is happening. Done. But this don`t work yet...

  • Objective 1- 90 phase shift -ok! (thanks guys!)
  • Objective 2- Magnitude without change- Not OK. The signal was atenuate by 5% if I change the input frequency from 60 to 40Hz.

Could you help me to explain why this is happen at magnitude?and What I should do to fix this?.... I need magnitude as flat as possible between this frequencies. I tried to increase the order of the filter(40->60) but don`t solve my issue yet.

Part 3 - Thanks Matt. Let me fix my code and use your suggestion. Now work!

Now my filtered signal is shifted properly and with low attenuation between 40 to 60hz. The attenuation is less than 0.4% at this range.

Thank again guys(Matt, Richard and Hilmar)


4 Answers 4


@Rodrigo PG: Your Matlab Hilbert transformer is causal. This means, in order to synchronize-in-time your $y$ sequence with your $yf$ sequence, you need to delay your $y$ sequence by (length of $b$ minus 1)/2 samples when the length of $b$ is odd. This will delay your input $y$ by the same amount as the Hilbert transformer's inherent time delay. Insert the following line of code after your yf = filter(b,1,y); command:

y = [zeros(1,(length(b)-1)/2), y];

to see the desired 90-deg phase shift.

  • $\begingroup$ Richard, take a look at my edited post. Regards $\endgroup$
    – Rodrigo PG
    Commented Oct 26, 2015 at 12:05

Regarding the magnitude response of the FIR Hilbert transformer, it is never ideally flat. The passband magnitude ripple can be reduced by increasing the filter order. However, in your case the frequency $40$ (whatever units) at a sampling frequency of $2000$ is outside the passband of the designed filter, because your lower band edge is $0.05$ (which corresponds to a frequency of $50$ for the given sampling rate).

So, if you want the Hilbert transformer to work well at a frequency of $40$, this frequency must be inside the passband, i.e. you must lower the lower band edge to say $0.035$. If the resulting passband ripple is too high, then you also must increase the filter order.

  • 1
    $\begingroup$ I tried to upvote all the answers, but this wasn`t possible. So I choose the user with lower reputation to help him to grow his reputation. $\endgroup$
    – Rodrigo PG
    Commented Oct 27, 2015 at 12:38

Hilbert Transformers are non-causal, i.e. they need to be delayed to be implementable. So you get the 90 degree phase-shift plus a bulk delay of 20 samples (half the filter length).

You see the 90 degree phase shift if you delay the original signal by 20 samples as well.

EDIT for Part 2:

Your lower bandpass cutoff is too high. It currently sits at 50 Hz. It needs to go down to 40 Hz or potentially a little lower. You may also have to crank up the number of points to get less amplitude ripple in the pass band. Something like

b = firpm(60,[38 950]*2/2000,[1 1],'h');

gets you about 0.1 dB ripple. Cranking the number of tabs up to 96 will reduce the pass band ripple to 0.01dB.

  • $\begingroup$ Hilmar, take a look at my edited post. Regards $\endgroup$
    – Rodrigo PG
    Commented Oct 26, 2015 at 12:05

@Rodrigo PG: Now that your Hilbert filter is working, you can start experimenting.

[1] Window your Hilb filter’s coefficients with a Hanning (Hann) or Hamming window to reduce the passband ripple. But make sure your signal of interest is still within the Hilb filter’s passband.

[2] Decimate your input signal by a factor of two using a halfband filter. That will allow you to use a simpler (fewer coefficients) Hilb filter.

[3] Insert a zero-valued coefficient in between each of your original Hilb filter’s coefficients. That will enable you to perform a Hilbert transform on lower-frequency signals.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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