Forum: Mikrocontroller und Digitale Elektronik Arduino Compiler/Linker command line switches für ein Projekt setzen


von Flunder (flunder)


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 ?

von Obelix X. (obelix)


Lesenswert?

Flunder schrieb:
> 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.

von Veit D. (devil-elec)


Lesenswert?

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.

: Bearbeitet durch User
von Harald K. (kirnbichler)


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

von Arduino F. (Firma: Gast) (arduinof)


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

von Arduino F. (Firma: Gast) (arduinof)


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
}

: Bearbeitet durch User
von Flunder (flunder)


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.

von Rahul D. (rahul)


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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Flunder schrieb:
> ....

Was ein Gejammere....
Es sollte doch mit den gegebenen Informationen, kein Problem sein, eine 
eigene Hardwaredefinition/Boarddefinition in sketchbook/hardware 
anzulegen.

: Bearbeitet durch User
von Norbert (der_norbert)


Lesenswert?

Was spricht gegen ein makefile um die Kontrolle wieder zu erlangen?

von Monk (roehrmond)


Lesenswert?

Norbert schrieb:
> Was spricht gegen ein makefile um die Kontrolle wieder zu erlangen?

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

: Bearbeitet durch User
von Norbert (der_norbert)


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.

von Arduino F. (Firma: Gast) (arduinof)


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.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Anstatt Klopper wie printf kann man evtl. auch Konverter wie atof oder 
ftostr verwenden?

https://avrdudes.github.io/avr-libc/avr-libc-user-manual-2.2.0/group__avr__stdlib.html

von Arduino F. (Firma: Gast) (arduinof)


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.

: Bearbeitet durch User
von Rahul D. (rahul)


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.

von Harald K. (kirnbichler)


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.

von J. S. (jojos)


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.

von Monk (roehrmond)


Lesenswert?

Norbert schrieb:
> 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.

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Monk schrieb:
> Nein, schon lange nicht mehr.

Dafür hat man jetzt CMake.

von Monk (roehrmond)


Lesenswert?

Harald K. schrieb:
> Dafür hat man jetzt CMake.

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

von J. S. (jojos)


Lesenswert?

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.

von Harald K. (kirnbichler)


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

von J. S. (jojos)


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.

von Monk (roehrmond)


Lesenswert?

J. S. schrieb:
> @Monk Nur weil du keine Ahnung hast

Habe ich etwas falsches geschrieben?

> Cmake ist eine Metasprache ...

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.

von Peter D. (peda)


Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


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/

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Peter D. (peda)


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.

von Harald K. (kirnbichler)


Lesenswert?

Peter D. schrieb:
> Als Anfänger muß man erstmal lernen, nur dort zu optimieren, wo es auch
> einen signifikanten Effekt hat.

Eben. "Premature optimization" und so ...

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.