Arduino Compiler/Linker command line switches für ein Projekt setzen

#7716784
Lesenswert?

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.

Gibt's da auch noch eine Möglichkeit ?

#7717231
Lesenswert?

Obelix X. schrieb:

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 ...

(Firma: Gast) #7717292
Lesenswert?

Harald K. schrieb:

mit anderen Compilern kann man das auch auf kleinen AVRs verwenden.

Geht auch mit dem von Arduino mitgeliefertem Compiler

Siehe: Veit D. schrieb im Beitrag #7717088:

man kann bei Arduino eine platform.local.txt anlegen und Compiler Flags wie bspw. "-Wl,-u,vfprintf -lprintf_flt -lm" setzen.

Durch wegnehmen des # die gewünschte Variante aktivieren.

1
# erlaubt float in sprintf und seinen Brüdern.
2
#compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt
3
# -lm
4

5
# erlaubt float in sscanf und seinen Brüdern.
6
#compiler.c.elf.extra_flags=-Wl,-u,vfscanf -lscanf_flt -lm
7

8
# erlaubt float in sscanf,sprintf und ihren   Brüdern.
9
#compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt  -Wl,-u,vfscanf -lscanf_flt
(Firma: Gast) #7717306
Lesenswert?

Flunder schrieb:

Fließkommazahlen in printf()

Ach ja.. Für printf() brauchts auch noch etwas Vorbereitung . z.B. so, oder so ähnlich:

1
int writeChar(char c, FILE *)
2
{
3
  return !Serial.write(c);
4
}
5

6
int readChar(FILE *)
7
{
8
   int c;
9
   while(-1 == (c=Serial.read()));
10
   return c;
11
}
12

13

14

15
FILE stdiostream;
16

17

18
void setup() 
19
{
20
  fdev_setup_stream(&stdiostream, writeChar, readChar, _FDEV_SETUP_RW);
21
  stdin = stdout = stderr = &stdiostream;
22

23
  
24
  Serial.begin(9600);
25

26
  signed value = 72;
27
  printf("testHex 0x%02X\r\n",value);
28
  printf("testDezimal %02d\r\n",value);
29
}
30

31
void loop()
32
{
33
}
#7718200
Lesenswert?

Veit D. schrieb:

Hallo,

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.

#7718206
Lesenswert?

Flunder schrieb:

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...).

#7718259
Lesenswert?

Monk schrieb:

Hast du einen Plan, wie Makefiles in der Arduino IDE bzw. mit dem Arduino Framework nutzt? Ich glaube, das ist dort nicht vorgesehen.

Könnte mir vorstellen, das man einfach ein Terminal öffnet und dann make eintippt. ;-)

Aber mal ernsthaft, Arduino nutzt doch soweit ich mich erinnern kann (und das ist ne sehr lange Zeit her) die GCC suite.

  • Kompiliert einen Sack voll.
  • Erstellt ein Archiv.
  • Kompiliert weiter und linkt den Plunder zusammen.

Na und ein einfaches Makefile erstellen gehört doch sozusagen zu den Grundfertigkeiten.

(Firma: Gast) #7718263
Lesenswert?

Norbert schrieb:

Arduino nutzt doch

Keine Makefiles!

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.

Norbert schrieb:

Na und ein einfaches Makefile erstellen gehört doch sozusagen zu den Grundfertigkeiten.

Der Builder macht so einige Dinge, die ein Makefile bzw. make nicht so ohne weiteres kann.

(Firma: Gast) #7718273
Lesenswert?

Johann L. schrieb:

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.

#7718279
Lesenswert?

Arduino F. schrieb:

Eine Notwendigkeit für printf und seine Brüder gibt es in der Arduinowelt eigentlich nicht.

Naja, die Formatierung mit printf ist schon komfortabler: Man kann alles in einen Formatstring packen und spart sich "zeilenweise" prints.

Arduino F. schrieb:

Bei scanf ist das etwas anders, das vermisse ich schon eher mal.

Noch nie benutzt.

#7718304
Lesenswert?

Johann L. schrieb:

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.

#7718307
Lesenswert?

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.

#7718691
Lesenswert?

Monk schrieb:

CMake ist nicht Bestandteil der GNU Compiler Collection, das muss man ggf. separat installieren.

Das hab' ich auch nicht behauptet.

J. S. schrieb:

Und Cmake ersetzt ein make nicht, das wird trotzdem gebraucht.

Genau, noch eine Schicht auf dem Schichtkuchen mehr.

CMake erzeugt nur Makefiles in einem zum gewünschten make hoffentlich passenden Format - das kennt sogar Microsofts nmake.

J. S. schrieb:

Oder es wird ninja benutzt, muss aber auch extra installiert werden.

Wieder 'ne andere Schicht.

Auch deshalb ist Pio angenehmer,

Eigentlich auch nicht, nur weil es wohl mit dem von Dir verwendeten Toolkit mitkommt ...

#7718698
Lesenswert?

@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.

Harald K. schrieb:

Eigentlich auch nicht, nur weil es wohl mit dem von Dir verwendeten Toolkit mitkommt ...

auch falsch, die Toolkits werden installiert wenn die Platform es braucht.

(Firma: Gast) #7718978
Lesenswert?

Ich habe den Eindruck, dass hier nicht alle wissen, was der Arduino Builder so alles tut. Dem kann abgeholfen werden: https://arduino.github.io/arduino-cli/0.21/sketch-build-process/

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.

Wie man eine solche erstellt findet sich hier: https://arduino.github.io/arduino-cli/0.21/platform-specification/

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

Flunder schrieb:

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
float u; // V
2
u = adc*5.0/1024.0;

könnte man auch mit einem Integer in mV rechnen und schreiben

1
uint32_t u; // 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.

#7719100
Lesenswert?

Lothar M. schrieb:

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.

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