# Matlab filter coefficients

Started by October 24, 2007
```Hi,
I have a problem in designing a filter. I have a 4th order
IIR Butterworth bandpass filter whose Second order systems
are represented by :

sos = [1 0 -1 1 -1.9837350041630541 0.98388232243107987;
1 0 -1 1 -1.7068352267865177 0.74814388078659311];

and the gain is:

gain = 0.10073985362198344 ^ 2;

I'm getting the filter coefficient values with sos2tf()
function such as:

[b,a] = sos2tf(sos,gain)

and get the result:

b =
0.0101 0 -0.0203 0 0.0101

a =
1.0000 -3.6906 5.1179 -3.1634 0.7361

and apply these coefficients to the filter:

y = filter(b,a,x);

This gives a pretty good working filter application. But
when I try to assign the filter coefficients by hand like
below (which are same with the results of sos2tf func.):

b = [ 0.0101 0 -0.0203 0 0.0101 ]

a = [ 1.0000 -3.6906 5.1179 -3.1634 0.7361 ]

I get very much different filter result. The filter doesn't
work in the second case. Do anyone knows the cause of this
problem?

Regards
Mursel

```
```On Oct 24, 5:04 am, "kerasus" <murselak...@gmail.com> wrote:
> Hi,
> I have a problem in designing a filter. I have a 4th order
> IIR Butterworth bandpass filter whose Second order systems
> are represented by :
>
>   sos = [1 0 -1 1 -1.9837350041630541 0.98388232243107987;
>          1 0 -1 1 -1.7068352267865177 0.74814388078659311];
>
> and the gain is:
>
>   gain = 0.10073985362198344 ^ 2;
>
> I'm getting the filter coefficient values with sos2tf()
> function such as:
>
>   [b,a] = sos2tf(sos,gain)
>
> and get the result:
>
>   b =
>     0.0101 0 -0.0203 0 0.0101
>
>   a =
>     1.0000 -3.6906 5.1179 -3.1634 0.7361
>
> and apply these coefficients to the filter:
>
>   y = filter(b,a,x);
>
> This gives a pretty good working filter application. But
> when I try to assign the filter coefficients by hand like
> below (which are same with the results of sos2tf func.):
>
>   b = [ 0.0101 0 -0.0203 0 0.0101 ]
>
>   a = [ 1.0000 -3.6906 5.1179 -3.1634 0.7361 ]
>
> I get very much different filter result. The filter doesn't
> work in the second case. Do anyone knows the cause of this
> problem?
>
> Regards
> Mursel

When you type them in by hand like that you are omitting significant
digits that Matlab doesn't display on the screen by default. Try
typing 'format long' and then display b and a to the screen.

John

```
```>On Oct 24, 5:04 am, "kerasus" <murselak...@gmail.com> wrote:
>> Hi,
>> I have a problem in designing a filter. I have a 4th order
>> IIR Butterworth bandpass filter whose Second order systems
>> are represented by :
>>
>>   sos = [1 0 -1 1 -1.9837350041630541 0.98388232243107987;
>>          1 0 -1 1 -1.7068352267865177 0.74814388078659311];
>>
>> and the gain is:
>>
>>   gain = 0.10073985362198344 ^ 2;
>>
>> I'm getting the filter coefficient values with sos2tf()
>> function such as:
>>
>>   [b,a] = sos2tf(sos,gain)
>>
>> and get the result:
>>
>>   b =
>>     0.0101 0 -0.0203 0 0.0101
>>
>>   a =
>>     1.0000 -3.6906 5.1179 -3.1634 0.7361
>>
>> and apply these coefficients to the filter:
>>
>>   y = filter(b,a,x);
>>
>> This gives a pretty good working filter application. But
>> when I try to assign the filter coefficients by hand like
>> below (which are same with the results of sos2tf func.):
>>
>>   b = [ 0.0101 0 -0.0203 0 0.0101 ]
>>
>>   a = [ 1.0000 -3.6906 5.1179 -3.1634 0.7361 ]
>>
>> I get very much different filter result. The filter doesn't
>> work in the second case. Do anyone knows the cause of this
>> problem?
>>
>> Regards
>> Mursel
>
>When you type them in by hand like that you are omitting significant
>digits that Matlab doesn't display on the screen by default. Try
>typing 'format long' and then display b and a to the screen.
>
>John
>
>

Thank you John, you are right. I changed the coefficients with exact ones
and it worked. But I wonder something; the difference was:

b-d

ans =

1.0e-004 *

0.4852         0    0.0296         0    0.4852

how can such a small difference be very significant? Is there a way to
round them safely? I'm asking that because I have a memory problem with my
microcontroller. If I use the exact coefficients the data size exceeds the
memory, and I have no chance to change my microcontroller. Can you offer
me something?
```
```kerasus wrote:
>> On Oct 24, 5:04 am, "kerasus" <murselak...@gmail.com> wrote:
>>> Hi,
>>> I have a problem in designing a filter. I have a 4th order
>>> IIR Butterworth bandpass filter whose Second order systems
>>> are represented by :
>>>
>>>   sos = [1 0 -1 1 -1.9837350041630541 0.98388232243107987;
>>>          1 0 -1 1 -1.7068352267865177 0.74814388078659311];
>>>
>>> and the gain is:
>>>
>>>   gain = 0.10073985362198344 ^ 2;
>>>
>>> I'm getting the filter coefficient values with sos2tf()
>>> function such as:
>>>
>>>   [b,a] = sos2tf(sos,gain)
>>>
>>> and get the result:
>>>
>>>   b =
>>>     0.0101 0 -0.0203 0 0.0101
>>>
>>>   a =
>>>     1.0000 -3.6906 5.1179 -3.1634 0.7361
>>>
>>> and apply these coefficients to the filter:
>>>
>>>   y = filter(b,a,x);
>>>
>>> This gives a pretty good working filter application. But
>>> when I try to assign the filter coefficients by hand like
>>> below (which are same with the results of sos2tf func.):
>>>
>>>   b = [ 0.0101 0 -0.0203 0 0.0101 ]
>>>
>>>   a = [ 1.0000 -3.6906 5.1179 -3.1634 0.7361 ]
>>>
>>> I get very much different filter result. The filter doesn't
>>> work in the second case. Do anyone knows the cause of this
>>> problem?
>>>
>>> Regards
>>> Mursel
>> When you type them in by hand like that you are omitting significant
>> digits that Matlab doesn't display on the screen by default. Try
>> typing 'format long' and then display b and a to the screen.
>>
>> John
>>
>>
>
> Thank you John, you are right. I changed the coefficients with exact ones
> and it worked. But I wonder something; the difference was:
>
>   b-d
>
>   ans =
>
>     1.0e-004 *
>
>       0.4852         0    0.0296         0    0.4852
>
> how can such a small difference be very significant? Is there a way to
> round them safely? I'm asking that because I have a memory problem with my
> microcontroller. If I use the exact coefficients the data size exceeds the
> memory, and I have no chance to change my microcontroller. Can you offer
> me something?

Small differences can be a big deal in recursive filters. You might try
quantizing the second order section coefficients and then filtering in
concatenated second order sections, rather than quantizing the fourth
order coefficients and running a single fourth order filter.

John
```
```John Sampson wrote:
> kerasus wrote:
>
>>> On Oct 24, 5:04 am, "kerasus" <murselak...@gmail.com> wrote:
>>>
>>>> Hi,
>>>> I have a problem in designing a filter. I have a 4th order
>>>> IIR Butterworth bandpass filter whose Second order systems
>>>> are represented by :
>>>>
>>>>   sos = [1 0 -1 1 -1.9837350041630541 0.98388232243107987;
>>>>          1 0 -1 1 -1.7068352267865177 0.74814388078659311];
>>>>
>>>> and the gain is:
>>>>
>>>>   gain = 0.10073985362198344 ^ 2;
>>>>
>>>> I'm getting the filter coefficient values with sos2tf()
>>>> function such as:
>>>>
>>>>   [b,a] = sos2tf(sos,gain)
>>>>
>>>> and get the result:
>>>>
>>>>   b =
>>>>     0.0101 0 -0.0203 0 0.0101
>>>>
>>>>   a =
>>>>     1.0000 -3.6906 5.1179 -3.1634 0.7361
>>>>
>>>> and apply these coefficients to the filter:
>>>>
>>>>   y = filter(b,a,x);
>>>>
>>>> This gives a pretty good working filter application. But
>>>> when I try to assign the filter coefficients by hand like
>>>> below (which are same with the results of sos2tf func.):
>>>>
>>>>   b = [ 0.0101 0 -0.0203 0 0.0101 ]
>>>>
>>>>   a = [ 1.0000 -3.6906 5.1179 -3.1634 0.7361 ]
>>>>
>>>> I get very much different filter result. The filter doesn't
>>>> work in the second case. Do anyone knows the cause of this
>>>> problem?
>>>>
>>>> Regards
>>>> Mursel
>>>
>>> When you type them in by hand like that you are omitting significant
>>> digits that Matlab doesn't display on the screen by default. Try
>>> typing 'format long' and then display b and a to the screen.
>>>
>>> John
>>>
>>>
>>
>> Thank you John, you are right. I changed the coefficients with exact ones
>> and it worked. But I wonder something; the difference was:
>>
>>   b-d
>>
>>   ans =
>>
>>     1.0e-004 *
>>
>>       0.4852         0    0.0296         0    0.4852
>>
>> how can such a small difference be very significant? Is there a way to
>> round them safely? I'm asking that because I have a memory problem
>> with my
>> microcontroller. If I use the exact coefficients the data size exceeds
>> the
>> memory, and I have no chance to change my microcontroller. Can you offer
>> me something?
>
>
> Small differences can be a big deal in recursive filters. You might try
> quantizing the second order section coefficients and then filtering in
> concatenated second order sections, rather than quantizing the fourth
> order coefficients and running a single fourth order filter.
>
> John

As you try to operate your filter farther from the sample frequency you
will also become more susceptible to small differences in the
coefficients.  Depending on the needs of your application, you may be
able to filter in stages and use decimation to reduce these effects.

You said that using the exact coefficients that the data size exceeds
that of your system.  I have seen the comment here many times that IIR
filters usually require 32 bit precision in a fixed point application.
If all else fails, you may consider performing "long hand" calculations
in software.  By "long hand" I mean the way that you were taught to
multiply and add large numbers using pen and paper.  I have seen this
tactic used to obtain 24 bit precision on 8 bit processors in assembly.

```
```On Oct 24, 7:33 am, "kerasus" <murselak...@gmail.com> wrote:

> how can such a small difference be very significant?

The denominator coefficients of your "sos" filter are:

d1 = [1 -1.9837350041630541 0.98388232243107987]
and
d2 = [1 -1.7068352267865177 0.74814388078659311]

In Matlab, roots(d1) =
0.991867502081527 + 0.009010035828557i
0.991867502081527 - 0.009010035828557i
and roots(d2) =
0.853417613393259 + 0.140791540714445i
0.853417613393259 - 0.140791540714445i

Both are stable.

But if a = [ 1.0000 -3.6906 5.1179 -3.1634 0.7361 ],
then roots(a) =
1.000000000001536
0.985670546913484
0.852464726542490 + 0.141792607448564i
0.852464726542490 - 0.141792607448564i

It's unstable.

> Is there a way to round them safely?

You have to reduce the wordsize in a way that maintains stability as
well as approximating your desired response.  You may also have to
deal with limit cycles.  Most DSP books have sections dealing with
finite register length effects.

Greg

```