Forum: Compiler & IDEs Ausgabe ADC-Werte mit C - WinAVR


von Matthias W. (matt007)


Lesenswert?

ich habe ein Arduino nano3-board und möchte z.B. 100 ADC-Werte 
freilaufend alle 104us unformatiert binär ins RAM schreiben und diese 
Werte dann aus dem RAM in echte Spannungswerte umgewandelt per UART zum 
Rechner schicken.

Der ADC liefert 0-1023 als Binärwert. Bei VREF=5V ist ~5mV Auflösung da. 
Sinnvoll wäre daher z.B. eine Ausgabe in der Form

uint    BCD-
Rohwert Ausgabe
0000 -> 0.000V
0001 -> 0.005V
1023 -> 5.000V

Um das zu erreichen kann man den ADC-Wert als unsigned int mit 5000 
multiplizieren und dann durch 1023 teilen.

Um Überlauf zu vermeiden muss dabei mit unsigned int long gearbeitet 
werden.

Eine andere Möglichkeit wäre z.B. erst mal nur mit 50 zu multiplizieren. 
Damit entsteht bei 1023*50=51150 erst mal kein uint Überlauf.

Dann jedoch müsste durch 10.23 geteilt werden. Oder man teilt durch 1023 
und multipliziert dann wieder mit 100.

Natürlich könnte man auch gleich mit float rechnen. Der Compiler setzt 
das ja in Code um. Der rechnet dann eben länger.

Hat mal jemand diese Methoden miteinander verglichen was Laufzeit und 
Codegröße anbelangt?

Am Ende muss der Wert in BCD gewandelt ausgegeben werden. Auch da gibt 
es verschiedene Ansätze. Hier sind es 4 Ziffern die auszugeben wären.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Matthias W. schrieb:
> Der rechnet dann eben länger.

Was erstmal noch zu beweisen wäre …

Ehrlich Jungs, ich verstehe dieses „Gleitkomma ist böse, muss ich auf
Teufel komm raus vermeiden“-Gehabe überhaupt nicht.  Am Ende braucht
die Ausgabe mehrere Millisekunden und wird einmal aller 200 ms
gerufen, aber es wird um die letzte Mikrosekunde gefeilscht, als wäre
es im Innern einer milliardenfach aufgerufenen Schleife, bei der es
wirklich drauf ankommt.

Wenn ich 5.000 als Ausgabe haben will, liegt es doch nun wirklich mehr
als nahe, das gleich mit Gleitkomma zu rechnen.

: Bearbeitet durch Moderator
von Matthias W. (matt007)


Lesenswert?

Jörg Wunsch schrieb:
> Was erstmal noch zu beweisen wäre …

Danke Jörg. Du meinst also es sei nicht sicher daß eine 
Float-Multiplikation viel schlechter abschneidet als die Versuche das 
mit Integer-Rechnungen hinzubiegen?

Zahlen hast Du keine?

von Matthias W. (matt007)


Lesenswert?

Jörg Wunsch schrieb:
> Ehrlich Jungs, ich verstehe dieses „Gleitkomma ist böse, muss ich auf
> Teufel komm raus vermeiden“-Gehabe überhaupt nicht.

ich bin da ja lernfähig. Vor Jahren arbeitete ich an einem Projekt wo 
man eine Wankstabilisierung im Auto mit Mikrocontroller realisierte. Es 
gab dazu eine Diplomarbeit zur Abschätzung der Performance.

Am Ende nahmen wir einen PowerPC-Controller mit FPU. Das war der 
wirtschaftlichste Weg damals damit umzugehen. Nachbarprojekte arbeiteten 
mit ASCET-SD - einer Toolumgebung um mit Festpunktarithmetik rechnen zu 
können. Man sieht wie unterschiedlich Ansätze sein können. In einem 
Projekt ohne FPU hatte bekam man Stress weil der Code am Ende kaum mehr 
reinpasste. Wenn man eine größere CPU genommen hätte wären viele 
Klimmzüge erspart geblieben . . .

Ich bin kein Feind einer Float-Rechnung. Gerne schaue ich mir Argumente 
und Zahlen dazu an.

von Uwe (de0508)


Lesenswert?

Hallo Matthias,

ich verwende dabei fast immer Ganzzahlberechnungen, um das Ergebnis als 
Festkommazahl mit drei  Nachkommastellen zu erhalten.

Im Datenblatt des atmega328p auf S.261 unter ADC Conversion Result 
wird die Berechnung der Spannung angegeben:

(1) ADC = Vin * 1024 / Vref
<==>
(2) Vin = ADC * Vref / 1024

Wenn man mit einer Skalierung s = 10^3 rechnet folgt:

(3) Vin = ADC *Vref *s /1024
    Vin = (ADC *5 *1000) /1024

Die ULONG (32Bit) Berechnung ist hier doch kein Beinbruch.

Der Divisor 1024 lässt sich als 10 facher rechts Shift |>> 10| 
schreiben.

Link
[1] http://www.atmel.com/Images/doc8161.pdf

: Bearbeitet durch User
von Matthias W. (matt007)


Lesenswert?

Danke Uwe für das Beispiel. Bei den 5V ist das erst mal ein guter Weg. 
Beim AVR Butterfly Datenlogger wird ein Floatrechnung verwendet. Ich 
habe nicht gemessen wie lange diese rechnet.

von Uwe (de0508)


Angehängte Dateien:

Lesenswert?

Matthias,

wenn die float und printf lib nicht eingebunden wird, spare ich mir 
einiges an Flash Speicher.

Das ist für mich eher ein Grund bei kleinen AVRs auf die 
Fließkommazahlen zu verzichten.

Da man aber immer noch eine Zahl formatieren muss, verwende ich eine 
kleine Lib valout von PeDa [1].

Das ist sicherlich sehr speziell, aber für genau die eine Anwendung - 
ADC Messwerte zu formatieren - passend.

Eine weitere alternative sind die Embedded String Functions [2] und 
General purpose numeral output module [3].

Eine "Reise" zu AVR assembler libraries for gcc projects [4] sollte 
man auch unternehmen.

Link
[1] Beitrag "Formatierte Zahlenausgabe in C"
[2] http://elm-chan.org/fsw/strf/xprintf.html
[3] http://elm-chan.org/docs/avrlib/xitoa.zip
[4] http://elm-chan.org/cc_e.html#avrgcc

von Matthias W. (matt007)


Lesenswert?

Vielen Dank Uwe - das sieht sehr hilfreich aus. Ich schau mal wie weit 
ich heute komme.

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.