Ich habe ein Programm, in dem ich mit vsnprintf() gerne Fließkommazahlen ausgeben möchte. Bei den kleinen AVRs deaktiviert die Arduino IDE aber leider die Unterstützung dafür.
Ich habe bisher nur Möglichkeiten gefunden, den Code umzuwursteln und eine Arduino Spezialfunktion zur Wandlung eines Fließkommawertes in eine Zeichenkette zu nutzen oder um die Unterstützung für Fließkommazahlen in printf() u.ä. auf meinem Rechner und meinem Login für alle AVR Cores zu aktivieren.
Ersteres ist etwas aufwändig. Zweiteres ist schlecht, weil auch ein Kollege mal das Programm übersetzen können soll, aber ich mich nicht um dessen Projekte kümmern mag, die plötzlich und unverhofft nicht mehr in den Speicher passen.
Bei den kleinen AVRs deaktiviert die Arduino IDE aber
leider die Unterstützung dafür.
Ich kenne mich mit den AVRs zwar nicht aus aber es wird wohl einen Grund haben, dass das so ist. Der Grund könnte Speichermangel sein weil sprintf ein riesen Batzen Code ist.
man kann bei Arduino eine platform.local.txt anlegen und Compiler Flags wie bspw. "-Wl,-u,vfprintf -lprintf_flt -lm" setzen. Die Ressourcenbelegung muss man sich dann anschauen.
Der Grund könnte Speichermangel sein weil
sprintf ein riesen Batzen Code ist.
So gigantisch ist es nun auch wieder nicht, mit anderen Compilern kann man das auch auf kleinen AVRs verwenden. Für manch einen liegt zwar viel Ehre darin, jede C-Libraryfunktion selbst neu zu schreiben (im festen Glauben, das viel besser zu können als diejenigen, die die Libraries für die Compiler zur Verfügung stellen), anderen aber liegt es mehr daran, ein Programm von überschaubarer Quelltextgröße zu erhalten, das einfach das tut, was es macht. Auch wenn sprintf 2 kiB Code umfasst - bekommt man Geld zurück, wenn man das Flash des Controllers ungenutzt lässt?
Wir sind ja nicht alle professionelle Produktdesigner, die Programme für zigmillionenfach gefertigte Geräte schreiben, bei denen es sich lohnen könnte, drei Cent am Controller einzusparen ...
man kann bei Arduino eine platform.local.txt anlegen und Compiler Flags
wie bspw. "-Wl,-u,vfprintf -lprintf_flt -lm" setzen. Die
Ressourcenbelegung muss man sich dann anschauen.
Diese Lösung hatte ich schon gesehen, aber die Datei muss unter den lokalen Anwendungsdaten eines Benutzers angelegt werden. D.h. jeder muss diese Datei auf jedem Rechner anlegen, um meinen Quellcode übersetzen zu können.
Andererseits ändert derjenige, der das tut, damit die Einstellungen mit denen er jedes Arduino Projekt für AVR Mikrocontroller übersetzt.
Beide Punkte sind extrem hinderlich, wenn man etwas an Kollegen weiter geben will, die das abändern und /schnell mal/ compilieren können sollen.
Diese Lösung hatte ich schon gesehen, aber die Datei muss unter den
lokalen Anwendungsdaten eines Benutzers angelegt werden. D.h. jeder
muss diese Datei auf jedem Rechner anlegen, um meinen Quellcode
übersetzen zu können.
Andererseits ändert derjenige, der das tut, damit die Einstellungen mit
denen er jedes Arduino Projekt für AVR Mikrocontroller übersetzt.
Beide Punkte sind extrem hinderlich, wenn man etwas an Kollegen weiter
geben will, die das abändern und schnell mal compilieren können
sollen.
Dann solltet Ihr auf eine andere IDE umsteigen, bei der nicht alles global geändert wird. Die Arduino-IDE ist ja ganz nett, hat aber so ihre Macken (Der Wechsel zwischen zwei Controllerfamile gilt für jedes Projekt...).
Was ein Gejammere....
Es sollte doch mit den gegebenen Informationen, kein Problem sein, eine eigene Hardwaredefinition/Boarddefinition in sketchbook/hardware anzulegen.
Aber dafür einen Builder
Den Arduino Builder, der die Boarddefinitionen lesen kann.
Wie make, lässt sich der auch einzeln aufrufen, ohne IDE.
Heißt dann Arduino CLI, oder so ähnlich.
Macht z.B. richtig Sinn, wenn man nach einer Lib/System Änderung, alle abhängigen Projekte im Stapel neu übersetzen möchte. Für alle verwendeten µC/Boards.
Anstatt Klopper wie printf kann man evtl. auch Konverter wie atof oder
ftostr verwenden?
Serial(erbt von Print) und auch String können float verarbeiten.
Eine Notwendigkeit für printf und seine Brüder gibt es in der Arduinowelt eigentlich nicht.
Ich selber verwende printf nur, weil/wenn ich uralt(?) C oder C++ Programme mit der Arduino IDE übersetze.
Bei scanf ist das etwas anders, das vermisse ich schon eher mal.
Anstatt Klopper wie printf kann man evtl. auch Konverter wie atof oder
ftostr verwenden?
Wenn es einem völlig wurscht ist, wie die Ausgabe formatiert wird, ja. Sobald man aber ein bestimmtes definiertes Format braucht (führende Leerzeichen, rechtsbündige Ausgabe, definierte Anzahl Nachkommastellen etc.) muss man den eigenen Code mit Kram aufblähen, den man nur braucht, weil man den gefühlten "Klopper" printf einsparen will.
Die Zeit, aus der die Weisheit stammt, printf um wirklich /jeden/ Preis zu vermeiden, ist eigentlich schon lange vorbei, jedenfalls, wenn man mit µCs arbeitet, die mehr als 2 kiB Flash-ROM haben.
printf braucht aber auch einiges an RAM der vom Stack genutzt wird, das dürfte eher ein Grund sein warum das bei den kleinen AVR deaktiviert ist.
Eigene Compilerschalter kann man einfach bei PlatformIO nutzen, die packt man da in die platformio.ini und gehört damit zum Projekt.
Auch die Abhängigkeiten mit den nötigen Versionen kann man da eintragen, das ist ja ebenfalls ein Problem bei der original Arduino IDE.
Na und ein einfaches Makefile erstellen gehört doch sozusagen zu den
Grundfertigkeiten.
Nein, schon lange nicht mehr.
Make ist nicht Bestandteil der GNU Compiler Collection, das muss man ggf. separat installieren. Wie viele andere IDE auch arbeitet auch die Arduino IDE ohne Make. Sie enthält ihren eigenen Build-Prozessor.
CMake ist nicht Bestandteil der GNU Compiler Collection, das muss man
ggf. separat installieren. Wie viele andere IDE auch arbeitet auch die
Arduino IDE ohne CMake. Sie enthält ihren eigenen Build-Prozessor
Und Cmake ersetzt ein make nicht, das wird trotzdem gebraucht. Oder es wird ninja benutzt, muss aber auch extra installiert werden.
Auch deshalb ist Pio angenehmer, aus der kleinen platformio.ini ist ersichtlich was zum bauen nötig ist und wird automatisch installiert.
@Monk Nur weil du keine Ahnung hast must nicht die Leute mit deinem 'Schichtkuchen'verunsischern, das ist einfach Bullshit.
Cmake ist eine Metasprache die eben etwas unabhängig von OS und Buildsystemen macht. Ja, es generiert makefiles für make oder ninja (ist dem make sehr ähnlich), aber vermeidet das bei jedem Build Abhängigkeiten geprüft werden müssen. Das macht bei großen Projekten einen gewaltigen Unterschied. Auch das Intellisense wird dabei unterstützt durch Export einer Datei compile_commands.json die dem Intellisense bei den tatsächlich verwendeten Includes und defines hilft. Das hat alles nichts mit irgendwelchen zusätzlichen Schichten zu tun.
Das ändert nichts daran, dass kein Make-Programm Bestandteil der gcc ist, und mit Arduino nichts zu tun hat und auch nicht mehr zu den Grundfertigkeiten gehört.
Make erzeugt nur die Kommandozeile für den Compiler, z.B. GCC.
Man kann daher sämtliche Aufrufe genauso gut in eine Batchdatei schreiben.
Eine Batchdatei kann sogar Errorlevel auswerten und so den Compilevorgang abbrechen. Oder Umgebungsvariablen und externe Tools einbinden.
Damit der TO sein Problem einfach lösen kann, wäre das erstellen einer eigenen Boarddefinition eine praktikable Möglichkeit, damit der Arduino Builder auch seinen Job erledigen kann.
ich mich nicht um dessen Projekte kümmern mag, die plötzlich und
unverhofft nicht mehr in den Speicher passen.
Gibt's da auch noch eine Möglichkeit ?
Auch wenn die Antwort erstmal OT erscheint ist sie grundsätzlich ganz einfach: keine Fließkommazahlen nehmen auf einem Rechner, der eh keine FPU hat.
Ich bin mir sicher, dass in deutlich über 99% der Fälle, wo ein üblicher Arduinist einen 32-Bit Float nimmt, ein 32-bit Integer die Arbeit mindestens gleich gut erledigen könnte. Wenn schon beim Berechnen einer Spannung aus einem ADC-Wert der Faktor 1024.0 (oder schlimmer noch 1023.0) drin seht, dann ist das sicher der Fall. Denn statt mit Float in Volt
1
floatu;// V
2
u=adc*5.0/1024.0;
könnte man auch mit einem Integer in mV rechnen und schreiben
1
uint32_tu;// mV
2
u=adc*5000/1024;
Und wenn man keine Float-Zahlen im Programm hat, muss man logischerweise keine Floatzahlen ausgeben. Problem gelöst.
Jetzt dürft ihr das Problem aber weiterhin auf die andere Art lösen. Viel Erfolg dabei.
Ich bin mir sicher, dass in deutlich über 99% der Fälle, wo ein üblicher
Arduinist einen 32-Bit Float nimmt, ein 32-bit Integer die Arbeit
mindestens gleich gut erledigen könnte.
Lustiger Weise ist eine Division in float auf dem AVR sogar schneller, als mit int32. Float rechnet nämlich nur mit 23 Bit Mantisse.
Flash kostet auch nur der erstmalige Aufruf einer Funktion, jeder weitere Aufruf kostet einfach nur den Call.
Besonders bei Regelungen bin ich es gründlich Leid, wenn sie wegen Rundungsfehlern oder Überläufen gegen den Baum laufen. Solange zeitlich nichts dagegen spricht, nehme ich für Berechnungen aller Art grundsätzlich nur noch float. Selbst ein 8-Pinner (ATtiny85) kann float rechnen.
Als Anfänger muß man erstmal lernen, nur dort zu optimieren, wo es auch einen signifikanten Effekt hat.