PIC: Zeitmessung - float Addition scheitert

Gast #3668575
Hallo,

wir arbeiten auf einem easypic v7 board mit einem pic 18f4520 und haben 
Probleme bei der Addition von float Werten.
Konkret soll eine Zeitmessung über einen Interrrupt an einem Port 
stattfinden. Da die Zeitmessung über den TimerInterrrupt maximal 8,3s 
läuft, speichern wir die Anzahl der Überlaufe in der 
Interruptserviceroutine. Der Timer funktioniert soweit und sowohl der 
einzelne gemessene Wert im Timer, als auch die Anzahl der Überlaufe sind 
korrekt.
Wenn wir jetzt die Anzahl der Überlaufe mit der Zeitkonstante 
multiplizieren und den Timermesswert zu dieser Zahl addieren wollen, 
hängt sich das Programm bei der Addition auf.
1
unsigned int TimerValue;
2

3
float TimeConstant = 8.388608f; //Zeitkonstante für TimerInterruptÜberlauf
4
float TimeBetweenEdge = 0.0f;   //Zeit zwischen zwei Interruptflanken
5

6
float TempTimer1 = 0.0f;
7
float TempTimer2 = 0.0f;
8

9
TimerValue = TMR0L;        //Aktuelle Zeit im Timer
10
TimerValue += TMR0H << 8;
11
TempTimer1 = (TimerValue / 65535.0f) * TimeConstant;
12

13
TempTimer2 = (float)TimeCount * TimeConstant; //Zeit der Überlaufe
14
         
15
TimeBetweenEdge = TempTimer1 + TempTimer2 ;  //geht nicht

Hat jemand eine Idee warum die zwei float Werte nicht addiert werden 
können?
Moderator (Firma: Titel) Persönliche Seite
Ma!k schrieb:
> TimeBetweenEdge = TempTimer1 + TempTimer2 ;  //geht nicht
WAS geht nicht?
Und WIE merkst du das?

> Hat jemand eine Idee warum die zwei float Werte nicht addiert werden
> können?
Hast du einen Grund, das an dieser Stelle unbedingt brauchen zu 
müssen?

> pic 18f4520
Merke: es ist i.A. keine gute Idee, auf einem 8-Bit uC ohne 
Coprozessor/FPU Fließkommazahlen zu verwenden.
X4U schrieb:
> Ma!k schrieb:
>> Hat jemand eine Idee warum die zwei float Werte nicht addiert werden
>> können?
>
> Ist das der gesamte Code?

Ist die Frage ernst gemeint? Lies den Beitrag des TO's. Er beschreibt 
einerseits, dass der Timer Korrekt funktioniert, der Wert richtig 
gelesen werden kann und dass auch die ISR richtig aufgerufen wird.

Siehst du in diesem Teil des Codes irgendiene Initialisation? Siehst du 
ein Main? Denke, jeder der weiss was ein Controller zum funktionieren 
braucht, sieht auch direkt dass dies lediglich ein Ausschnitt sein kann.
Ich glaube du hast dem Problem an der falschen stelle nachgejagt.

Ma!k schrieb:
> TempTimer1 = (TimerValue / 65535.0f) * TimeConstant;

Wenn unsigned int 16 bit gross ist, wird dass immer 0 ergeben, weil
unsigned int / float = unsigned int
unsigned x;x/UINT_MAX==0;
Timer value muss zu float gekastet werden. Wir sind hier nicht in Java!

Also so:
TempTimer1 = ((float)TimerValue / 65535.0f) * TimeConstant;
Oder besser:
TimeConstant * TimerValue / 65535.0f
Gast
Lothar Miller schrieb:
> WAS geht nicht?
> Und WIE merkst du das?

Wie oben beschrieben hängt sich das Programm bei folgender Zeile auf:
1
TimeBetweenEdge = TempTimer1 + TempTimer2;
Festgestellt wurde dies unter anderem im Debugger. Wenn ich die Addition 
zum Test einmal weglasse und nur TempTimer1 in TimeBetweenEdge 
reinschreibe werden da auch die richtigen Werte ausgegeben. Genauso 
funktioniert es für TempTimer2. Es scheitert also wirklich an der 
Addition.

jetzt schrieb:
> Float is in den meisten Faelle unnoetig. Rechne in Millisekunden und
> behalte das Komma.

Die Zeitmessung soll allerdings über mehrere Minuten laufen. D.h. ein 
unsigned int würde vom Wertebereich nicht mehr ausreichen. Also würde 
ich auf einen unsigned long int ausweichen?


X4U schrieb:
> Ist das der gesamte Code?

Nein das ist natürlich nicht der gesamte Code sondern nur der Teil in 
dem der Fehler auftritt.


jetzt schrieb:
>>(float)TimeCount
>
> kommt aus dem Nichts.

TimeCount ist die Anzahl der Timer-Überlaufe und wird in der ISR 
hochgezählt.


Daniel A. schrieb:
> Wenn unsigned int 16 bit gross ist, wird dass immer 0 ergeben, weil
> unsigned int / float = unsigned int
> unsigned x;x/UINT_MAX==0;
> Timer value muss zu float gekastet werden. Wir sind hier nicht in Java!
>
> Also so:
> TempTimer1 = ((float)TimerValue / 65535.0f) * TimeConstant;
> Oder besser:
> TimeConstant * TimerValue / 65535.0f

Mit dem jetzigen Code kommt auch schon wieder ein float raus und es 
steht da auch wirklich die richtige Zeit drin, also nicht 0. Selbst 
wenn, sollte eine Addition mit 0.0f kein Problem sein.
Moderator (Firma: Titel) Persönliche Seite
Daniel A. schrieb:
> gekastet werden. Wir sind hier nicht in Java!
Wir haben auch keine Kasten. Wir sind hier nicht in Indien!

Der Code an sich funktioniert tadellos:
http://codepad.org/5Pxlqyyj
Das Problem liegt woanders...

Ma!k schrieb:
> Die Zeitmessung soll allerdings über mehrere Minuten laufen. D.h. ein
> unsigned int würde vom Wertebereich nicht mehr ausreichen. Also würde
> ich auf einen unsigned long int ausweichen?
Richtig. So machen es alle Anderen auch.
Ein float braucht genau so viel Speicherplatz wie ein long, nur sind die 
Rechnungen mit floats wesentlich ineffizienter...
Gast
>TimeBetweenEdge = TempTimer1 + TempTimer2 ;
>TempTimer1 = (TimerValue / 65535.0f) * TimeConstant;
TempTimer2 = (float)TimeCount * TimeConstant; //Zeit der Überlaufe
>TimeBetweenEdge = TempTimer1 + TempTimer2 ;


Ist irgendwie Quatsch. Macht
TimeBetweenEdge = (TimerValue/65535.0f + (float)TimeCount) * 
TimeConstant

Zum einen kann man * Timeconst weglassen, das bingt nichts.

Falls man das wirklich etwas so will, dann rechnet man :
(long) TimeBetweenEdge = TimeCount << 16 + TimerValue; //als Timer 
Einheiten.
Gast
Ma!k schrieb:
> Hat jemand eine Idee warum die zwei float Werte nicht addiert werden
> können?

Was willst du bei der Aktion überhaupt mit Float?
Welchen Dynamikbereich erwartest du, dass du auf Kosten der Genauigkeit 
die Dynamik vergrößerst?
Gast
Ok, also wir haben jetzt die float Operationen komplett weggelassen und 
alles mit int bzw. long berechnet. Jetzt funktioniert das Programm auch 
ohne Probleme.

Danke für eure schnelle Hilfe.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.