LowPassFW

  • 1
  • 2
  • Seite 1 von 2
robertkc
 
Avatar
 
Betreff:

LowPassFW

 · 
Gepostet: 04.10.2013 - 20:13 Uhr  ·  #1
I ran across LowPassFW in the documentation, but all that is said about it is "T.B.D." Also, there is an example in the examples folder, but that doesn't tell me very much either.

Can anyone provide more details on how LowPassFW works?
rh
Administrator
Avatar
Geschlecht:
Herkunft: Germany
Alter: 25
Homepage: e-lab.de
Beiträge: 5558
Dabei seit: 03 / 2002
Betreff:

Re: LowPassFW

 · 
Gepostet: 04.10.2013 - 21:17 Uhr  ·  #2
Hello Robert,

this filter function was provided by an user a very long time ago.
Here are the definitions in AVRco:

Code
TFiltData = record 
  value : word; 
  Err   : byte; 
end;

TFilterFreq = (ffdiv2,ffdiv4,ffdiv8,ffdiv16,ffdiv32,ffdiv64,ffdiv128,ffdiv256);

procedure LowPassFW(var FiltData : TFiltData; NewVal : word; FilterFreq : TFilterFreq);
var
  lw           : longword;
  LowWord[@lw] : word;
  UpWord[@lw+2]: word;
  ShiftCount   : byte;
  BitMask      : byte;
  LowByte[@lw] : byte;
begin
  ShiftCount     := ord(FilterFreq) + 1;
  BitMask        := %11111111 shr (8 - ShiftCount);  //Calculate ErrorBitMask
  UpWord         := 0;                               //Reset upper part of lw
  LowWord        := FiltData.Value;                  //Set Lower part of lw with old FilterOutput
  lw             := (lw shl ShiftCount) - lw;        //Equal to lw := lw * (2^ShiftCount - 1)
  lw             := lw + LongWord(NewVal + word(FiltData.Err)); //Add NewVal and Old Error
  FiltData.Err   := LowByte AND BitMask;             //Save Modulo of 2^n division
  lw             := lw shr ShiftCount;               //Perform 2^n division
  FiltData.Value := LowWord;                         //Store ResultValue of Filter
end;

But don't ask me what it does, no idea... :binky:

rolf
robertkc
 
Avatar
 
Betreff:

Re: LowPassFW

 · 
Gepostet: 05.10.2013 - 19:16 Uhr  ·  #3
Thank you for the reply.

I guess I'll have to play around with it to learn more. :)

Zitat geschrieben von rh

Hello Robert,

this filter function was provided by an user a very long time ago.
Here are the definitions in AVRco:
[...]
But don't ask me what it does, no idea... :binky:

rolf
rh
Administrator
Avatar
Geschlecht:
Herkunft: Germany
Alter: 25
Homepage: e-lab.de
Beiträge: 5558
Dabei seit: 03 / 2002
Betreff:

Re: LowPassFW

 · 
Gepostet: 08.10.2013 - 18:14 Uhr  ·  #4
@all,
the very first appearance of this Filter in AVRco was Oct.2005 :color:
Of course this is a lowpass filter, but does anyone exactly know what
it does? Maybe Avra?
It would be fine if I can get a good explanation for our compiler manual... :unknown:

rolf
Avra
Schreiberling
Avatar
Geschlecht:
Herkunft: Belgrade, Serbia
Alter: 54
Homepage: rs.linkedin.com/in…
Beiträge: 653
Dabei seit: 07 / 2002
Betreff:

Re: LowPassFW

 · 
Gepostet: 10.10.2013 - 15:52 Uhr  ·  #5
Zitat geschrieben von rh
Maybe Avra?


It provides inertion to changing filter value, with inertion resistance as TFilterFreq parameter. Higher parameter value gives higher resistance to changing fiter value. First picture explains everything. Code exploits shifting bits in a word for fast division, and takes just between 354 cycles (ffDiv2) and 423 cycles (ffDiv256) to provide result quickly. I guess that W in LowPassFW name stands that it is a word parameter based version. Longword, byte, or a positive fixed point number version could be also made of it.

Now I will try to explain how it works. For example, if you start with FiltData.Value = 0 and want to apply NewValue = 1000 once using ffDiv2, then after first LowPassFW call FiltData.Value will have half of a difference between FiltData.Value and NewValue which is (1000-0)/2=500. Then in next call to LowPassFW difference between FiltData.Value and NewValue is (1000-500)/2=250 and FiltData.Value will be 500+250=750. After next call FiltData.Value will be 750+125=875, next 875+62=937, and so on and so on (if NewValue is still 1000, of course). So, ffDiv2 will adjust on each call for half of a difference, ffDiv4 will adjust for one fourth of a difference, ffDiv8 one eight of a difference, etc. You get the picture. Therefore ffDiv2 allows filter value to change with much higher frequency then with ffDiv256, which is much, much slower. So, choosing higher TFilterFreq allows us to filter more peaks in analog signal data acquisition and smoother trending data without instant jumps.

Here is some simple test code for better understanding:
Code
program LowPassFilterTest;

{$NOSHADOW}
{ $WG}                     {global Warnings off}

Device = mega88, VCC=5;
{ $BOOTRST $00C00}         {Reset Jump to $00C00}

Import SysTick, SerPort, LCDport;

From System Import LongWord, LongInt, Float;


Define
  ProcClock      = 16000000;       {Hertz}
  SysTick        = 10;             {msec}
  StackSize      = $0032, iData;
  FrameSize      = $0032, iData;
  SerPort        = 9600, Stop1;    {Baud, StopBits|Parity}
  RxBuffer       = 8, iData;
  TxBuffer       = 8, iData;
  LCDport        = PortB;
  LCDtype        = 44780;
  LCDrows        = 2;              {rows}
  LCDcolumns     = 40;             {columns per line}

Implementation

{$IDATA}

{--------------------------------------------------------------}
{ Type Declarations }

type
  TFiltData = record
    Value : word;
    Err   : byte;
  end;


{--------------------------------------------------------------}
{ Const Declarations }

{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}


{--------------------------------------------------------------}
{ functions }

TFilterFreq = (ffdiv2,ffdiv4,ffdiv8,ffdiv16,ffdiv32,ffdiv64,ffdiv128,ffdiv256);

procedure LowPassFW(var FiltData : TFiltData; NewVal : word; FilterFreq : TFilterFreq);
var
  lw           : longword;
  LowWord[@lw] : word;
  UpWord[@lw+2]: word;
  ShiftCount   : byte;
  BitMask      : byte;
  LowByte[@lw] : byte;
begin
  ShiftCount     := ord(FilterFreq) + 1;
  BitMask        := %11111111 shr (8 - ShiftCount);  //Calculate ErrorBitMask
  UpWord         := 0;                               //Reset upper part of lw
  LowWord        := FiltData.Value;                  //Set Lower part of lw with old FilterOutput
  lw             := (lw shl ShiftCount) - lw;        //Equal to lw := lw * (2^ShiftCount - 1)
  lw             := lw + LongWord(NewVal + word(FiltData.Err)); //Add NewVal and Old Error
  FiltData.Err   := LowByte AND BitMask;             //Save Modulo of 2^n division
  lw             := lw shr ShiftCount;               //Perform 2^n division
  FiltData.Value := LowWord;                         //Store ResultValue of Filter
end;


{--------------------------------------------------------------}
{ Main Program }
{$IDATA}

var
  FiltData: TFiltData;
  FilterFreq: TFilterFreq;
  Pass, NewValue: word;
  i: byte;
begin
  FiltData.Value := 0;
  NewValue := 1000;
  Pass := 0;
  LCDclr;                                  { clear display }
  LCDcursor(false, false);                 { display on, cursor off & no blink }
  LCDhome;                                 { cursor home }
  EnableInts;
  loop
    Inc(Pass);
    LCDxy(0, 0);
    Write(LCDout, 'Pass=' + IntToStr(Pass) + ', ');
    Write(LCDout, 'NewValue=' + IntToStr(NewValue) + '      ');
    LCDxy(0, 1);
    LowPassFW(FiltData, NewValue, ffDiv2);
    Write(LCDout, IntToStr(FiltData.Value) + ', ');
  endloop;
end LowPassFilterTest.
Der an diesem Beitrag angefügte Anhang ist entweder nur im eingeloggten Zustand sichtbar oder die Berechtigung Deiner Benutzergruppe ist nicht ausreichend.
rh
Administrator
Avatar
Geschlecht:
Herkunft: Germany
Alter: 25
Homepage: e-lab.de
Beiträge: 5558
Dabei seit: 03 / 2002
Betreff:

Re: LowPassFW

 · 
Gepostet: 13.10.2013 - 17:05 Uhr  ·  #6
Hello Avra,
thank you very much. :angel13:
Is it possible to have an opposite function in a similar way to get a HighPass filter?

rolf
Avra
Schreiberling
Avatar
Geschlecht:
Herkunft: Belgrade, Serbia
Alter: 54
Homepage: rs.linkedin.com/in…
Beiträge: 653
Dabei seit: 07 / 2002
Betreff:

Re: LowPassFW

 · 
Gepostet: 10.11.2013 - 14:37 Uhr  ·  #7
Merlin
Administrator
Avatar
Geschlecht:
Alter: 25
Beiträge: 1474
Dabei seit: 03 / 2005
Betreff:

Re: LowPassFW

 · 
Gepostet: 11.11.2013 - 13:30 Uhr  ·  #8
Mmmm.

Zitat
No, it must be done "the regular way", with an array of data recordings.


I don't doubt you for a minute Avra, but this feels counter-intuitive. If you have a low pass filter f(S(t)) on a signal S(t) it removes high frequencies as you explained. Does not S(t) - f(S(t)) leave you with what was removed, i.e. the high frequencies, and is this not a high pass filter? I acknowledge that it is crude, but then so is the function S(t).

Just a thought...
  • 1
  • 2
  • Seite 1 von 2
Gewählte Zitate für Mehrfachzitierung:   0

Registrierte in diesem Topic

Aktuell kein registrierter in diesem Bereich

Die Statistik zeigt, wer in den letzten 5 Minuten online war. Erneuerung alle 90 Sekunden.
MySQL Queries: 15 · Cache Hits: 14   130   144 · Page-Gen-Time: 0.042075s · Speichernutzung: 2 MB · GZIP: ein · Viewport: SMXL-HiDPI