ADC - Wert berechnen

OP #7456833
Lesenswert?

Hallo, Ich habe einen Drucksensor mit einem Messbereich von 0 - 10 bar und einen mit -1 - +1 bar. Beide geben eine analoge/lineare Spannung von 1-5 Volt aus. Die wird runter geteilt auf 1,235V und mit einem 10bit ADC eingelesen.

Bei einer Spannungsausgabe von 0-5 Volt wäre ja die Rechnung für den Druck ganz "normal":

U = 1,235 * (ADC/1023) Druck = 10 * (U/1,235)

Da mein Spannungsbereich am Sensor aber erst bei einem Volt beginnt, beträgt die Spannung am ADC 0,247 - 1,235V bzw. seine Werte von 205 - 1023 (Hab ich mir zumindest so zusammengereimt). Kann mir jemand sagen wie ich die Formel mit dem o.ä. Spannungsbereich aussehen müsste und wie würde sie mit dem Sensor: -1 - +1 Bar aussehen. Danke im Voraus. Alex

#7456850
Lesenswert?

na ja, der Messbereich umfasst halt 2 Bar zwischen -1 und +1. Damit liegt "0" bar genau "in der Mitte", also bei 512, 0 enspricht "-1" Bar und 1023 "+1" bar. Oder in deiner Formel Druck = -1 + 2*(U/Umax)

Das "Da mein Spannungsbereich am Sensor aber erst bei einem Volt beginnt" verstehe ich nicht

(Firma: Gast) #7456862
Lesenswert?

Alexander K. schrieb:

(ADC/1023)

Sollte da nicht 1024 stehen, wie im Datenblatt beschrieben?

Alexander K. schrieb:

Kann mir jemand sagen wie ich die Formel mit dem o.ä. Spannungsbereich aussehen müsste und wie würde sie mit dem Sensor: -1 - +1 Bar aussehen.

Lineare Interpolation. oder Geradengleichung.

In der Arduino Welt: https://www.arduino.cc/reference/de/language/functions/math/map/

Moderator (Firma: Titel) Persönliche Seite #7456872
Lesenswert?

Arduino F. schrieb:

Alexander K. schrieb:

(ADC/1023)

Sollte da nicht 1024 stehen

Korrekterweise und schon allein um es dem Compiler einfacher zu machen sollte da 1024 stehen.

Siehe den Beitrag "ADC-Spannung korrekt berechnen?" und den darin verlinkten Beitrag "1023 oder 1024"

Für mich sind 1023 an dieser Stelle schlicht ein Programmfehler. Und wenn ich diesen Fehler sehe, dann sind da sicher noch mehr...

#7456923
Lesenswert?

Alexander K. schrieb:

Ich gehe in gar keine Klasse und arbeite üblicherweise auch nicht in der Branche ;)

Schon mal was von einer linearen Geradengleichung gehört?

1
Sensor   ADC-Eingang ADC-Wert    Druck1   Druck2
2
1V       0,247V      205         0bar     -1bar
3
3V       0,741V      615         5bar      0bar
4
5V       1,235V      1023        10bar     1bar
5

6
p = f(adc) = M*ADC+N
7

8
// 10 Bar Sensor
9
M = dy/dx = (10bar-0bar)/(1023-205)=0,0122 bar/LSB
10
N = P2-M*ADC = 10bar - 0,0122bar/LSB*1023 = -2,506bar
11

12
// +/-1 Bar Sensor
13
M = dy/dx = (1bar- -1bar)/(1023-205)=0,002445 bar/LSB
14
N = P2-M*ADC = 1bar - 0,002445bar/LSB*1023 = -1,5bar

Man kann das mit Fließkomma rechnen und ist fertig. Man kann aber auch 5 Minuten nachdenken und Festkommaarithmetik benutzen. Wenn man alles in Millibar rechnet, braucht es keine Kommas. Dabei darf im Zwischenergebnis kein Überlauf auftreten, also Rechnung mit 32 Bit. Beim +/1bar Sensor reichen die Millibar nicht, da muss man eher auf Mikrobar gehen. Klingt komisch, ist aber so. Kann man aber am Ende wieder auf Millibar umrechnen.

1
int p;
2
p = 122 * (int32_t)ADC - 2506; // 10 bar Sensor
3
p = (2445 * (int32_t)ADC - 1500000) / 1000; // +/-1 bar Sensor
#7456928
Lesenswert?

Moin, ich habe so einen Drucksensor in mein Heizungsrohr eingebaut. Liefert auch von 1 bis 5 V. Dann ist es etwas in Vergessenheit geraten. Ich hatte vor, wie in anderen Schaltungen die Werte mit einem ATtiny84 zu messen und zu speichern. Abfrage über I2C. Der hat die Möglichkeit über“ Differential ADC Channel“ zu messen. Leider ist der Minuspol mit dem Gehäuse verbunden und somit der „Rauschabstand“ kleiner. Dadurch ist es für mich günstiger mit 5V VCC ADC Input Voltage Range zu messen. Gruß Carsten

OP #7456956
Lesenswert?

Falk B. schrieb:

1
> Sensor   ADC-Eingang ADC-Wert    Druck1   Druck2
2
> 1V       0,247V      205         0bar     -1bar
3
> 3V       0,741V      615         5bar      0bar
4
> 5V       1,235V      1023        10bar     1bar
5
> 
6
> p = f(adc) = M*ADC+N
7
> 
8
> // 10 Bar Sensor
9
> M = dy/dx = (10bar-0bar)/(1023-205)=0,0122 bar/LSB
10
> N = P2-M*ADC = 10bar - 0,0122bar/LSB*1023 = -2,506bar
11
> 
12
> // +/-1 Bar Sensor
13
> M = dy/dx = (1bar- -1bar)/(1023-205)=0,002445 bar/LSB
14
> N = P2-M*ADC = 1bar - 0,002445bar/LSB*1023 = -1,5bar
15
> 
16
>

Man kann das mit Fließkomma rechnen und ist fertig. Man kann aber auch 5 Minuten nachdenken und Festkommaarithmetik benutzen. Wenn man alles in Millibar rechnet, braucht es keine Kommas. Dabei darf im Zwischenergebnis kein Überlauf auftreten, also Rechnung mit 32 Bit. Beim +/1bar Sensor reichen die Millibar nicht, da muss man eher auf Mikrobar gehen. Klingt komisch, ist aber so. Kann man aber am Ende wieder auf Millibar umrechnen.

1
> int p;
2
> p = 12,2 * (int32_t)ADC - 2506; // 10 bar Sensor
3
> p = (2445 * (int32_t)ADC - 1500000) / 1000; // +/-1 bar Sensor
4
>

Danke für die konkrete Lösung! Funktioniert gut (nachdem ich deinen Kommafehler ausgebessert habe ;))

Für die 10 Bar Ausführung hätte ich mir jetzt auch die Formel zusammengereimt:

1
int p;
2
p = (10/819) * (adc-205);

Lineargleichnug dürfte aber die universellere Lösung sein.?

#7456967
Lesenswert?

Alexander K. schrieb:

Beide geben eine analoge/lineare Spannung von 1-5 Volt aus. Die wird runter geteilt auf 1,235V und mit einem 10bit ADC eingelesen.

Diesen Satz solltest du noch mal überdenken. Herunterteilen eines Bereichs auf einen festen Wert?? Ich nehme mal an, die wird mit 1,235/5 multipliziert. Sauber formulieren ist oft die halbe Lösung.

Ausgangslage bei dem +-1 Sensor: U_adc = U_sensor * 1,235/5 ADC = U_adc * 1024/1,235 U_sensor = 2*Druck + 3

Wir eliminieren U_adc: ADC = (U_sensor * 1,235/5) * 1024/1,235 U_sensor = 2*Druck + 3

Wir eliminieren U_sensor: ADC = (2*Druck + 3) * 1,235/5 * 1024/1,235

Auflösen nach Druck: Druck = (ADC * 5/1024 -3)/2

Kein Problem von Elektronik, kein Problem von Software. Stimmt schon, alles nur Rechnen Klasse 8 oder so.

#7457196
Lesenswert?

Alexander K. schrieb:

was spricht dagegen mit einem float oder double zu arbeiten?

Solange Dein Arduino genug freien Speicher hat, nichts.

Falk B. schrieb:

was spricht dagegen mit einem float oder double zu arbeiten?

Der 8-Bit Programmierer Ehrencodex ;-) Heutzutage schert sich kaum noch einer um Resourcenbedarf und sinnvoll Lösungen,

Man sollte sich bemühen, immer sparsam zu agieren. Im Gegensatz zum PC kann man im Mikrocontroller nicht mal eben etwas RAM / ROM nachrüsten.

#7457205
Lesenswert?

Falk B. schrieb:

Der 8-Bit Programmierer Ehrencodex ;-)

Na, nicht nur, Fließkommazahlen sind verbuggt. Mit Integern ist man da schon eher auf der sicheren Seite. Darüber hinaus kann man öfter auch (positive) Überraschungen erleben wenn man sich Mühe gibt, und kommt auch eher vom Automatismus weg, Fließkommazahlen benutzen zu müssen. Im Zweifelsfall kann man es einfacher machen, und fehlerfreier. Wie gesagt, im Zweifelsfall, aber nicht im Sinne von voreiliger Optimierung. Die ist nämlich zu recht als Wurzel allen Übels verpönt. Erstmal gucken, dass überhaupt was läuft. Also durchaus keine triviale Frage ;)

(https://softwareengineering.stackexchange.com/questions/80084/is-premature-optimization-really-the-root-of-all-evil)

#7457209
Lesenswert?

MaWin O. schrieb:

Wenn Moby das liest, eröffnet er gleich die nächsten 10 Threads.

Wäre ja gar nicht so schlimm, wenn das nicht ständig der selbe neuaufgegossene kalte Kaffee wäre. Ich fand z.B. diese zugeHolmten Threads gar nicht so übel, auch wenn ich gelegentlich recht dankbar war für das ein oder andere Stoppschild da.

Beitrag #7457222 wurde von einem Moderator gelöscht.
Beitrag #7457236 wurde von einem Moderator gelöscht.
#7457500
Lesenswert?

Arduino F. schrieb:

Tipp: Sage "immer"! Denn wüsste man vorher, ob sie exakt gleich sind, bräuchte man keinen Vergleich mehr.

Nein, sag ich nicht. Und natürlich können die Binärpräsentationen zweier Float Zahlen gleich sein, auch wenn man vorher nicht weiß, dass sie gleich sind.

Wenn klar ist, dass die Binärpräsentation der beiden zu vergleichenden Zahlen auf gleiche Weise entsteht, d.h. im Fall der "Gleichheit" beide binär gleich werden müssen, kann der Vergleich kappen ;-)

#7457562
Lesenswert?

Stefan F. schrieb:

Warum sollte eine Programmiersprache das verbieten? Float Variablen können den gleichen Wert enthalten.

Naja, sie können schon, aber häufig tun sie es nicht obwohl sie gleich sein müssten - wenn man es mit dem Taschenrechner nachrechnet. Verbieten muss man es nicht, aber vielleicht warnen? [Vielleicht tut das ein Compiler auch, habe schon lange keine Floats mehr verwendet].

Ich möchte nicht wissen, wie viele da schon darüber gestolpert sind ...

Wie wäre es mit |Wert1 - Wert2| < epsilon?

Moderator (Firma: Titel) Persönliche Seite #7457585
Lesenswert?

Stefan F. schrieb:

Das sind Grundlagen in praktisch jeder Programmiersprache.

Das sind die Grundlagen des üblichen binary32 Zahlentyps der IEEE754:

Stefan F. schrieb:

Rbx schrieb:

Fließkommazahlen sind verbuggt

Inwiefern?

Wenn man sie noch nicht ganz verstanden hat, dann mutet es einen leicht so an, wenn man einen Vergleich wie z.B.

1
f=2.0+1.33
2
if (f==3.33)
3
   tuwas();

macht und tuwas() nicht aufgeriufen wird.

Mich stört an floats eher, dass sie zwar eine gewaltige Dynamik haben, aber nur 6 signifikante Stellen. Man kann also nicht sicher sein, dass nach dieser Rechnung wie erwartet f = 100.001 ist.

1
 f = 1000.0;
2
 f+= 0.001;

Drum nehme ich float nur dort, wo es nötig ist. Und sonst eben einen Integer in "Dezigrad" oder "Centibar" oder "Millimeter", wenn ich wegen einer höheren Auflösung 0,1 Grad oder 0,01 bar oder 0,001 m auflösen will.

Moderator (Firma: Titel) Persönliche Seite #7457597
Lesenswert?

Falk B. schrieb:

Von einem 8-Bit Andruiden war in der gesamten Diskussion, bis auf meine Anmerkung des 8-Bit Programmierer Ehrenkodex, keine Rede.

Da hast du durchaus Recht.

Allerdings habe ich einfach auf den Eröffnungspost einen Wahrscheilichkeitsalgorithmus angewendet und besonders diese Information linear extrapoliert, wo

Alexander K. schrieb:

mit einem 10bit ADC eingelesen.

#7458301
Lesenswert?

Stefan F. schrieb:

Inwiefern?

Könntest du die Frage noch etwas genauer stellen? Auf Stackoverflow gibt es immerhin 10 Reputationpoints für eine gute Antwort auf eine ähnliche, allerdings genauere Frage. https://stackoverflow.com/questions/588004/is-floating-point-math-broken

So allgemein kann man nur sagen, dass Zahlen, wie z.B. 3,1415 für sich gesehen erstmal nicht problematisch sind. Die Probleme kommen in der Computeranwendung u.a. durch (statisches) Rundungsverhalten bei (iterierenden) Funktionen oder beim Zahlen konvertieren oder rund um Registerbitbreiten. Beim Heron-Verfahren zum Wurzelziehen, da sind die Fließkommazahlen ganz gut, denn das funktioniert über Annäherungen an die Genauigkeit.

Wenn es aber um hergeleitete Genauigkeit geht:

  • die Fließkommazahlen gaukeln Genauigkeit vor, obwohl sie nur als Annäherung zu verstehen sind und man aufpassen muss.
  • die Probleme, die sie mitbringen sind mehrdimensional, und man kann nicht alle Problemfälle überblicken -
  • man muss aber die Schwierigkeiten verstehen z.B. für Testprogramme, die dann wichtiger werden. Gibt man sich keine Mühe, kann es zum Unfall kommen, und das ist sch..

Fuzzy Logic könnte man eventuell auf Fließkommazahlen anwenden. Das ist aber wo implementiert?

#7458325
Lesenswert?

Lothar M. schrieb:

Und sonst eben einen Integer in "Dezigrad" oder "Centibar" oder "Millimeter", wenn ich wegen einer höheren Auflösung Z0,1 Grad oder 0,01 bar oder 0,01 m auflösen will.

me too und wenn ich größer oder gleich wissen will nehme ich strcmp will ich Kommata einsetzen durch umrechnen mache ich das im String um aus 500 CentiVolt 5,00V zu machen.

#7458489
Lesenswert?

Ich frage mich, wie viele sich die Mühe gemacht und wirklich einmal überprüft haben wie lange einfache FP-Rechenoperationen dauern.

Ich hab's vor langer Zeit schon, deshalb benutze ich FP selbst auf 8-Bittern ziemlich oft. WIMRE waren das nämlich so um die 300-500 CPU-Zyklen pro Operation bei den kleinen AVRs. Also 1/2ms bei einer CPU Geschwindigkeit von 1MHz. Oder 1/32ms bei 16MHz.

Wenn man eine Berechnung nur ein paar zehn- oder hundertmal pro Sekunde macht, interessiert das fast niemanden.(#)

Bei einer simplen Mul/Div Operation um ADC Werte umzurechnen, muss man sich auch keine Gedanken um die Genauigkeit von float/double machen. Oder um Error-Propagation, …

Wollt's nur mal erwähnen. ;-)

(#) Nitpicker mal ausgeschlossen.

Moderator (Firma: Titel) Persönliche Seite #7458609
Lesenswert?

Rolf schrieb:

Außer, wenn man Strom sparen muss

Oder wenn man z.B. solche Operationen auf ein größeres Array wiederholt anwenden muss.

Norbert schrieb:

WIMRE waren das nämlich so um die 300-500 CPU-Zyklen pro Operation bei den kleinen AVRs. Also 1/2ms

Eine einzige Rechenoperation macht kein Programm. Der Witz ist, dass jede einzelne derartige float-Rechnung eben 50 mal langsamer ist als die integer-Rechnung, die das selbe Ergebnis bringt. Und dann nennt der Programmierer den Controller "zu langsam", statt sein Programm "ungeeignet geschrieben".

Wenn man ein klein wenig Gehirnschmalz in sein Programm steckt, dann muss man oft überhaupt gar nicht umrechnen. Oder erst dann, wenn irgendwer irgendwelche Werte auf einer Anzeige sehen will.

#7458622
Lesenswert?

Lothar M. schrieb:

Der Witz ist, dass jede einzelne derartige float-Rechnung eben 50 mal langsamer ist als die integer-Rechnung

Nö Lothar, das ist kein Witz, das ist einfach so. Allerdings muss ich zugeben, das die CPUs nun nicht mehr zu 90% herum-idlen, sondern nur noch zu 89%. Das ist zugegebenermaßen nur schwer zu ertragen, aber man muss auch mal bereit sein ein Opfer zu bringen.

PS. Wenn ich auf anderen Systemen 500ksps per DMA vom ADC bekomme, diese verarbeiten und weiterschieben muss, dann nehme ich auch FixPoint. Dann, nur dann.

#7458639
Lesenswert?

Lothar M. schrieb:

Eine einzige Rechenoperation macht kein Programm. Der Witz ist, dass jede einzelne derartige float-Rechnung eben 50 mal langsamer ist als die integer-Rechnung, die das selbe Ergebnis bringt.

Das halte ich für einen Irrtum. Miss mal nach, wenn mit 16 oder eher 32 Bit grerechnet wird! Ich würde vermuten, daß Float weniger als Faktor 5 langsamer ist.

#7458799
Lesenswert?

Joachim B. schrieb:

meist geht es nicht um die Dauer sondern das einem der RAM ausgeht weil alles auf dem Stack passiert, das kann schöne versteckte Fehler ergeben.

Das tritt aber auch mit anderen Funktionalitäten auf und hat nichts direkt mit Floatingpoint zu tun. Ich empfehle bei Embedded Systemen immer Stacküberwachung einzubauen.

Die Diskussion scheint Richtung Glaubenskrieg zu gehen. Ich nutze das was am besten passt. Und auch auf kleinen 8Bittern funktioniert float gut. Und manchmal braucht man auch Integer/Fixpoint Operationen auf 32Bittern.

#7458808
Lesenswert?

Falk B. schrieb:

Und morgen geht die Welt unter! Nein! Der Norbert hat schon recht!

Nein, man redet hier ein Problem herbei, was man in einfachen Anwendungen kaum hat.

Mit dem Rechnen ist das auch so eine Sache: 16 MHz sind 0,0625µs. Mal 500 komme ich auf 32 MIKROsekunden, nicht ms!

Mein 8MHz-Arduino liest vom angeschlossenen ADS1115 alle 10 Sekunden zwei Spannungen und schreibt diese auf eine SD-Karte. Ich habe mich um Variablentypen nicht geschert, da fliegen 4 Nachkommastellen herum. Das läuft mit einer 18650-LiIon an die 500 Stunden, mit aktivem OLED natürlich weniger.

Mein Spannungslogger kann auch jede Sekunde zur Karte schreiben, da bin ich weder in Zeitnot noch stürzt irgendwas ab.

Zeitnot habe ich mal an anderer Stelle gefangen, wo die A/D des ATMega benutzt werden und damit eine Regelung im Millisekunden-Bereich läuft. Das war nicht die Float-Rechnerei, sondern zweistellige Millisekunden für mein I2C-LCD.

Ich hätte gerne ein Problem passt hier wohl besser.

#7458811
Lesenswert?

Ich hab mal gemessen. Einmal im Simulator im staubigen AVR-Studio mit dem ollen 2010er avr gcc (der noch einen "Bug" hat und sich in einigen Situationen viel RAM gönnt, so auch hier) und einmal mit Arduino UNO. Im AVR-Studio mit Optimierung -Os (minimale Codegröße) compiliert. Beim Arduino wurde die Zeit per Oszi gemessen. In beiden Fällen mit 16 MHz CPU-Takt.

1
WinAVR-20100110
2
        FLASH /B  RAM /B  Zeit /us
3
float    2860     264      197,0
4
int32     186       0        4,1
5

6
Arduino 1.8.13
7
        FLASH /B  RAM /B  Zeit /us
8
float    1666       9     23,0 
9
int32     920       9      4,2

Ziemliche Unterschiede! Aber bei ein paar handvoll oder auch hundert Berechnungen/s kein wirkliches Problem. Bei größeren Arduinos mit 32 Bit geht es noch schneller, wenn ne FPU vorhanden ist bedeutungslos.

Angehängte Dateien:
#7458843
Lesenswert?

Eine Sache die hier nicht berücksichtigt wird: Bei Integer-Operationen kann es unüberlegt schnell zu Überläufen kommen. So geschehen bei der Kalibration eines Sensors über eine Polynom-Funktion. Trotz Optimierungen konnte der Überlauf nur sehr aufwändig abgefangen werden, da sich die Faktoren in den Einzelgeräten stark unterschieden. Mit float hatte sich das Problem erledigt.

#7458865
Lesenswert?

Hallo, wenn man über “ Differential ADC Channel“ messen würde und dir Referenzspannung und Eingang mit einem Trimmer auf 4 V und 1V regeln würde, würden 1V =0bar =0 und 10bar =4V =1023 bzw. 1000 ergeben können (je nach Trimmung). Dadurch würden 1/5 der Werte nicht „verschenkt“ werden also 0-1V. Gruß Carsten

#7458873
Lesenswert?

Carsten-Peter C. schrieb:

wenn man über “ Differential ADC Channel“ messen würde und

Du hast mitbekommen, dass Alexander K. ausgestiegen ist und hofft, nach den Schulferien endlich Grundrechnen zu lernen?

Differential ist nett gedacht, aber er hat es ja nicht nötig, seinen ADC zu benennen. 10-Bit lässt einen AVR vermuten, der das vermutlich nicht kann.

Es fehlen auch Details zu den Drucksensoren. Dass die als Endwert 5 Volt liefern, lässt vermuten, dass es deren Betriebsspannung sein könnte. Da wäre eine ratiometrische Messung sinnvoll - also µC-Referenz und Sensoren an der selben Versorgung.

Moderator (Firma: Titel) Persönliche Seite #7458973
Lesenswert?

Rainer W. schrieb:

"unüberlegt" und "Integer-Operation" passt nicht wirklich zusammen

Generell finde ich, dass "unüberlegt" und "programmieren" nicht zusammenpassen.

Denn ich kann z.B.

1
int i = 1000000000;
2
i += 1;

schreiben und bekomme 1000000001 heraus.

Wenn ich aber

1
float f = 1000000000.0;
2
f += 1.0;

schreibe, dann ist f nach dem ersten Befehl annähernd 1000000000. Und nsch der Addition kommt unverändert annähernd 1000000000 heraus.

#7459011
Lesenswert?

Lothar M. schrieb:

Generell finde ich, dass…

Generell finde ich, dass man immer wissen sollte was man macht.

1
#include <stdio.h>
2

3
// gcc -Wall -Wextra -pedantic -std=c11 -Os -o "x" "x.c"
4

5
int main(void) {
6
    float xf = 0.0, yf = 1.0;
7
    double xd = 0.0, yd = 1.0;
8

9
    for(int i= 0; i < 25; i++) {
10
        xf += yf;
11
        printf("%3d %.25f\n", i, xf);
12
        yf /= 2.0;
13
    }
14
    for(int i= 0; i < 54; i++) {
15
        xd += yd;
16
        printf("%3d %.54f\n", i, xd);
17
        yd /= 2.0;
18
    }
19
    return 0;
20
}
1
~/tmp$ "./x"
2
  0 1.0000000000000000000000000
3
  1 1.5000000000000000000000000
4
  2 1.7500000000000000000000000
5
  3 1.8750000000000000000000000
6
  4 1.9375000000000000000000000
7
  5 1.9687500000000000000000000
8
  6 1.9843750000000000000000000
9
  7 1.9921875000000000000000000
10
  8 1.9960937500000000000000000
11
  9 1.9980468750000000000000000
12
 10 1.9990234375000000000000000
13
 11 1.9995117187500000000000000
14
 12 1.9997558593750000000000000
15
 13 1.9998779296875000000000000
16
 14 1.9999389648437500000000000
17
 15 1.9999694824218750000000000
18
 16 1.9999847412109375000000000
19
 17 1.9999923706054687500000000
20
 18 1.9999961853027343750000000
21
 19 1.9999980926513671875000000
22
 20 1.9999990463256835937500000
23
 21 1.9999995231628417968750000
24
 22 1.9999997615814208984375000
25
 23 1.9999998807907104492187500
26
 24 2.0000000000000000000000000
27
  0 1.000000000000000000000000000000000000000000000000000000
28
  1 1.500000000000000000000000000000000000000000000000000000
29
  2 1.750000000000000000000000000000000000000000000000000000
30
  3 1.875000000000000000000000000000000000000000000000000000
31
  4 1.937500000000000000000000000000000000000000000000000000
32
  5 1.968750000000000000000000000000000000000000000000000000
33
  6 1.984375000000000000000000000000000000000000000000000000
34
  7 1.992187500000000000000000000000000000000000000000000000
35
  8 1.996093750000000000000000000000000000000000000000000000
36
  9 1.998046875000000000000000000000000000000000000000000000
37
 10 1.999023437500000000000000000000000000000000000000000000
38
 11 1.999511718750000000000000000000000000000000000000000000
39
 12 1.999755859375000000000000000000000000000000000000000000
40
 13 1.999877929687500000000000000000000000000000000000000000
41
 14 1.999938964843750000000000000000000000000000000000000000
42
 15 1.999969482421875000000000000000000000000000000000000000
43
 16 1.999984741210937500000000000000000000000000000000000000
44
 17 1.999992370605468750000000000000000000000000000000000000
45
 18 1.999996185302734375000000000000000000000000000000000000
46
 19 1.999998092651367187500000000000000000000000000000000000
47
 20 1.999999046325683593750000000000000000000000000000000000
48
 21 1.999999523162841796875000000000000000000000000000000000
49
 22 1.999999761581420898437500000000000000000000000000000000
50
 23 1.999999880790710449218750000000000000000000000000000000
51
 24 1.999999940395355224609375000000000000000000000000000000
52
 25 1.999999970197677612304687500000000000000000000000000000
53
 26 1.999999985098838806152343750000000000000000000000000000
54
 27 1.999999992549419403076171875000000000000000000000000000
55
 28 1.999999996274709701538085937500000000000000000000000000
56
 29 1.999999998137354850769042968750000000000000000000000000
57
 30 1.999999999068677425384521484375000000000000000000000000
58
 31 1.999999999534338712692260742187500000000000000000000000
59
 32 1.999999999767169356346130371093750000000000000000000000
60
 33 1.999999999883584678173065185546875000000000000000000000
61
 34 1.999999999941792339086532592773437500000000000000000000
62
 35 1.999999999970896169543266296386718750000000000000000000
63
 36 1.999999999985448084771633148193359375000000000000000000
64
 37 1.999999999992724042385816574096679687500000000000000000
65
 38 1.999999999996362021192908287048339843750000000000000000
66
 39 1.999999999998181010596454143524169921875000000000000000
67
 40 1.999999999999090505298227071762084960937500000000000000
68
 41 1.999999999999545252649113535881042480468750000000000000
69
 42 1.999999999999772626324556767940521240234375000000000000
70
 43 1.999999999999886313162278383970260620117187500000000000
71
 44 1.999999999999943156581139191985130310058593750000000000
72
 45 1.999999999999971578290569595992565155029296875000000000
73
 46 1.999999999999985789145284797996282577514648437500000000
74
 47 1.999999999999992894572642398998141288757324218750000000
75
 48 1.999999999999996447286321199499070644378662109375000000
76
 49 1.999999999999998223643160599749535322189331054687500000
77
 50 1.999999999999999111821580299874767661094665527343750000
78
 51 1.999999999999999555910790149937383830547332763671875000
79
 52 1.999999999999999777955395074968691915273666381835937500
80
 53 2.000000000000000000000000000000000000000000000000000000
81
~/tmp$
#7459053
Lesenswert?

Rainer W. schrieb:

Generell finde ich, dass "unüberlegt" und "programmieren" nicht zusammenpassen.

Mit immer leistungsfähigeren Prozessoren und immer unübersichtlicheren Abstraktionsebenen/Bibliotheken fällt das leider immer häufiger zusammen. Die Beziehung zu dem, was der µC wirklich tut, gerät oft weit ins Hintertreffen.

Bist du des Mobys! ;-) Stimmt aber leider. Sieht man auch fast jeden Tag, was da an Softwareungetümen zusammengebacken wird, die immmer größer und träger werden! Bloatware at it's best!

#7459220
Lesenswert?

Falk B. schrieb:

Ich hab mal gemessen. Einmal im Simulator im staubigen AVR-Studio mit dem ollen 2010er avr gcc (der noch einen "Bug" hat und sich in einigen Situationen viel RAM gönnt, so auch hier) und einmal mit Arduino UNO.

Der Ramverbrauch its das eine, aber daß der (leicht staubige) arduino-gcc (7.3.0) bei float einen fast um den Faktor 10 schnelleren Code produzieren soll als der staubige 2010er (vermutlich ein 4.5), ist dann doch nicht nachvollziehbar.

Oliver

Moderator (Firma: Titel) Persönliche Seite #7459238
Lesenswert?

Norbert schrieb:

yf /= 2.0;

Irgendwie eine sehr vorteilhafte Wahl, wenn der Rechner sowieso im Binärsystem arbeitet und die Schleife genau rechtzeitig abgebrochen eird.

Mit ein paar Iterationen mehr oder einer unbinären Zahl sieht man das dann besser, dass dich der xf Wert nicht mehr ändert, obwohl yf nicht 0 ist.

1
#include <stdio.h>
2
int main(void) {
3
    float xf, yf;
4
    
5
    xf = 0.0, yf = 1.0;
6
    for(int i= 0; i < 30; i++) {
7
        xf += yf;
8
        printf("%3d %.25f %.025f\n", i, xf, yf);
9
        yf /= 2.0;
10
    }
11
    
12
    xf = 0.0, yf = 1.0;
13
    for(int i= 0; i < 30; i++) {
14
        xf += yf;
15
        printf("%3d %.25f %.025f\n", i, xf, yf);
16
        yf /= 3.33;
17
    }
18
    
19
    return 0;
20
}

Da sieht man dann, dass sich ab der der sechsten Nachkommastelle nichts mehr tut:

1
  0 1.0000000000000000000000000 1.0000000000000000000000000
2
  1 1.5000000000000000000000000 0.5000000000000000000000000
3
  2 1.7500000000000000000000000 0.2500000000000000000000000
4
  3 1.8750000000000000000000000 0.1250000000000000000000000
5
  4 1.9375000000000000000000000 0.0625000000000000000000000
6
  5 1.9687500000000000000000000 0.0312500000000000000000000
7
  6 1.9843750000000000000000000 0.0156250000000000000000000
8
  7 1.9921875000000000000000000 0.0078125000000000000000000
9
  8 1.9960937500000000000000000 0.0039062500000000000000000
10
  9 1.9980468750000000000000000 0.0019531250000000000000000
11
 10 1.9990234375000000000000000 0.0009765625000000000000000
12
 11 1.9995117187500000000000000 0.0004882812500000000000000
13
 12 1.9997558593750000000000000 0.0002441406250000000000000
14
 13 1.9998779296875000000000000 0.0001220703125000000000000
15
 14 1.9999389648437500000000000 0.0000610351562500000000000
16
 15 1.9999694824218750000000000 0.0000305175781250000000000
17
 16 1.9999847412109375000000000 0.0000152587890625000000000
18
 17 1.9999923706054687500000000 0.0000076293945312500000000
19
 18 1.9999961853027343750000000 0.0000038146972656250000000
20
 19 1.9999980926513671875000000 0.0000019073486328125000000
21
 20 1.9999990463256835937500000 0.0000009536743164062500000
22
 21 1.9999995231628417968750000 0.0000004768371582031250000
23
 22 1.9999997615814208984375000 0.0000002384185791015625000
24
 23 1.9999998807907104492187500 0.0000001192092895507812500
25
 24 2.0000000000000000000000000 0.0000000596046447753906250
26
 25 2.0000000000000000000000000 0.0000000298023223876953125
27
 26 2.0000000000000000000000000 0.0000000149011611938476562
28
 27 2.0000000000000000000000000 0.0000000074505805969238281
29
 28 2.0000000000000000000000000 0.0000000037252902984619141
30
 29 2.0000000000000000000000000 0.0000000018626451492309570
31
  0 1.0000000000000000000000000 1.0000000000000000000000000
32
  1 1.3003003597259521484375000 0.3003003001213073730468750
33
  2 1.3904806375503540039062500 0.0901802703738212585449219
34
  3 1.4175617694854736328125000 0.0270811617374420166015625
35
  4 1.4256942272186279296875000 0.0081324810162186622619629
36
  5 1.4281364679336547851562500 0.0024421864654868841171265
37
  6 1.4288698434829711914062500 0.0007333893445320427417755
38
  7 1.4290900230407714843750000 0.0002202370378654450178146
39
  8 1.4291561841964721679687500 0.0000661372469039633870125
40
  9 1.4291760921478271484375000 0.0000198610359802842140198
41
 10 1.4291820526123046875000000 0.0000059642752603394910693
42
 11 1.4291838407516479492187500 0.0000017910736005433136597
43
 12 1.4291844367980957031250000 0.0000005378599325922550634
44
 13 1.4291845560073852539062500 0.0000001615194946680276189
45
 14 1.4291845560073852539062500 0.0000000485043543108076847
46
 15 1.4291845560073852539062500 0.0000000145658720640540196
47
 16 1.4291845560073852539062500 0.0000000043741357202975450
48
 17 1.4291845560073852539062500 0.0000000013135542653586185
49
 18 1.4291845560073852539062500 0.0000000003944607418482349
50
 19 1.4291845560073852539062500 0.0000000001184566750245253
51
 20 1.4291845560073852539062500 0.0000000000355725761347347
52
 21 1.4291845560073852539062500 0.0000000000106824549206408
53
 22 1.4291845560073852539062500 0.0000000000032079443268440
54
 23 1.4291845560073852539062500 0.0000000000009633466984196
55
 24 1.4291845560073852539062500 0.0000000000002892933017706
56
 25 1.4291845560073852539062500 0.0000000000000868748635855
57
 26 1.4291845560073852539062500 0.0000000000000260885470128
58
 27 1.4291845560073852539062500 0.0000000000000078343983116
59
 28 1.4291845560073852539062500 0.0000000000000023526721275
60
 29 1.4291845560073852539062500 0.0000000000000007065081696

Oliver S. schrieb:

ist dann doch nicht nachvollziehbar.

Wundert mich schon auch ein wenig. 10 Jahre Compilerentwicklung ergeben 10 fach schnelleren Code. Wenn man das mal extrapoliert...

#7459277
Lesenswert?

Lothar M. schrieb:

Irgendwie eine sehr vorteilhafte Wahl, wenn der Rechner sowieso im Binärsystem arbeitet

Das war ja der Plan. Man kann - so wie du - zeigen, das man sich Probleme einfangen kann wenn man im Dezimalsystem über die Genauigkeit einer float Variablen hinaus noch weiter arbeiten will. Oder das man eine erstaunliche Genauigkeit erreicht, wenn man die Mantisse im dualen System massiert. Beides ist richtig, beides muss man wissen.

PS. Die Schleifen wurden nicht rechtzeitig abgebrochen, sondern erst nachdem der erste Rechenfehler auftrat. So ehrlich bin ich dann doch… ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren