Was machst du wenn du Spannungen oder Ströme misst und damit im µC rechnen willst ? Da will man ja auf die Genauigkeit von float oder double nicht verzichten unter anderem.
Wenn man mit einem µC Ströme oder Spannungen misst, dann oft mit 10-12 Bit Auflösung. 16 Bit Auflösung ist schon eher die Seltenheit. Wenn man eine float oder double Bibliothek einbinden kann, dann dürfte man kaum Speicherplatzprobleme haben. Das war ein Tipp a) um zu zeigen, dass es geht und b) für Leute, die mit kleinen µC arbeiten und z.B. nur 64 Byte RAM haben oder aus Geschwindigkeitsgründen lieber in Registern arbeiten als mit RAM zugriffen. Generell empfehle ich bei der Programmierung float und double zu vermeiden, wenn es nicht wirklich notwendig ist. Lieber auf das Problem angepasste Festpunktaritmetik (=Integeraritmetik) verwenden, dann kann man auch mit kleinen Controllern viel erreichen.
Danke für die Antwort ! Also benutzt du auch bei ADC Messungen bei kleinen µC oft Integerarithmetik ? Also ja ich bezog mich auch auf kleine µC die kaum Speicherplatz haben. Würde sicher keinen Sinn bei hochpräzisen 16-24bit Messungen machen da am Integer zu sparen ich würde da denk ich auf einen großen wechseln und mit double arbeiten. 🙂
@@Telectronics Das geht eigentlich super. Man muss sich gedanklich nur einen Dezimalpunkt in der Integerzahl vorstellen. z.B. 0-5V mit 12-Bit. Liefert 0-4095. Wenn man nun 5000 als anzeige will, dann wählt man z.B. eine uint32_t Variable und multipliziert mit dem Wert 5001 (=5000*4096/4095 gerundet) und schiebt anschließend um 12Bit nach rechts (hebt das *4096 wieder auf). Und wenn es besonders "luxeriös" sprich gut werden soll, kann man vor dem Rechtsschieben noch 2048 (= 4096/2) addieren und bekommt eine 4/5er Rundung. Dann ist der höchste Wert auch genau 5000. Und das geht super schnell, weil nur Multiplikation und Schieben verwendet wird.
@@iurlc Super ! Das werde ich mal ausprobieren ! Hätte ich auch gleich drauf kommen können das du das im Binärformat und nicht als Dezimalzahl rechnest. Das macht den Integerkram super weil es überhaupt keine Kommastellen gibt sondern alles nur ganze Zahlen sind. Eben die 0-4095 oder 12Bit und wenn es nicht reicht wobei 1,22mV Auflösung bei 5V deckt schon vieles ab. Ist ja praktisch schon im Rauschen. Das luxuriöse mit dem Schieben wusste ich aber gar nicht von daher 👍
Gute Ergänzung für Integer. Bei float geht es nur bei Zahlen ohne Nachkommastellen und wenn der Exponent nicht zu unterschiedlich ist gut. Sobald man Nachkommastellen hat und die Vorkommazahl um den Faktor 10 oder größer unterscheiden geht es nicht mehr, weil die ja immer auf den Exponenten normiert werden und es dann schnell zu Problemen kommt, weil ein paar Nachkommastellen bei der Subtraktion verloren gehen. Ich würde es bei float nicht verwenden. Einfach mal ein Testprogramm schreiben und sich alle Nachkommastellen vor und nach dem Tausch anzeigen lassen.
@@PedaleLR Ich hatte noch einen Gedankenfehler in meiner Antwort. Wir bewegen uns ja im dualen Zahlensystem. Also ist bereits bei einen Unterschied um den Faktor 2 das Problem da. Habe es mal auf einem Arduino Nano mit 0.3 und 1.7 ausprobiert. Vor dem Tausch A=0.30000000 B=1.70000004 Nach dem Tausch A=1.70000004 B=0.29999995
Das hätte ich auch vermutet - mir ging es hier um Speicherplatzsparen bei kleinen µC mit sagen wir mal 16 oder 32 Byte RAM. Ich habe eben mal eine Messung gemacht und das Ergebnis hat mich auch überrascht: int8_t Hilfsvariable=9 Exor-Tausch =8 int16_t Hilfsvariable=19 Exor-Tausch =16 int32_t Hilfsvariable=38 Exor-Tausch =32 Offenbar kann der C-Compiler den Code mit weniger Speicherzugriffen besser optimieren.
@@iurlc Ich kenne diese aufgeblasenen compilierten C-Progamme für den Arduino. Darum hatte ich dann Assembler genommen, mit dem ich auch nie Ram-Platzprobleme bekam. Allerdings waren auch keine komplexeren Routinen, wie Diplaytreiber etc. dabei.
@@karlbesser1696 In diesem Fall hat der C-Compiler sehr gute Arbeit geleistet. Ein Transfer vom RAM ins Register und umgekehrt kostet jeweils laut Datenblatt 2 Taktzyklen. Also benötigt selbst ein Assemblerprogramm 2x2Taktzyklen, um die beiden Variablen vom RAM in 2 Register zu schieben und noch mal 2x2 Taktzyklen um sie wieder in umgekehrter Anordnung zurück ins RAM zu schreiben. Es ist richtig, dass das Grundsystem erst mal 444 Bytes Flash-Speicher und 9 Bytes RAM braucht, damit das System mit der Entwicklungsumgebung kommunizieren kann und eine C-Umgebung (Stack, ect.) geschaffen wird. Aber der darauf aufbauende Code ist normalerwiese sehr kompakt.
@@iurlc Danke, dass du dir die Mühe machtest, meine Vermutungen zu verifizieren. Bisher hatte ich mir noch nicht die Mühe gemacht, die eigentlichen Routinen, wie sie der Compiler in den Flash schreibt, zu deassemblieren und auf Ballast zu prüfen. Gruß Karl.
Was machst du wenn du Spannungen oder Ströme misst und damit im µC rechnen willst ? Da will man ja auf die Genauigkeit von float oder double nicht verzichten unter anderem.
Wenn man mit einem µC Ströme oder Spannungen misst, dann oft mit 10-12 Bit Auflösung. 16 Bit Auflösung ist schon eher die Seltenheit. Wenn man eine float oder double Bibliothek einbinden kann, dann dürfte man kaum Speicherplatzprobleme haben. Das war ein Tipp a) um zu zeigen, dass es geht und b) für Leute, die mit kleinen µC arbeiten und z.B. nur 64 Byte RAM haben oder aus Geschwindigkeitsgründen lieber in Registern arbeiten als mit RAM zugriffen.
Generell empfehle ich bei der Programmierung float und double zu vermeiden, wenn es nicht wirklich notwendig ist. Lieber auf das Problem angepasste Festpunktaritmetik (=Integeraritmetik) verwenden, dann kann man auch mit kleinen Controllern viel erreichen.
Danke für die Antwort ! Also benutzt du auch bei ADC Messungen bei kleinen µC oft Integerarithmetik ? Also ja ich bezog mich auch auf kleine µC die kaum Speicherplatz haben. Würde sicher keinen Sinn bei hochpräzisen 16-24bit Messungen machen da am Integer zu sparen ich würde da denk ich auf einen großen wechseln und mit double arbeiten. 🙂
@@Telectronics Das geht eigentlich super. Man muss sich gedanklich nur einen Dezimalpunkt in der Integerzahl vorstellen. z.B. 0-5V mit 12-Bit. Liefert 0-4095. Wenn man nun 5000 als anzeige will, dann wählt man z.B. eine uint32_t Variable und multipliziert mit dem Wert 5001 (=5000*4096/4095 gerundet) und schiebt anschließend um 12Bit nach rechts (hebt das *4096 wieder auf). Und wenn es besonders "luxeriös" sprich gut werden soll, kann man vor dem Rechtsschieben noch 2048 (= 4096/2) addieren und bekommt eine 4/5er Rundung. Dann ist der höchste Wert auch genau 5000. Und das geht super schnell, weil nur Multiplikation und Schieben verwendet wird.
@@iurlc Super ! Das werde ich mal ausprobieren ! Hätte ich auch gleich drauf kommen können das du das im Binärformat und nicht als Dezimalzahl rechnest. Das macht den Integerkram super weil es überhaupt keine Kommastellen gibt sondern alles nur ganze Zahlen sind. Eben die 0-4095 oder 12Bit und wenn es nicht reicht wobei 1,22mV Auflösung bei 5V deckt schon vieles ab. Ist ja praktisch schon im Rauschen. Das luxuriöse mit dem Schieben wusste ich aber gar nicht von daher 👍
So könnte es auch mit float klappen (allerdings mit Wertebereichbeschränkung)
A=A+B
B=A-B
A=A-B
Gute Ergänzung für Integer. Bei float geht es nur bei Zahlen ohne Nachkommastellen und wenn der Exponent nicht zu unterschiedlich ist gut. Sobald man Nachkommastellen hat und die Vorkommazahl um den Faktor 10 oder größer unterscheiden geht es nicht mehr, weil die ja immer auf den Exponenten normiert werden und es dann schnell zu Problemen kommt, weil ein paar Nachkommastellen bei der Subtraktion verloren gehen. Ich würde es bei float nicht verwenden. Einfach mal ein Testprogramm schreiben und sich alle Nachkommastellen vor und nach dem Tausch anzeigen lassen.
Genau deshalb die Klammern in meinem Post ;-)
@@PedaleLR Ich hatte noch einen Gedankenfehler in meiner Antwort. Wir bewegen uns ja im dualen Zahlensystem. Also ist bereits bei einen Unterschied um den Faktor 2 das Problem da. Habe es mal auf einem Arduino Nano mit 0.3 und 1.7 ausprobiert.
Vor dem Tausch
A=0.30000000
B=1.70000004
Nach dem Tausch
A=1.70000004
B=0.29999995
Mal die Anzahl der Taktzyklen im MC für beide Varianten abzählen. Ich vermute mit Hilfsspeicherzelle sind es weniger.
Das hätte ich auch vermutet - mir ging es hier um Speicherplatzsparen bei kleinen µC mit sagen wir mal 16 oder 32 Byte RAM. Ich habe eben mal eine Messung gemacht und das Ergebnis hat mich auch überrascht:
int8_t
Hilfsvariable=9
Exor-Tausch =8
int16_t
Hilfsvariable=19
Exor-Tausch =16
int32_t
Hilfsvariable=38
Exor-Tausch =32
Offenbar kann der C-Compiler den Code mit weniger Speicherzugriffen besser optimieren.
@@iurlc Ich kenne diese aufgeblasenen compilierten C-Progamme für den Arduino. Darum hatte ich dann Assembler genommen, mit dem ich auch nie Ram-Platzprobleme bekam. Allerdings waren auch keine komplexeren Routinen, wie Diplaytreiber etc. dabei.
@@karlbesser1696 In diesem Fall hat der C-Compiler sehr gute Arbeit geleistet. Ein Transfer vom RAM ins Register und umgekehrt kostet jeweils laut Datenblatt 2 Taktzyklen. Also benötigt selbst ein Assemblerprogramm 2x2Taktzyklen, um die beiden Variablen vom RAM in 2 Register zu schieben und noch mal 2x2 Taktzyklen um sie wieder in umgekehrter Anordnung zurück ins RAM zu schreiben.
Es ist richtig, dass das Grundsystem erst mal 444 Bytes Flash-Speicher und 9 Bytes RAM braucht, damit das System mit der Entwicklungsumgebung kommunizieren kann und eine C-Umgebung (Stack, ect.) geschaffen wird. Aber der darauf aufbauende Code ist normalerwiese sehr kompakt.
@@iurlc Danke, dass du dir die Mühe machtest, meine Vermutungen zu verifizieren. Bisher hatte ich mir noch nicht die Mühe gemacht, die eigentlichen Routinen, wie sie der Compiler in den Flash schreibt, zu deassemblieren und auf Ballast zu prüfen. Gruß Karl.