Forum: Mikrocontroller und Digitale Elektronik Differenzierfilter


von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute!

ich möchte diesen Differenzier-Filter auf mein EKG-Signal anwenden:
(Derivative Filter Pan-Tompkins-Algorithmus)

Jetzt habe ich diesen Filter folgendermaßen implementiert:
1
signed long diff(signed long *data, unsigned char n)
2
{
3
  signed long y = 0;
4
5
  if(n==0)
6
  {
7
    y = ((2*data[n]) + data[4] - data[2] - (2*data[1])) >> 3;
8
  }
9
  if(n==1)
10
  {
11
    y = ((2*data[n]) + data[0] - data[3] - (2*data[2])) >> 3;
12
  }
13
  if(n==2)
14
  {
15
    y = ((2*data[n]) + data[1] - data[4] - (2*data[3])) >> 3;
16
  }
17
  if(n==3)
18
  {
19
    y = ((2*data[n]) + data[2] - data[0] - (2*data[4])) >> 3;
20
  }
21
  if(n==4)
22
  {
23
    y = ((2*data[n]) + data[3] - data[1] - (2*data[0])) >> 3;
24
  }
25
  
26
  return y;
27
}

Allerdings bekomme ich da nur Mist raus und ich verstehe nicht warum!
Habe ich den Filter falsch implementiert?
Das Foto im Anhang zeigt das Signal was ich nach dem Filter erhalte.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> Habe ich den Filter falsch implementiert?

Sieht nicht so schlecht aus.

Dump dir die Werte irgendwo hin aus (LCD, UART, was du eben hast). 
Meistens erkennt man dann schon mehr.
Stell erst mal alles in Frage und überprüf es. Auch, ob deine 
Eingangswerte im 5-er Array data korrekt sind. Das kommt gar nicht so 
selten vor, dass in der Kette
   Eingabe - Verarbeitung - Ausgabe
das Problem schon im Schritt Eingabe zu finden ist, und die Verarbeitung 
gar nichts dafür kann :-)

Wie heißt es so schön:  garbage in - garbage out.

von Peter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Wie heißt es so schön:  garbage in - garbage out.

Ja oftmals ist es so das stimmt! :-)

Habe ich zwar schon überprüft aber bleibt mir wohl nichts anderes übrig 
als es nochmals eingehend zu tun! :-)

von Georg G. (df2au)


Lesenswert?

Sorry, ich verstehe das Filter anders.

 signed long diff(signed long *data, unsigned char n)
  {
  signed long y = 0;

  y = ((2*data[n]) + data[n-1] - data[n-3] - (2*data[n-4])) >> 3;

  return y;
  }

von Peter (Gast)


Lesenswert?

Georg G. schrieb:

>Sorry, ich verstehe das Filter anders.

Ja ist ja auch richtig so wie du es gemacht hast...aber ich habe nur ein 
Array mit 5 Werten und wenn n=0 ist dann ist [n-1] = 4 usw.
Ich habe mir die Implementierung mit Pointern usw. gespart da es nur 5 
Werte sind.

von Achim S. (Gast)


Lesenswert?

Peter schrieb:
> Das Foto im Anhang zeigt das Signal was ich nach dem Filter erhalte.

sieht ein wenig danach aus, als hättest du als Ergebnis nur zwei 
bestimmte Zahlen: 0 und ca. 1,68E7. Falls die zweite Zahl genau 16777215 
ist (?) entspräche das 0x00FFFFFF. Das könnte darauf hindeuten, dass du 
irgendwo (allerdings nicht in dem C-Code oben) den Wertebereich eines 
Integertyps überschreitest oder sonstige Probleme bei einer 
Typkonvertierung hast.

Der Plot ist mit Labview gemacht? Lass dir doch mal mit einer Probe die 
zugehörigen Zahlenwerte anzeigen.

von Georg G. (df2au)


Lesenswert?

Peter schrieb:
> aber ich habe nur ein Array mit 5 Werten

Ich hätte nicht den Mut, bei 5 Messwerten ein Differenzierfilter zu 
nehmen.

von Achim S. (Gast)


Lesenswert?

Georg G. schrieb:
> Ich hätte nicht den Mut, bei 5 Messwerten ein Differenzierfilter zu
> nehmen.

ich schätze mal, dass Peter ein array mit 5 Messwerten als Ringpuffer 
verwendet. Die Anzahl der Messwerte, die er durch den Puffer schiebt, 
dürft laut seinem Plot wesentlich größer sein.

von Karl H. (kbuchegg)


Lesenswert?

Achim S. schrieb:

> ich schätze mal, dass Peter ein array mit 5 Messwerten als Ringpuffer
> verwendet. Die Anzahl der Messwerte, die er durch den Puffer schiebt,
> dürft laut seinem Plot wesentlich größer sein.


Jup.
Ganz genau so hab ich den Ausschnitt auch aufgefasst.
Aber eines steht fest. Der Code ist in Ordnung. Das Problem muss 
ausserhalb zu finden sein.
Vielleicht funktioniert ja auch das befüllen des Ringpuffers nicht.

Aber wir können hier raten so viel wir wollen. Klarheit bringt oft, wenn 
man sich einfach mal die Werte ansieht. Wenn in der Funktion immer nur 
data[0] einen vernünftigen Wert hat und alle anderen Unsinn sind, dann 
ist es kein Wundern, wenn das Filter Blödsinn ausrechnet. Schuld ist in 
diesem Fall dann auch nicht der Filtercode, sondern der Code der die 
Mist-Daten an das Filter gibt. Die Werte aus dem Filter sind dann nur 
das Symptom. Aber das Filter ist nicht die Ursache.

Von daher: Die ganze Kette der Verarbeitung überprüfen. Und am 
einfachsten geht das, indem man sich einfach mal die Zahlenwerte 
ansieht. Dann sieht man schon, bis wohin die Zahlen noch Sinn ergeben 
und ab wo der Unsinn anfängt.

von Erich (Gast)


Lesenswert?

Man kann sich diese Berechnungsvorschrift(en) zunächst in Excel 
erstellen und dort ausprobieren.
An GANZZAHL und korrekter Rundung denken falls in der embedded SW 
Integers verwendet werden (sollen).

von Georg G. (df2au)


Lesenswert?

Auch dann ist die Funktion nicht richtig. Mal dir einen Puffer auf und 
sieh dir an, welche Meßwerte wann verarbeitet werden. Vielleicht wird es 
noch klarer, wenn du auch beim ersten, durch [n] referenzierten Wert den 
festen Wert für n schreibst und mit der Soll-Formel vergleichst. Nur bei 
n == 5 würde es passen. Und dieser Fall tritt nie auf.

Sinnvoller: Nach jedem Durchgang die Werte des Puffers um 1 in die 
Vergangenheit schieben. Das ist deutlich effektiver und übersichtlicher, 
als Pointerarithmetik mit 5 Vergleichen auf Überlauf.

von Michael (Gast)


Lesenswert?

Hallo

Das Diagramm sieht nach einer signed / unsigned Problematik aus.

Mfg

Michael

von Achim S. (Gast)


Lesenswert?

Georg G. schrieb:
> Auch dann ist die Funktion nicht richtig. Mal dir einen Puffer auf und
> sieh dir an, welche Meßwerte wann verarbeitet werden.

Hab ich gemacht: ich kann keinen Fehler finden. Vielleicht hilft dir der 
Hinweis, dass im Rinpuffer der Index 5 wieder dem Index 0 entspricht.

Georg G. schrieb:
> Sinnvoller: Nach jedem Durchgang die Werte des Puffers um 1 in die
> Vergangenheit schieben. Das ist deutlich effektiver und übersichtlicher,

Na ja, so wie es implementiert ist, muss bei jedem Durchgang nur der 
Index inkrementiert werden. Dein Vorschlag würde das selbe bewirken, 
aber man müsste bei jedem Durchgang 4 Messwerte verschieben. Ich vermute 
Peters Code ist effizienter. Um es nachzuweisen müsste ich mir aber 
anschauen, was der Compiler aus der Serie von if-Abfragen macht.

Karl Heinz Buchegger schrieb:
> Aber wir können hier raten so viel wir wollen. Klarheit bringt oft, wenn
> man sich einfach mal die Werte ansieht.

Ja, Peter macht es spannend für uns. Wäre der Code von mir, dann läge 
der Fehler mit ziemlicher Sicherheit in der Labview-Auswertung: wenn man 
nicht genau hinschaut, sehen dort alle Ganzzahlentypen praktisch gleich 
aus...

von Hagen R. (hagen)


Lesenswert?

ich meine auch das es ein Interpretationsfehler des Vorzeichens ist. Der 
Wert würde dann zwischen 0 und -1 schwanken, bei 24Bit Integern.

von Peter (Gast)


Lesenswert?

Hallo Leute vielen Dank für eure zahlreichen Antworten!

Achim S. schrieb:
> ich schätze mal, dass Peter ein array mit 5 Messwerten als Ringpuffer
> verwendet. Die Anzahl der Messwerte, die er durch den Puffer schiebt,
> dürft laut seinem Plot wesentlich größer sein.

Genau so ist es!

Achim S. schrieb:
> sieht ein wenig danach aus, als hättest du als Ergebnis nur zwei
> bestimmte Zahlen: 0 und ca. 1,68E7. Falls die zweite Zahl genau 16777215
> ist (?) entspräche das 0x00FFFFFF. Das könnte darauf hindeuten, dass du
> irgendwo (allerdings nicht in dem C-Code oben) den Wertebereich eines
> Integertyps überschreitest oder sonstige Probleme bei einer
> Typkonvertierung hast.

Ja ich habe mir die Werte mal anzeigen lassen und sie schwanken immer 
entweder zwischen 0 und -1 oder 0 und 16777215. Also wird der Fehler 
wohl in einer Überschreitung des Wertebereichs liegen. Die Werte die ich 
reinschiebe habe ich auch überprüft, die stimmen.

von Erich (Gast)


Lesenswert?

Nochmals mein Hinweis von neulich 
Beitrag "Re: Differenzierfilter"

Egal welche Typgrösse eines int man nimmt, immer wenn mehrere davon 
aufaddiert werden, muss dafür sorgen daß ein Bereichsüberlauf nicht 
stattfinden kann.
Man darf also mehrere "long" nicht addieren auf ein "long" wenn nicht 
sichergestellt ist das das "reinpasst". Notfalls muss man unter 
Genauigkeitsverlust eben schon die Teilwerte vorab durch /2 oder /4 
teilen.
Das alles man man mit EXCEL vorher erstellen und ausprobieren, unter 
Zuhilfenahme der tatsächlich möglichen Werte (Maximas und Minimas).
Gruss

von Karl H. (kbuchegg)


Lesenswert?

> Also wird der Fehler wohl in einer Überschreitung des Wertebereichs
> liegen.

Ich stimme da ehrlich gesagt nicht mit Achim überein.
Das bei einer Wertebereichsüberschreitung exakt -1 (in24 Bit) rauskommt, 
ist sehr sehr unwahrscheinlich.
Ich denke immer noch, dass dein Problem schon bei den Ausgangswerten zu 
suchen ist und du deine Sensorwerte schon falsch vom Sensor holst, wenn 
da nur 0 bzw. -1 (bzw 0x00FFFFFF) rauskommt. Da kann dann auch ein 
Filter nichts mehr richten.
Entweder das, oder dein Auswerte- und Anzeigecode ist fehlerhaft.

von Peter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das bei einer Wertebereichsüberschreitung exakt -1 (in24 Bit) rauskommt,
> ist sehr sehr unwahrscheinlich.

Das macht mich auch sehr stutzig dass da exakt immer 0 oder -1 oder 
16777216 rauskommt.

Karl Heinz Buchegger schrieb:
> Ich denke immer noch, dass dein Problem schon bei den Ausgangswerten zu
> suchen ist und du deine Sensorwerte schon falsch vom Sensor holst, wenn
> da nur 0 bzw. -1 (bzw 0x00FFFFFF) rauskommt. Da kann dann auch ein
> Filter nichts mehr richten.

Fakt ist aber wenn ich die Funktion des Differenzierfilters nicht 
ausführe und nur die Werte anzeige die ich einlese in den Puffer dann 
erhalte ich ein schönes EKG-Signal also korrekte Werte. Daher muss es 
irgendwie mit der Funktion bzw. den Operationen in der Funktion zu tun 
haben.

von Achim S. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich stimme da ehrlich gesagt nicht mit Achim überein.
> Das bei einer Wertebereichsüberschreitung exakt -1 (in24 Bit) rauskommt,
> ist sehr sehr unwahrscheinlich.


Da hast du schon recht. Aber es müsste auch eine ziemlich 
unwahrscheinliche Folge von Dummy-Werten an die Funktion übergeben 
werden, damit dieses seltsame Ergebnis rauskommt. (Bei der das Flippen 
zwischen den beiden Ergebniswerten auch noch so unregelmäßig alle paar 
Sekunden erfolgt.) Und Peter schreibt ja, dass er die Eingangswerte 
überprüft hat.

@Peter: hast du eigentlich eine Idee, woher die Beschränkung auf 24 bit 
kommt? Nutzt du in deinem sonstigen Code einen Datentyp mit 24 bit 
Breite oder machst du irgendwo Normierungen/Schiebeoperationen (>>8) bei 
denen evtl. das Vorzeichenbit nicht richtig behandelt wird?

Ansonsten eine Frage zur gesamten Signalkette: mein Eindruck ist (muss 
aber nicht stimmen), dass du einen Controller einsetzt um die ADCs zu 
bedienen und den Filter zu implementieren, und dass die Daten danach an 
einen PC geschickt und mit Labview weiter verarbeitet werden. Ist das so 
oder läuft alles auf Labview-Ebene, und der oben gezeigte C-Code steckt 
in einem Formula-Node?

Na ja, letztlich würde auch ich dir einfach vorschlagen, die Signalkette 
Schritt für Schritt durchzugehen und jeweils zu prüfen, wo aus 
vernünftigen Meswerten auf einmal diese digitale Wertefolge wird.

von Achim S. (Gast)


Lesenswert?

das war ja perfektes Timing...

Peter schrieb:
> Fakt ist aber wenn ich die Funktion des Differenzierfilters nicht
> ausführe und nur die Werte anzeige die ich einlese in den Puffer dann
> erhalte ich ein schönes EKG-Signal also korrekte Werte.

Wie sieht das Ergebnis denn aus, wenn du die Funktion ausführst, aber 
den Code in der Funktion einfach ersetzt durch

return data[n]

(was ja die ungefilterten Daten ergeben sollte)

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> Fakt ist aber wenn ich die Funktion des Differenzierfilters nicht
> ausführe und nur die Werte anzeige die ich einlese in den Puffer dann
> erhalte ich ein schönes EKG-Signal also korrekte Werte. Daher muss es
> irgendwie mit der Funktion bzw. den Operationen in der Funktion zu tun
> haben.


Zeig doch mal den Code, der diese Filterfunktion benutzt, bzw. das ganze 
Drumherum vom Messwerte holen, aufteilen in den Ringpuffer bis zur 
Anzeige des Ergebnisses.

An der Funktion ist immer noch nichts falsch (ausser der Division, die 
du durch >>3 ersetzt hast). Aber das heißt ja nicht, dass du die 
Funktion korrekt benutzt.

> Daher muss es irgendwie mit der Funktion

Nö.
Wenn du die Funktion nicht aufrufst, dann musst du ja an der 
Aufrufstelle irgendwas anderes machen. D.h. das ist ein anderes 
Programm. Ein anderes Programm interessiert hier aber nicht. Du hast mit 
DIESEM Programm ein Problem. Also sehen wir uns auch DIESES Programm 
(mit Aufruf der Funktion) genauer an.

von Karl H. (kbuchegg)


Lesenswert?

Achim S. schrieb:

> Na ja, letztlich würde auch ich dir einfach vorschlagen, die Signalkette
> Schritt für Schritt durchzugehen und jeweils zu prüfen, wo aus
> vernünftigen Meswerten auf einmal diese digitale Wertefolge wird.

Das hatte ich ihm schon vorgeschlagen. Und wahrscheinlich wär das 
Problem damit schon längst gelöst, wenn er nicht 
vergleichendes-Diagramm-Debugging durch ein und auskommentieren von Code 
betreiben würde. Es dauert einfach seine Zeit, bis die Leute begreifen, 
dass Code verändern und sich dann nur ansehen wie sich das Endergebnis 
verändert einfach nur eine Hi-Tech Methode ist, Zeit totzuschlagen.

von Peter (Gast)


Lesenswert?

Achim S. schrieb:
> Das hatte ich ihm schon vorgeschlagen. Und wahrscheinlich wär das
> Problem damit schon längst gelöst, wenn er nicht
> vergleichendes-Diagramm-Debugging durch ein und auskommentieren von Code
> betreiben würde. Es dauert einfach seine Zeit, bis die Leute begreifen,
> dass Code verändern und sich dann nur ansehen wie sich das Endergebnis
> verändert einfach nur eine Hi-Tech Methode ist, Zeit totzuschlagen.

Das stimmt das ist nicht sehr effektiv, ich habe aber auch lediglich den 
Bereich eingrenzen wollen in dem der Fehler steckt.

Achim S. schrieb:
> Ansonsten eine Frage zur gesamten Signalkette: mein Eindruck ist (muss
> aber nicht stimmen), dass du einen Controller einsetzt um die ADCs zu
> bedienen und den Filter zu implementieren, und dass die Daten danach an
> einen PC geschickt und mit Labview weiter verarbeitet werden. Ist das so
> oder läuft alles auf Labview-Ebene, und der oben gezeigte C-Code steckt
> in einem Formula-Node?

Ja richtig der Controller nimmt die Werte über SPI von einem anderem 
Chip auf und Labview dient nur der Visualisierung.

Achim S. schrieb:
> @Peter: hast du eigentlich eine Idee, woher die Beschränkung auf 24 bit
> kommt? Nutzt du in deinem sonstigen Code einen Datentyp mit 24 bit
> Breite oder machst du irgendwo Normierungen/Schiebeoperationen (>>8) bei
> denen evtl. das Vorzeichenbit nicht richtig behandelt wird?

Ich bekomme immer pro Wandlungswert einen 24-Bit Wert und speichere den 
in der signed long Variable. Daher kommen die 24-Bit.

Karl Heinz Buchegger schrieb:
> Zeig doch mal den Code, der diese Filterfunktion benutzt, bzw. das ganze
> Drumherum vom Messwerte holen, aufteilen in den Ringpuffer bis zur
> Anzeige des Ergebnisses.
1
while(1)
2
  {    
3
    if(new_sample == 1)  
4
    {
5
      CS_state(0);
6
      SPI_TransmitByte(RDATA);
7
      status = SPI_Receive_3Bytes();
8
      data = SPI_Receive_3Bytes();
9
      CS_state(1);
10
      
11
      LOFF_STATP = status >> 12;
12
      LOFF_STATN = status >> 4;
13
      
14
      if((LOFF_STATP == 0) && (LOFF_STATN == 0)) // Hands-on-detection
15
      {
16
        data = check_negative(data);
17
        data = iir_bandpassx1(data,w_bandpassx1);
18
        data = iir_bandpassx2(data,w_bandpassx2);
19
        
20
        data_in[i] = data;  
21
22
        data_in[i] = diff(data_in,i);
23
24
        USART_Transmit_4Bytes(data_in[i]);
25
26
        i++;
27
        if(i>=5)
28
        {
29
          i = 0;
30
        }  
31
      }
32
      else
33
      {
34
        USART_Transmit_4Bytes(0x000000);
35
      }
36
      new_sample = 0;  
37
    }
38
  }
39
}

Achim S. schrieb:
> Wie sieht das Ergebnis denn aus, wenn du die Funktion ausführst, aber
> den Code in der Funktion einfach ersetzt durch
> return data[n]

Auch dann pendelt der Wert zwischen 0 und 16777215.
Alsoo habt ihr natürlich Recht es liegt nicht an dem Filter sondern der 
Fehler liegt irgendwie an der Übergabe der Daten an die Funktion. Denn 
genau da entsteht diese Wertefolge.

von Achim S. (Gast)


Lesenswert?

Peter schrieb:
>         data_in[i] = data;
>
>         data_in[i] = diff(data_in,i);

Überschreibst du mit der zweiten Zeile nicht den Messwert an der i-ten 
Stelle, den du für die Filterung der nachfolgenden Messwerte noch 
brauchst?
Müsste es nicht folgendermaßen heißen?

>         data_in[i] = data;
>
>         data = diff(data_in,i);
>
>         USART_Transmit_4Bytes(data);

von Peter (Gast)


Lesenswert?

Achim S. schrieb:
> Überschreibst du mit der zweiten Zeile nicht den Messwert an der i-ten
> Stelle, den du für die Filterung der nachfolgenden Messwerte noch
> brauchst?
> Müsste es nicht folgendermaßen heißen?

>         data_in[i] = data;
>
>         data = diff(data_in,i);
>
>         USART_Transmit_4Bytes(data);

Das hatte ich auch schon vermutet und ausprobiert aber ändert sich 
nichts, bekomme immer noch diese seltsame Wertefolge und kann es mir 
nicht erklären.

War mir auch nicht ganz sicher ob der neue Wert data_in[i] dann mit dem 
von dem Filter berechnetem Wert überschrieben werden muss oder nicht. 
Ist aber Blödsinn das stimmt denn es heißt ja in der Gleichung x[n],.... 
und nicht y[n]

von Achim S. (Gast)


Lesenswert?

Peter schrieb:
> Das hatte ich auch schon vermutet und ausprobiert aber ändert sich
> nichts, bekomme immer noch diese seltsame Wertefolge und kann es mir
> nicht erklären.

richtig, das kann nicht der gesuchte Fehler sein, sonst hätte der Aufruf 
der Funktion mit

> return data[n]

dir ja vernünftige Werte geliefert. Aber damit das Filter richtig 
funktioniert, muss der Code dennoch geändert werden.


Kannst du uns zum Vergleich bitte noch den funktionierenden Code zeigen, 
auf dem folgende Aussage beruht?

Peter schrieb:
> wenn ich die Funktion des Differenzierfilters nicht
> ausführe und nur die Werte anzeige die ich einlese in den Puffer dann
> erhalte ich ein schönes EKG-Signal also korrekte Werte.

Und um die Sache komplett zu machen vielleicht noch die 
Deklaration/Initialisierung von data, data_in und i?

Ansonsten gilt weiterhin: falls du z.B. Debugger-Zugriff auf den 
Controller haben solltest wäre es am einfachsten direkt nachzuschauen, 
ab welchem Punkt die Werte "umkippen".

von Peter (Gast)


Lesenswert?

Achim S. schrieb:
> Kannst du uns zum Vergleich bitte noch den funktionierenden Code zeigen,
> auf dem folgende Aussage beruht?
> Und um die Sache komplett zu machen vielleicht noch die
> Deklaration/Initialisierung von data, data_in und i?

Das ist der funktionierende Code also der Code den ich eben gepostet 
habe nur ohne Ausführen der Funktion diff.
1
signed long data_in[5] = {0,0,0,0,0};
2
unsigned char i=0;
3
signed long data;
4
5
while(1)
6
  {    
7
    if(new_sample == 1)  
8
    {
9
      CS_state(0);
10
      SPI_TransmitByte(RDATA);
11
      status = SPI_Receive_3Bytes();
12
      data = SPI_Receive_3Bytes();
13
      CS_state(1);
14
      
15
      LOFF_STATP = status >> 12;
16
      LOFF_STATN = status >> 4;
17
      
18
      if((LOFF_STATP == 0) && (LOFF_STATN == 0))
19
      {
20
        data = check_negative(data);
21
        data = iir_bandpassx1(data,w_bandpassx1);
22
        data = iir_bandpassx2(data,w_bandpassx2);
23
        
24
        data_in[i] = data;  
25
26
        USART_Transmit_4Bytes(data);
27
28
        i++;
29
        if(i>=5)
30
        {
31
          i = 0;
32
        }  
33
      }
34
      else
35
      {
36
        USART_Transmit_4Bytes(0x000000);
37
      }
38
      new_sample = 0;  
39
    }
40
  }
41
}

Achim S. schrieb:
> Ansonsten gilt weiterhin: falls du z.B. Debugger-Zugriff auf den
> Controller haben solltest wäre es am einfachsten direkt nachzuschauen,
> ab welchem Punkt die Werte "umkippen".

Leider habe ich nicht die Möglichkeit zu Debuggen.

von Achim S. (Gast)


Lesenswert?

Peter schrieb:
> das ist der funktionierende Code also der Code den ich eben gepostet
> habe nur ohne Ausführen der Funktion diff.

Tja, dann sollte man den Fehler jetzt eigentlich erkennen können, aber 
ich sehe ihn leider auch nicht.

Peter schrieb:
> Leider habe ich nicht die Möglichkeit zu Debuggen.

Du hast keinen Debugger, aber du kannst den USART zum Debuggen benutzen. 
Erster Vorschlag: im zuletzt gezeigten, funktionierenden Code nur eine 
Zeile umändern in

Peter schrieb:
> USART_Transmit_4Bytes(data_in[i]);

Das sollte dir ja wieder die original Messdaten liefern. Wenn die Daten 
da noch gut aussehen: im nicht funktionierenden Code die 
USART-Senderoutine aus der Hauptschleife in die Funktion diff verlagen, 
und dort folgende Daten übermitteln:

data[n]
y

von Peter (Gast)


Lesenswert?

Achim S. schrieb:
> Du hast keinen Debugger, aber du kannst den USART zum Debuggen benutzen.
> Erster Vorschlag: im zuletzt gezeigten, funktionierenden Code nur eine
> Zeile umändern in
>
> Peter schrieb:
>> USART_Transmit_4Bytes(data_in[i]);
>
> Das sollte dir ja wieder die original Messdaten liefern. Wenn die Daten
> da noch gut aussehen: im nicht funktionierenden Code die
> USART-Senderoutine aus der Hauptschleife in die Funktion diff verlagen,
> und dort folgende Daten übermitteln:
>
> data[n]
> y

Jau gute Idee! Habs beides gemacht und beides mal werden die korrekten 
Daten per USART übermittelt...also muss es irgendwie bei der Rückgabe 
der Werte passieren.

von Achim S. (Gast)


Lesenswert?

Peter schrieb:
> Habs beides gemacht und beides mal werden die korrekten
> Daten per USART übermittelt...also muss es irgendwie bei der Rückgabe
> der Werte passieren.

na das gibt es doch nicht: am Ende der Funktion diff wird der 
Rückgabewert y richtig ausgegeben, aber nach dem Rücksprung in der 
Hauptschleife nicht?

Ich würde an deiner Stelle noch mal folgende drei Varianten probieren:

a) am Ende der Funktion diff ein
      USART_Transmit_4Bytes(y)

b) in der Hauptschleife ein
      USART_Transmit_4Bytes(diff(data_in,i))

c) in der Hauptschleife ein
      data=diff(data_in,i);
      USART_Transmit_4Bytes(data)

Wenn wir dann noch nicht kapieren, was abläuft, müssen wir jemanden 
fragen,  der sich mit sowas auskennt. Und dann wird es vielleicht Zeit 
sich anzuschauen, was für ein Assemblercode aus dem C-Code erzeugt 
wurde.

von Peter (Gast)


Lesenswert?

Achim S. schrieb:
> Ich würde an deiner Stelle noch mal folgende drei Varianten probieren:
>
> a) am Ende der Funktion diff ein
>       USART_Transmit_4Bytes(y)
>
> b) in der Hauptschleife ein
>       USART_Transmit_4Bytes(diff(data_in,i))
>
> c) in der Hauptschleife ein
>       data=diff(data_in,i);
>       USART_Transmit_4Bytes(data)

Variante a) gibt mir die korrekten Werte aus

Variante b) und c) nicht

Das ist doch echt kurios!!

von Erich (Gast)


Lesenswert?

>Leider habe ich nicht die Möglichkeit zu Debuggen.

Tja, dann würde ich jetzt mal, so langsam, nach knapp 1 Woche mit diesem 
Problem, evtl. mal die Anschaffung eines Debuggers in Erwägung ziehen.

Gruss

von Achim S. (Gast)


Lesenswert?

Das ist in der Tat seltsam.

Ich würde an deiner Stelle jetzt den Simulator/Dissambler bemühen und 
anschauen, wie das Ergebnis von Diff an die aufrufende Funktion 
zurückgegeben wird.

Und vielleicht kannst du ja in deinem Umfeld (zumindest leihweise) einen 
Debugger organisieren.

von Karl H. (kbuchegg)


Lesenswert?

Erich schrieb:
>>Leider habe ich nicht die Möglichkeit zu Debuggen.
>
> Tja, dann würde ich jetzt mal, so langsam, nach knapp 1 Woche mit diesem
> Problem, evtl. mal die Anschaffung eines Debuggers in Erwägung ziehen.

....
Er hat eine UART.

Weg vom jetzigen Frontend und stattdessen ein Terminal angehängt!

Dann kann man sich auch Zahlenwerte ausgeben lassen. Aber dieses 
Stochern im Nebel bringt dich nicht weiter! Da wirst du doch alt dabei.


Was hast du an UART Funktionen zur Verfügung? Da ist sicher auch eine 
dabei, mit der man sich einen String ausgeben lassen kann. (Ich nenn die 
mal UART_String)
1
#define ASCII_DUMP
2
3
...
4
#ifdef ASCII_DUMP
5
char line[80];
6
#endif
7
8
while(1)
9
  {    
10
    if(new_sample == 1)  
11
    {
12
      CS_state(0);
13
      SPI_TransmitByte(RDATA);
14
      status = SPI_Receive_3Bytes();
15
      data = SPI_Receive_3Bytes();
16
      CS_state(1);
17
      
18
      LOFF_STATP = status >> 12;
19
      LOFF_STATN = status >> 4;
20
      
21
      if((LOFF_STATP == 0) && (LOFF_STATN == 0))
22
      {
23
#ifdef ASCII_DUMP
24
        sprintf( line, "vom Sensor %ld\n", data );
25
        UART_String( line );
26
#endif
27
28
        data = check_negative(data);
29
        data = iir_bandpassx1(data,w_bandpassx1);
30
        data = iir_bandpassx2(data,w_bandpassx2);
31
32
#ifdef ASCII_DUMP
33
        sprintf( line, "nach Bandpass %ld\n", data );
34
        UART_String( line );        
35
#endif
36
37
#ifdef ASCII_DUMP
38
        sprintf( line, "Filter %d %ld %ld %ld %ld %ld\n", (int)i,
39
                                                       data_in[0],
40
                                                       data_in[1],
41
                                                       data_in[2],
42
                                                       data_in[3],
43
                                                       data_in[4] );
44
        UART_String( line );
45
#endif
46
47
        data_in[i] = data;  
48
        data_in[i] = diff(data_in,i);
49
50
#ifdef ASCII_DUMP
51
        sprintf( line, "nach Filter %ld\n", data_in[i] );
52
        UART_String( line );        
53
#else
54
        USART_Transmit_4Bytes(data_in[i]);
55
#endif
56
57
        i++;
58
        if(i>=5)
59
        {
60
          i = 0;
61
        }  
62
      }
63
      else
64
      {
65
#ifndef ASCII_DUMP
66
        USART_Transmit_4Bytes(0x000000);
67
#endif
68
      }
69
      new_sample = 0;  
70
    }
71
  }
72
}


und dann hat das Stochern im Nebel ein Ende, weil man die Werte schwarz 
auf weiß im Terminalprogramm auf dem PC sieht.
Nutz doch die Infrastruktur die du hast! Die ist mehr als ausreichend, 
um das Problem einzukreisen.

(UNd wenn du fertig bist, kommentierst du den #define für ASCII_DUMP aus 
und dein ganzer Debug-Test Code ist wieder weg und alles ist wieder so 
wie es vorher war. Nutze die Macht, Luke!)

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Achim S. schrieb:
>> Ich würde an deiner Stelle noch mal folgende drei Varianten probieren:
>>
>> a) am Ende der Funktion diff ein
>>       USART_Transmit_4Bytes(y)
>>
>> b) in der Hauptschleife ein
>>       USART_Transmit_4Bytes(diff(data_in,i))
>>
>> c) in der Hauptschleife ein
>>       data=diff(data_in,i);
>>       USART_Transmit_4Bytes(data)
>
> Variante a) gibt mir die korrekten Werte aus
>
> Variante b) und c) nicht
>
> Das ist doch echt kurios!!


Du hast nicht "zufällig" eine Warnung vom Compiler. Irgendwas in der 
Richtung: "call of undeclared function" oder so ähnlich?

Für diff gibt es einen Funktionsprototypen und der stimmt auch mit der 
Funktion überein bzw. die Funktion steht codemässig vor dem ersten 
Aufruf?


(Mein Bachkribbeln hat sich gerade zu Wort gemeldet, dass du genau das 
nicht hast, und der Compiler beim Aufruf aufgrund der C-Regeln annehmen 
muss, dass die Funktion entgegen der Realität einen int zurückliefert 
und keinen signed long)

von Peter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Du hast nicht "zufällig" eine Warnung vom Compiler. Irgendwas in der
> Richtung: "call of undeclared function" oder so ähnlich?
>
> Für diff gibt es einen Funktionsprototypen und der stimmt auch mit der
> Funktion überein bzw. die Funktion steht codemässig vor dem ersten
> Aufruf?
>
>
> (Mein Bachkribbeln hat sich gerade zu Wort gemeldet, dass du genau das
> nicht hast, und der Compiler beim Aufruf aufgrund der C-Regeln annehmen
> muss, dass die Funktion entgegen der Realität einen int zurückliefert
> und keinen signed long)

Aaaaaaah verdammt ich glaube es nicht wie kann man nur so blind 
sein...es lag tatsächlich an einem Fehler im Funktionsprototyp aber ich 
habe keine warnung vom compiler bekommen!!
Sorry dass ich euch so lange auf Trapp gehalten habe mit so einem dummen 
Fehler! ;-)

Vieeeelen Dank für eure Hilfe!!!

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> Aaaaaaah verdammt ich glaube es nicht wie kann man nur so blind
> sein...es lag tatsächlich an einem Fehler im Funktionsprototyp aber ich
> habe keine warnung vom compiler bekommen!!

Wie ist die genaue Code-Konstallation?
Hast du Compiler Warnings eingeschaltet?


Wenn du einen Prototypen hast und er Compiler den auch kennt wenn er 
sich die Funktion vornimmt UND die beiden nicht übereinstimmen, dann ist 
das keine Warning mehr sondern ein Error. Da muss der Compiler was dazu 
sagen. Aber es hängt davon ab, ob du den Compiler auch lässt.

Hast du das Filter zb in einem eigenen C-File ausgelagert
1
signed long diff(signed long *data, unsigned char n)
2
{
3
  ....
4
}

und dazu ein Header File
1
#ifndef FILTER_H_INCLUDED
2
#define FILTER_H_INCLUDED
3
4
int diff( signed long* data, unsigned char n );
5
#endif

dann muss dir der Compiler den Fehler ankreiden, wenn du ihn dazu in die 
Lage versetzt, in dem das C-File sein eigenes Header File inkludiert.
1
#include "filter.h"
2
3
signed long diff(signed long *data, unsigned char n)
4
{
5
  ....
6
}

verzichtest du auf diesen Include, dann verzichtest du damit auch auf 
eine Prüfung, die der Compiler für dich erledigen kann.


Auch in der Konstallation
1
int diff( signed long* data, unsigned char n );
2
3
4
int main()
5
{
6
   diff( ....
7
}
8
9
signed long diff(signed long *data, unsigned char n)
10
{
11
  ....
12
}

ist das ein Fehler (und keine Warnung), die dir der Compiler ankreiden 
muss.

D.h. sieh dir die genaue Konstruktion an, wie dieser Fehler vom Compiler 
unentdeckt bleiben konnte und überleg dir, was du tun kannst, damit er 
dir nie wieder passiert.

Der Compiler kann dir helfen. Aber du musst ihn auch lassen. Ein Teil 
dieses 'Lassens' besteht zb darin, dass man so gut wie alle Warnungen 
aktiviert, die es nur gibt. Kommerzieller Code muss auf dem höchsten 
Warning-Level (maximal eine Stufe drunter, wenn in der höchsten Stufe 
nur noch esoterische Angst-Warnungen kommen) völlig ohne Warnungen 
kompilieren!

Man kann blöde Fehler machen. Aber nur einmal. Ein zweites mal ist dann 
schon ein langes Gesicht und ein drittes mal darf es schon nicht mehr 
geben, weil man auf die Fehlersituation reagiert und für Abhilfe gesorgt 
hat.

von Peter (Gast)


Lesenswert?

Danke für die Hinweise nochmals Karl Heinz Buchegger!
Ich habe nun alle Warnungen aktiviert, dadurch sollten solche Fehler in 
Zukunft vermieden werden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.