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
signedlongdiff(signedlong*data,unsignedcharn)
2
{
3
signedlongy=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
returny;
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.
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.
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! :-)
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;
}
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.
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.
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.
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.
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).
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.
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...
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.
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
> 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.
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.
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.
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)
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.
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.
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.
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.
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);
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]
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".
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
signedlongdata_in[5]={0,0,0,0,0};
2
unsignedchari=0;
3
signedlongdata;
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.
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
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.
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.
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!!
>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
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.
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)
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!)
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)
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!!!
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
signedlongdiff(signedlong*data,unsignedcharn)
2
{
3
....
4
}
und dazu ein Header File
1
#ifndef FILTER_H_INCLUDED
2
#define FILTER_H_INCLUDED
3
4
intdiff(signedlong*data,unsignedcharn);
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
signedlongdiff(signedlong*data,unsignedcharn)
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
intdiff(signedlong*data,unsignedcharn);
2
3
4
intmain()
5
{
6
diff(....
7
}
8
9
signedlongdiff(signedlong*data,unsignedcharn)
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.
Danke für die Hinweise nochmals Karl Heinz Buchegger!
Ich habe nun alle Warnungen aktiviert, dadurch sollten solche Fehler in
Zukunft vermieden werden.