Filter für Messwert

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Murphy.
Beiträge: 20
Registriert: Fr 21. Okt 2016, 19:02

Filter für Messwert

Beitrag von Murphy. »

Hallo,
ich sitze seit einigen Wochen an meiner Abschlussarbeit und benötige dringend Hilfe, da ich nur noch 2 Wochen Zeit habe. Leider hat die Anlage wo sie nur konnte Schwierigkeiten gemacht, daher der Zeitdruck -.-

Ich benötige Hilfe einen Filter, mit dem ich Messwerte von einem A/D-Wandler beruhigen kann, zu schreiben. Ich stelle mir das ganze in etwa so vor:
In einem Array will ich 5 Werte hinterlegen, aus denen der Mittelwert also der Messwert gebildet wird.

Das Problem ist, dass ich nicht weiß wie ich anfangen soll. Ich hätte gern, dass wenn der neue Messwert eine gewisse Abweichung nicht überschreitet er an Position 1 im Array hinterlegt wird únd der letzte Messwert aus dem Array fällt. Falls die Abweichung unrealistisch groß ist, soll der Mittelwert des Arrays bis zum nächsten Messwert nicht verändert werden.

Über eure Hilfe würde ich mich sehr freuen!!! :-)

Mein erster Versuch sieht so aus:

Code: Alles auswählen

 
var
  arr_adc1: array [1..5] of integer;
  spi_adc1, i_adc1, sum_adc1, count_adc1: integer;   
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
   If spi_adc1 > adc1*0,1 or spi_adc1 < adc1*0,1 then
   begin
     Move(arr_adc1[4],arr_adc1[5]);
     Move(arr_adc1[3],arr_adc1[4]);
     Move(arr_adc1[2],arr_adc1[3]);
     Move(arr_adc1[1],arr_adc1[2]);
     arr_adc1[1] := spi_adc1;
   end;
 
   for i := Low(arr_adc1) to High(arr_adc1) do
   sum_adc1 := sum_adc1 + arr_adc1[i];
   count_adc1 := Length(arr_adc1);
   adc1 := sum_adc1 div count_adc1;
 
 
end;           
Zuletzt geändert von Murphy. am Mo 23. Jan 2017, 22:46, insgesamt 1-mal geändert.

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Filter für Messwert

Beitrag von siro »

Das könnte in etwa so aussehen:

Code: Alles auswählen

 
const PufferGroesse = 5 + 2{ +2 weil kleinster und groesster Wert rausgeschmissen wird }
var Puffer:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
var index:Integer;    { Index auf den Messwert im Puffer }
 
{ jeder neue Messwert wird in den Puffer geschrieben }
{ der älteste Messwert wird automatisch überschrieben }
{ und der neue eingertragen }
procedure WertSpeichern(NeuerWert:Integer);
begin
  { den Wert in den Ringpuffer schreiben, index gibt die Position an }
  Puffer[index]:=NeuerWert;
 
  { den index aktualisieren }
  if index < PufferGroesse-1 then index:=index+1
                             else index:=0;
end;
 
{----------------------------------------------------------------}
{ liefert den Mittelwert deines Messwert Puffers zurück }
 
const MAX_ADU = 4095;   { beim 12 Bit Wandler }
const MIN_ADU = 0;
 
function MittelWert:Integer;
var Wert,min,max,i:Integer;
begin
  Wert:= 0;   { Wert auf 0 initialisieren }
  min := MAX_ADU;   { !!! umgekehrte initialisierung }
  max := MIN_ADU;   { fuer min und max, das soll so ... }
  { alle Werte aus dem Puffer aufaddieren }
  for i:=0 to PufferGroesse-1 do begin
    if Puffer[i] > max then max:=Puffer[i];
    if Puffer[i] < min then min:=Puffer[i];
    Wert:=Wert + Puffer[i];
  end;
 
  Wert:=Wert-min;  { den kleinsten Wert vom Puffer abziehen }
  Wert:=Wert-max;  { den groessten Wert vom Puffer abziehen }
 
  { durch die Anzahl Werte im Puffer teilen }
  Wert:=Wert DIV PufferGroesse;                                      (PufferGroesse-2)
 
  result:=Wert;      { den Mittelwert zurück liefern }
end;
 
 


Ich schmeisse vor der Mittelwertbildung jedoch noch den Groesten und kleinsten Messwert raus und bilde nur noch aus den restlichen Werten den Mittelwert,
Ausreisser werden damit schön geglättet.
Zuletzt geändert von siro am Mi 25. Jan 2017, 15:20, insgesamt 1-mal geändert.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

creed steiger
Beiträge: 957
Registriert: Mo 11. Sep 2006, 22:56

Re: Filter für Messwert

Beitrag von creed steiger »

kommt ja auf deine Messwerte an, aber diese Diskussion könnte dir weiterhelfen:

http://www.mikrocontroller.net/topic/99902

Murphy.
Beiträge: 20
Registriert: Fr 21. Okt 2016, 19:02

Re: Filter für Messwert

Beitrag von Murphy. »

siro hat geschrieben:Das könnte in etwa so aussehen:

Code: Alles auswählen

 
const PufferGroesse = 5 + 2{ +2 weil kleinster und groesster Wert rausgeschmissen wird }
var Puffer:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
var index:Integer;    { Index auf den Messwert im Puffer }
 
{ jeder neue Messwert wird in den Puffer geschrieben }
{ der älteste Messwert wird automatisch überschrieben }
{ und der neue eingertragen }
procedure WertSpeichern(NeuerWert:Integer);
begin
  { den Wert in den Ringpuffer schreiben, index gibt die Position an }
  Puffer[index]:=NeuerWert;
 
  { den index aktualisieren }
  if index < PufferGroesse-1 then index:=index+1
                             else index:=0;
end;
 
{----------------------------------------------------------------}
{ liefert den Mittelwert deines Messwert Puffers zurück }
 
const MAX_ADU = 4095;   { beim 12 Bit Wandler }
const MIN_ADU = 0;
 
function MittelWert:Integer;
var Wert,min,max,i:Integer;
begin
  Wert:= 0;   { Wert auf 0 initialisieren }
  min := MAX_ADU;   { !!! umgekehrte initialisierung }
  max := MIN_ADU;   { fuer min und max, das soll so ... }
  { alle Werte aus dem Puffer aufaddieren }
  for i:=0 to PufferGroesse-1 do begin
    if Puffer[i] > max then max:=Puffer[i];
    if Puffer[i] < min then min:=Puffer[i];
    Wert:=Wert + Puffer[i];
  end;
 
  Wert:=Wert-min;  { den kleinsten Wert vom Puffer abziehen }
  Wert:=Wert-max;  { den groessten Wert vom Puffer abziehen }
 
  { durch die Anzahl Werte im Puffer teilen }
  Wert:=Wert DIV PufferGroesse;
 
  result:=Wert;      { den Mittelwert zurück liefern }
end;
 
 


Ich schmeisse vor der Mittelwertbildung jedoch noch den Groesten und kleinsten Messwert raus und bilde nur noch aus den restlichen Werten den Mittelwert,
Ausreisser werden damit schön geglättet.


Vielen Dank, das sieht sehr gut aus :!: :!:

Murphy.
Beiträge: 20
Registriert: Fr 21. Okt 2016, 19:02

Re: Filter für Messwert

Beitrag von Murphy. »

Bei mir schaut das ganze jetzt so aus:

Code: Alles auswählen

 
var
  spi_form: Tspi_form;
  adc1, adc2, adc3, adc4, adc5, adc6, adc7, adc8, dac1, dac2: integer;
  spi_adc1, spi_adc2, spi_adc3, spi_adc4, spi_adc5, spi_adc6, spi_adc7: integer;
 
var index:Integer;    { Index auf den Messwert im Puffer }
var Wert,min,max,i:Integer;
 
const PufferGroesse = 5 + 2{ +2 weil der kleinste und groesste Wert entfernt werden }
const MAX_ADU = 4095;   { beim 12 Bit Wandler }
const MIN_ADU = 0;
 
{ Filter_ADC1 }
var Puffer_adc1:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC2 }
var Puffer_adc2:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC3 }
var Puffer_adc3:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC4 }
var Puffer_adc4:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC5 }
var Puffer_adc5:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC6 }
var Puffer_adc6:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC7 }
var Puffer_adc7:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
 
 
implementation
 
{$R *.lfm}
 
{ Tspi_form }
 
procedure Tspi_form.spi_timerTimer(Sender: TObject);
var
  spi: TSPILinuxDevice;
  rbuf, wbuf: array[0..2] of Byte;
  rslt: Word;
  dac_rbuf, dac_wbuf: array[0..1] of Byte;
 
begin
  spi := TSPILinuxDevice.Create(0,0);
  spi.Mode := SPI_MODE_0;
  try
    // ADC_Ch1
    wbuf[0] := %00000110;
    wbuf[1] := %00000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc1 := rslt;
    { jeder neue Messwert wird in den Pufferspeicher geschrieben }
    { der älteste Messwert wird automatisch überschrieben }
    { und der neue eingertragen }
    { Wert in den Ringpuffer schreiben, index gibt die Position an }
    Puffer_adc1[index]:=spi_adc1;
    { den index aktualisieren }
    if index < PufferGroesse-1 then index:=index+1
                                    else index:=0;
    {----------------------------------------------------------------}
    { liefert den Mittelwert des Messwert Puffers zurück }
    Wert:= 0;   { Wert auf 0 initialisieren }
    min := MAX_ADU;   { !!! umgekehrte initialisierung }
    max := MIN_ADU;   { fuer min und max }
    { alle Werte aus dem Puffer aufaddieren }
    for i:=0 to PufferGroesse-1 do begin
    if Puffer_adc1[i] > max then max:=Puffer_adc1[i];
    if Puffer_adc1[i] < min then min:=Puffer_adc1[i];
    Wert:=Wert + Puffer_adc1[i];
    end;
    Wert:=Wert-min;  { den kleinsten Wert vom Puffer abziehen }
    Wert:=Wert-max;  { den groessten Wert vom Puffer abziehen }
    Wert:=Wert DIV PufferGroesse; { durch die Anzahl Werte im Puffer teilen }
    adc1:=Wert;      { den Mittelwert zurück liefern } 
 


Leider erhalte ich als adc1 immer den Wert 0 ... :?:

ohne den Filter läuft der Analog/Digital-Wandler normal.

Schonmal vielen Dank

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Filter für Messwert

Beitrag von siro »

Guten Morgen,

sorry, mir ist da ein Fehler unterlaufen:
Ich darf nicht durch die Puffergroöße teilen, sondern durch die Puffergröße -2 weil wir ja den Größten und Kleinsten abziehen.... :P
Und die Klammern nicht vergessen :wink:

Wert:=Wert DIV (PufferGroesse-2);

Hab es eben mit Werten ausprobiert und das sollte nun funktionieren.
Einen Timer mit 1 Sekunde eingestellt und dann immer den Wert 1000 reingeschrieben.
Hier sieht man schön wie der Wert langsam hochläuft bis er stabil ist.
Man hat also eine Tiefpass. Wenn Du das SIgnal noch weiter "glätten" möchtest, musst Du nur deinen Puffer vergrößern, das wars dann schon.

Hier mein TestCode:

Code: Alles auswählen

 
var index:Integer;
var Wert,min,max,i:Integer;
var adc1:Integer;
 
const PufferGroesse = 5 + 2;
const MAX_ADU = 4095;
const MIN_ADU = 0;
 
var Puffer_adc1:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
 
procedure Test(spi_adc1:Integer);
begin
    Puffer_adc1[index]:=spi_adc1;
    if index < PufferGroesse-1 then index:=index+1
                               else index:=0;
    Wert:= 0;
    min := MAX_ADU;
    max := MIN_ADU;
    for i:=0 to PufferGroesse-1 do begin
      if Puffer_adc1[i] > max then max:=Puffer_adc1[i];
      if Puffer_adc1[i] < min then min:=Puffer_adc1[i];
      Wert:=Wert + Puffer_adc1[i];
    end;
    Wert:=Wert-min;
    Wert:=Wert-max;
    Wert:=Wert DIV (PufferGroesse-2);
    adc1:=Wert;
 
    Form1.Caption:=IntToStr(adc1){ Wert angucken }
end;
 
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Test(1000);   { für zufällige Messwerte, Test(Random(MAX_ADU));   }
end;
 
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Filter für Messwert

Beitrag von siro »

mir fällt grad auf, dass Du in deiner Timer Funktion immer wieder das Objekt erzeugst..
Soll das so sein ? das macht man doch eigentlich nur einmal beim Starten, oder gibst Du das auch jedes Mal wieder frei am Ende deiner Timer Procedure ?

spi := TSPILinuxDevice.Create(0,0);
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Murphy.
Beiträge: 20
Registriert: Fr 21. Okt 2016, 19:02

Re: Filter für Messwert

Beitrag von Murphy. »

siro hat geschrieben:mir fällt grad auf, dass Du in deiner Timer Funktion immer wieder das Objekt erzeugst..
Soll das so sein ? das macht man doch eigentlich nur einmal beim Starten, oder gibst Du das auch jedes Mal wieder frei am Ende deiner Timer Procedure ?

spi := TSPILinuxDevice.Create(0,0);


Hey,
ja das soll so... ich habe mehere spi Geräte daher wusste ich mir nciht besser zu helfen :) Ich hab leider immer noch ein Problem. Wenn ich den Filter mit den Timer teste funktionierts wunderbar aber in meiner Anwendung leider nicht... Ich erhalte weider den Wert 0

es sieht jetzt so aus:

Code: Alles auswählen

 
var
  spi_form: Tspi_form;
  adc1, adc2, adc3, adc4, adc5, adc6, adc7, adc8, dac1, dac2: integer;
  spi_adc1, spi_adc2, spi_adc3, spi_adc4, spi_adc5, spi_adc6, spi_adc7: integer;
 
{ Es folgen gemeinsame Variablen und Konstanten der Median-Filter}
 
var index:Integer;    { Index auf den Messwert im Puffer }
var Wert,min,max,i:Integer;
 
const PufferGroesse = 5 + 2{ +2 weil der kleinste und groesste Wert entfernt werden }
const MAX_ADU = 4095;   { beim 12 Bit Wandler }
const MIN_ADU = 0;
 
{ Es folgen die Pufferspeicher der einzelnen Kanäle }
 
{ Filter_ADC1 }
var Puffer_adc1:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC2 }
var Puffer_adc2:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC3 }
var Puffer_adc3:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC4 }
var Puffer_adc4:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC5 }
var Puffer_adc5:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC6 }
var Puffer_adc6:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
{ Filter_ADC7 }
var Puffer_adc7:Array[0..PufferGroesse-1] of Integer;   { Messwert Ringpuffer }
 
 
procedure filter(spi_adc:Integer; Puffer_adc: Array of Integer; adc:integer );
begin
    Puffer_adc[index]:=spi_adc;
    if index < PufferGroesse-1 then index:=index+1
                               else index:=0;
    Wert:= 0;
    min := MAX_ADU;
    max := MIN_ADU;
    for i:=0 to PufferGroesse-1 do begin
      if Puffer_adc[i] > max then max:=Puffer_adc[i];
      if Puffer_adc[i] < min then min:=Puffer_adc[i];
      Wert:=Wert + Puffer_adc[i];
    end;
    Wert:=Wert-min;
    Wert:=Wert-max;
    Wert:=Round(Wert DIV (PufferGroesse-2));
    adc:=Wert;
end;
 
procedure Tspi_form.spi_timerTimer(Sender: TObject);
begin
filter(spi_adc1,Puffer_adc1, adc1);
  filter(spi_adc2,Puffer_adc2, adc2);
  filter(spi_adc3,Puffer_adc3, adc3);
  filter(spi_adc4,Puffer_adc4, adc4);
  filter(spi_adc5,Puffer_adc5, adc5);
  filter(spi_adc6,Puffer_adc6, adc6);
  filter(spi_adc7,Puffer_adc7, adc7);
 end;                                                               
 


Kann mir jemand den Fehler erklären?

Beste Grüße und vielen Dank

shokwave
Beiträge: 470
Registriert: Do 15. Nov 2007, 16:58
OS, Lazarus, FPC: Win11/Ubuntu Budgie (L 3.0 FPC 3.2.2)
CPU-Target: i386, x64
Wohnort: Gera

Re: Filter für Messwert

Beitrag von shokwave »

Hi,

ich vermute mal es liegt an deiner Procedure.

Code: Alles auswählen

procedure filter(spi_adc:Integer; Puffer_adc: Array of Integer; adc:integer );

du benutzt "adc" um "Wert" zurück zu geben. So wie die Procedure deklariert ist wird das aber nichts, da du nicht in "adc" schreiben darfst. Damit das funktioniert sollte es so aussehen.

Code: Alles auswählen

procedure filter(spi_adc:Integer; Puffer_adc: Array of Integer; var adc:integer );

Alternativ kannst du auch eine Function machen.

Code: Alles auswählen

function filter(spi_adc:Integer; Puffer_adc: Array of Integer):Integer;
...
Result:= Wert;


Hoffe das hilft.
mfg Ingo

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Filter für Messwert

Beitrag von Mathias »

Noch etwas, was dein Code vereinfacht.

Code: Alles auswählen

var
  adc : array[1..8] of integer;
  dac : array[1..2] of integer;
  spi_adc : array[1..8] of integer;
// anstelle
  adc1, adc2, adc3, adc4, adc5, adc6, adc7, adc8, dac1, dac2: integer;
  spi_adc1, spi_adc2, spi_adc3, spi_adc4, spi_adc5, spi_adc6, spi_adc7: integer;

Somit verhinderst du Copy-Past Fehler.

PS:
Ich benötige Hilfe einen Filter, mit dem ich Messwerte von einem A/D-Wandler beruhigen kann, zu schreiben.

Was verwendest du für Wandler, wir hatten in der Firma auch Ärger, das die Messwerte rauschten.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Murphy.
Beiträge: 20
Registriert: Fr 21. Okt 2016, 19:02

Re: Filter für Messwert

Beitrag von Murphy. »

ich find den Fehler einfach nicht, daher hab ich mal die ganze unit kopiert.. An Spi_adc1 liegt ein Wert an, aber nach der filter funktion bleibt adc1 auf 0.
Ich hoffe ihr könnt mir helfen

Code: Alles auswählen

unit u_spi_form;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  spidev, fpspi;
 
type
 
  { Tspi_form }
 
  Tspi_form = class(TForm)
    spi_timer: TTimer;
    procedure spi_timerTimer(Sender: TObject);
 
  private
    { private declarations }
  public
    { public declarations }
  end;
 
var
  spi_form: Tspi_form;
  spi_adc1, spi_adc2, spi_adc3, spi_adc4, spi_adc5, spi_adc6, spi_adc7: integer;
  adc1, adc2, adc3, adc4, adc5, adc6, adc7, adc8, dac1, dac2: integer;
 
implementation
 
{$R *.lfm}
 
var index:Integer;    { Index auf den Messwert im Puffer }
var Wert,min,max,i:Integer;
 
const PufferGroesse = 5 + 2{ +2 weil der kleinste und groesste Wert entfernt werden }
const MAX_ADU = 4095;   { beim 12 Bit Wandler }
const MIN_ADU = 0;
 
{ Es folgen die Pufferspeicher der einzelnen Kanäle }
 
type
  Pufferspeicher = Array[0..PufferGroesse-1] of Integer;
 
{ Filter_ADC1 }
var Puffer_adc1: Pufferspeicher;   { Messwert Ringpuffer }
{ Filter_ADC2 }
var Puffer_adc2: Pufferspeicher;   { Messwert Ringpuffer }
{ Filter_ADC3 }
var Puffer_adc3: Pufferspeicher;   { Messwert Ringpuffer }
{ Filter_ADC4 }
var Puffer_adc4: Pufferspeicher;   { Messwert Ringpuffer }
{ Filter_ADC5 }
var Puffer_adc5: Pufferspeicher;   { Messwert Ringpuffer }
{ Filter_ADC6 }
var Puffer_adc6: Pufferspeicher;   { Messwert Ringpuffer }
{ Filter_ADC7 }
var Puffer_adc7: Pufferspeicher;   { Messwert Ringpuffer }
 
function filter(spi_adc:Integer; Puffer_adc: Pufferspeicher):Integer;
  begin
    Puffer_adc[index]:=spi_adc;
    if index < PufferGroesse-1 then index:= index+1
    else index:=0;
    Wert:=0;
    min:=MAX_ADU;
    max:=MIN_ADU;
    for i:=0 to PufferGroesse-1 do
    begin
      if Puffer_adc[i] > max then max:=Puffer_adc[i];
      if Puffer_adc[i] < min then min:=Puffer_adc[i];
      Wert:=Wert+Puffer_adc[i];
    end;
    Wert := Wert-min;
    Wert := Wert-max;
    Wert := Wert DIV (PufferGroesse-2);
    result := Wert;
  end;
 
 
{ Tspi_form }
 
procedure Tspi_form.spi_timerTimer(Sender: TObject);
var
  spi: TSPILinuxDevice;
  rbuf, wbuf: array[0..2] of Byte;
  rslt: Word;
  dac_rbuf, dac_wbuf: array[0..1] of Byte;
 
begin
  spi := TSPILinuxDevice.Create(0,0);
  spi.Mode := SPI_MODE_0;
  try
    // ADC_Ch1
    wbuf[0] := %00000110;
    wbuf[1] := %00000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc1 := rslt;
    adc1:=filter(spi_adc1,Puffer_adc1);
 
    //ADC_Ch2
    wbuf[0] := %00000110;
    wbuf[1] := %01000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc2 := rslt;
    adc2:=filter(spi_adc2,Puffer_adc2);
 
    // ADC_Ch3
    wbuf[0] := %00000110;
    wbuf[1] := %10000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc3 := rslt;
    adc3:=filter(spi_adc3,Puffer_adc3);
 
    // ADC_Ch4
    wbuf[0] := %00000110;
    wbuf[1] := %11000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc4 := rslt;
    adc4:=filter(spi_adc4,Puffer_adc4);
 
    // ADC_Ch5
    wbuf[0] := %00000111;
    wbuf[1] := %00000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc5 := rslt;
    adc5:=filter(spi_adc5,Puffer_adc5);
 
    // ADC_Ch6
    wbuf[0] := %00000111;
    wbuf[1] := %01000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc6 := rslt;
    adc6:=filter(spi_adc6,Puffer_adc6);
 
    // ADC_Ch7
    wbuf[0] := %00000111;
    wbuf[1] := %10000000;
    spi.ReadandWrite(wbuf[0], 3, rbuf[0], 3);
    rslt := (rbuf[1] and $0F) shl 8;
    rslt := rslt or rbuf[2];
    spi_adc7 := rslt;
    adc7:=filter(spi_adc7,Puffer_adc7);
  finally
    spi.Destroy;
  end;
 
  spi := TSPILinuxDevice.Create(0,1);
  spi.Mode := SPI_MODE_0;
  try
    dac_wbuf[0] := %01110000 or (dac1 shr 8)// DAC_Ch1
    dac_wbuf[1] := dac1 shl 4;
    spi.ReadandWrite(dac_wbuf[0], 2, dac_rbuf[0], 2);
 
    dac_wbuf[0] := %11110000 or (dac2 shr 8)// DAC_Ch2
    dac_wbuf[1] := dac2 shl 4;
    spi.ReadandWrite(dac_wbuf[0], 2, dac_rbuf[0], 2);
  finally
    spi.Destroy;
  end;
 
 end;
 
end.
 

Murphy.
Beiträge: 20
Registriert: Fr 21. Okt 2016, 19:02

Re: Filter für Messwert

Beitrag von Murphy. »

Mathias hat geschrieben:Noch etwas, was dein Code vereinfacht.

Code: Alles auswählen

var
  adc : array[1..8] of integer;
  dac : array[1..2] of integer;
  spi_adc : array[1..8] of integer;
// anstelle
  adc1, adc2, adc3, adc4, adc5, adc6, adc7, adc8, dac1, dac2: integer;
  spi_adc1, spi_adc2, spi_adc3, spi_adc4, spi_adc5, spi_adc6, spi_adc7: integer;

Somit verhinderst du Copy-Past Fehler.

PS:
Ich benötige Hilfe einen Filter, mit dem ich Messwerte von einem A/D-Wandler beruhigen kann, zu schreiben.

Was verwendest du für Wandler, wir hatten in der Firma auch Ärger, das die Messwerte rauschten.



Ich verwende einen MCP3208 ... mit einem 10kohm und 100nF Tiefpass.

Mathias
Beiträge: 6194
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Filter für Messwert

Beitrag von Mathias »

Ich verwende einen MCP3208 ... mit einem 10kohm und 100nF Tiefpass.

Ich bin Gegenwärtig auch an einem Messprogramm zu schreiben, aber ich verwende dafür ADS1115, diese arbeiten mit 16Bit und ich habe ein Rauschen von ca. 2Digits.
Dafür arbeiten diese nur mit 860SPS. Aber dies nur an einem Kanal.
Dein MCP3208 ist da wohl ein bisschen schneller. :wink:

Code: Alles auswählen

• 100 ksps max. sampling rate at VDD = 5V
• 50 ksps max. sampling rate at VDD = 2.7V
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Murphy.
Beiträge: 20
Registriert: Fr 21. Okt 2016, 19:02

Re: Filter für Messwert

Beitrag von Murphy. »

.

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Filter für Messwert

Beitrag von siro »

Guten Abend Murphy,

da kommt 0 raus weil:

function filter(spi_adc:Integer; var Puffer_adc: Pufferspeicher):Integer;

Da fehlt einfach nur das VAR in deiner Funktion..... :wink:


10K zu 100nF sind dann 159 Hz Grenzfreuenz, welche Samplerate läuft denn dein ADU ?
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Antworten