mikrocontroller.net

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


Autor: Ruben (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Mathias Fendl (minglifu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das gefällt mir!

Autor: Ruben (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: DirkB (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Knut (Gast)
Datum:

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

Knut

Autor: DirkB (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil er vorzeichenbehaftet ist. von +(2^23)-1 bis -2^23

Autor: Knut (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das is plausibel... Danke

Knut

Autor: Armin W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk:

>Siehe Festkommaarithmetik

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

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

Autor: Ruben (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)) 
;

Autor: Chris (Gast)
Datum:

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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> result = result/56

Sorry, war zu schnell, ist falsch

richtig

result = result/*5614*

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.