Forum: Compiler & IDEs Float vermeiden, ADC-Ergebnis umrechnen?


von Ruben (Gast)


Lesenswert?

Hallo,

mein 24 bit DAC liefert 0,5  VREF  2^23 -1 als "Vollausschlag". Mein 
Drucksensor liefert eine bestimmte Spannung unterhalb von 0,5 * VREF als 
Vollausschlag.

Jetzt würde ich gerne das Ergebnis (steht in einem int32_t) zur 
Displayausgabe in die physikalische Einheit umrechen (hier Druck, 
Pascal). Dabei würde ich gerne auch zwei Kommastellen ausgeben!

Wie mache ich das am besten, ohne float benutzen zu müssen? Den Artikel 
über Festkommaarithmetik habe ich mir durchgelesen, aber nicht ganz 
verstanden.

Der direkte Zusammenhang zwischen physikalischer Größe und DAC 
Datenregister
wäre:

druck = dac / 56,1486412316

Danke schonmal für Tips in die richtige Richtung.

von Klaus W. (mfgkw)


Lesenswert?

Als Tip, wo du noch etwas selber rechnen musst:

Den Wert teilen durch 56 ist ja zu ungenau, durch de exakten
Wert teilen geht nicht ohne Gleitkommarechnung.
Also ein kleiner Umweg: durch 56.1486412316 teilen ist
dasselbe wie mit 0.01780987 multiplizieren. Das sieht zwar
auch nach Gleitkomma aus, aber man kann ja auch mit
0.1780987 multiplizieren und sich mekren, daß das Ergebnis
um 10 zu groß ist, oder mit 1.780987 und sich den Faktor 100
merken, oder mit 17.80987 multiplizieren und 1000 merken...

Dein AD-Wert nutzt die 32 Bit ja nicht aus. Also kannst
du sehen, wie weit du das obige Spiel treiben kannst, bevor
die 32 Bit nicht mehr reichen.
Mit der größtmöglichen Zahl multiplizierst du jetzt (ganzzahlig),
konvertierst z.B. mit ultoa() in einen String und gibst den aus,
allerdings mit einem eingefügten Dezimalpunkt oder Komma an der
Stelle, die sich aus dem gemerkten Korrektutfaktor ergibt (z.B.
4. Stelle von hinten bei 10000).

von Mathias F. (minglifu)


Lesenswert?

Das gefällt mir!

von Ruben (Gast)


Lesenswert?

Danke für den Tip. Aber von 24 bit bis 32 bit sind ja nur 8 bit 
Unterschied, der maximale Faktor also 256. Oder vertue ich mich da? Dann 
könnte ich maximal mit 178 multiplizieren und dann durch 100 teilen. 
Wenn ich das richtig sehe, hätte ich dann meine zwei Dezimalstellen, 
oder? Wenn auch mit einem leichten Rechenfehler.

von Oliver (Gast)


Lesenswert?

Ruben schrieb:
> Danke für den Tip. Aber von 24 bit bis 32 bit sind ja nur 8 bit
> Unterschied, der maximale Faktor also 256. Oder vertue ich mich da? Dann
> könnte ich maximal mit 178 multiplizieren und dann durch 100 teilen.

Rechnerisch sind das nur 8 Bit, praktisch wette ich, daß du mindestens 
16 bit Unterschied nutzen kannst.

Die Hardware, die an einem 24-Bit-AD-Wandler auch noch das letzte Bit 
sinnvoll nutzbar macht, möchte ich sehen. Vermutlich enthalten die 
unteren 8 bit nur reines Rauschen.

Oliver

von Falk B. (falk)


Lesenswert?


von Klaus (Gast)


Lesenswert?

Ich stelle mir gerade die Anzeige von 24 Bit als Dezimalzahl mit 2 
Stellen hinter dem Komma vor:
Max Wert :   167 772,15 hPa (sollte Druck sein?)
Min Wert :         0,01

MfG Klaus

von DirkB (Gast)


Lesenswert?

Ich habe das so verstanden:

(2^23-1) / 56,1486412316 Pa

 = 8388607 / 56,1486412316 Pa
 = 149400,00 Pa
 = 1494,0000 hPa

Das ist zwar für Luftdruck ein bisschen hoch, aber man braucht ja noch 
Reserven :-)

@Ruben
Überleg dir aber mal:
- wieviel Volt diese Nachkommstellen haben?
- welche Genauigkeit hat der ADC?
- wie ist der ADC kalibriert?
- wie hoch ist das Rauschen?
- welche Genauigkeit hat der Sensor?

Die Unsicherheit bei (Spitzen-)Kalibrierlaboratorien liegt bei ca. 0,02 
hPa im atmosphärischen Bereich.

Du wirst die Nachkommstellen nicht wirklich brauchen.

von Knut (Gast)


Lesenswert?

Nur mal so am Rande, wieso eigentlich bei einem 24-Bit ADC (2^23)-1 und 
nicht (2^24)-1?

Knut

von DirkB (Gast)


Lesenswert?

Weil er vorzeichenbehaftet ist. von +(2^23)-1 bis -2^23

von Knut (Gast)


Lesenswert?

Das is plausibel... Danke

Knut

von Armin W. (Gast)


Lesenswert?

@Falk:

>Siehe Festkommaarithmetik

Ruben:
>Den Artikel über Festkommaarithmetik habe ich mir durchgelesen, aber nicht ganz
>verstanden.

Siehe http://www.mikrocontroller.net/articles/Netiquette

von Ruben (Gast)


Lesenswert?

Moin DAC hat einen Bereich von -2,5V bis 2,5V. Mein Sensor liefert aber 
nur +/- 200mV bei Vollausschlag. Wenn ich den Ausgangswert durch 56 
teile, gehen Informationen verloren. Die Nachkommastellen würden schon 
noch ziemlich stabil bleiben. Mir geht es nicht um absolute Genauigkeit, 
sondern hauptsächlich um Auflösung. Ich muss den Zeitpunkt und die 
ungefähre Amplitude von kleinen Drucksprüngen auswerten.

von Chris (Gast)


Lesenswert?

Naja, es ist ganz einfach. Mache ein Beispiel mit 16bit 
Festkomma-Aritmetik,
sollte der Compiler long long beherrschen (multiplication) dann kannst 
du auch 32.32bit Festkomma-Aritmetik machen.

Beispiel dac/adc result = 100
wird dividiert durch 56,1486412316
Hier ist es vereinfacht, man muß auch gegenrechnen,
z.B. macht (float)(0xffff)/(unsigned int)(0xffff/56.1486412316)
56.1576692373607540702656389032 und nicht 56.1486412316
hier würde man den Fehler ausbessern, indem man
value=value*1167+value>>7 macht, als Beispiel um den Fehler von
0.009028... bei der Division auszubessern. Diese Sachen sind meist
Handoptimiert, oder man nimmt einen generelle fixnum lib.

Zuerst mal wird die division in eine Multiplication umgewandelt.
Hier da 16 bit Fixmath wird 0xffff verwendet.
Wegen mycast sowie high/low bin ich mir unsicher ob das so funktioniert,
kann mittels union, ... gemacht werden, prinzipiell ist es so aber 
einfacher
zu verstehen. high(value) => (value>>16) -- low(value) ==(value&0xffff)

int32_t value;
#define mycast(x,type,offset) ((uint[])(unsigned int)&x)[offset]
#define high(x) mycast(x,uint16_t,0)
#define low(x) mycast(x,uint16_t,1)
#define DIV(x) (unsigned int)(0xffff/(x))
value=100;
value *= DIV(56.1486412316);
printf("%d",high(value)); high(value)=0;
if(value)
for(printf(",");value;high(value)=0)value*=10,printf("%01d",high(value)) 
;

von Chris (Gast)


Lesenswert?

und schon wieder so ein ärgerlicher Fehler, bei mycast(x,type,offset)
muss es mycast(x,uint,offset) heissen.

von Klaus (Gast)


Lesenswert?

Ruben schrieb:
> Moin DAC hat einen Bereich von -2,5V bis 2,5V. Mein Sensor liefert aber
> nur +/- 200mV bei Vollausschlag. Wenn ich den Ausgangswert durch 56
> teile, gehen Informationen verloren. Die Nachkommastellen würden schon
> noch ziemlich stabil bleiben. Mir geht es nicht um absolute Genauigkeit,
> sondern hauptsächlich um Auflösung. Ich muss den Zeitpunkt und die
> ungefähre Amplitude von kleinen Drucksprüngen auswerten.

Du willst 2 Stellen hinter dem Komma, also (Pseudocode):

result = ADCvalue * 100

Da dein ADC-Ergebniss weniger als 20 Bit hat (0,2V von 2,5V), gibts 
keinen Überlauf.

result = result/56

alle anderen digits in deinem Faktor machen weniger aus, als die 2 
Stellen hinter dem Komma anzeigen können.

dann

print result/100
print ','          // oder '.'
print result^100   // Modulo

MfG Klaus

von Klaus (Gast)


Lesenswert?

Klaus schrieb:
> result = result/56

Sorry, war zu schnell, ist falsch

richtig

result = result/*5614*

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.