HOWTO · Arduino

Arduino printf Funktion

Mit der Funktion sprintf() und der Funktion Serial.print() kann dieselbe Ausgabe wie printf() erzielt werden.

Auf dieser Seite

Die standardmäßige Arduino-Programmierumgebung stellt keinen portablen printf()-Aufruf bereit, der in den seriellen Monitor schreibt. Einige Board-Cores ergänzen eine eigene Methode Serial.printf(); prüfen Sie daher die Dokumentation Ihrer ausgewählten Platine. Für portable Sketches formatieren Sie den Text mit sprintf() in einem Zeichenpuffer und senden ihn mit Serial.print() oder Serial.println(). Wenn Sie keine Formatzeichenfolge benötigen, können mehrere serielle Aufrufe dieselbe Nachricht direkt zusammensetzen.

Stellt Arduino printf() bereit?

Es gibt keine printf()-Schnittstelle, die für alle Arduino-Platinen garantiert ist. Die C-Bibliotheksfunktion printf() schreibt normalerweise in einen Standardausgabestrom, den eine Mikrocontroller-Umgebung möglicherweise nicht mit einem seriellen Anschluss verbindet. Ein boardspezifischer Core kann Serial.printf() bereitstellen; ob die Methode verfügbar ist und welche Formatangaben sie unterstützt, hängt jedoch vom Zielsystem ab. Die folgenden Sketches verwenden setup() und loop() und geben Daten über Serial aus. Ein kleiner serieller Platzhalter auf dem Host-Rechner ermöglicht es, dieselben Beispiele ohne Arduino-Platine auszuführen. Auf einer Platine stellt der Arduino-Core Serial und den Lebenszyklus des Sketches bereit.

Text mit sprintf() formatieren und über die serielle Schnittstelle senden

Verwenden Sie sprintf(), wenn eine Nachricht Platzhalter oder Auffüllzeichen benötigt. Die Funktion schreibt den fertigen Text in ein Zeichenarray; anschließend sendet Serial.println() diesen Text samt Zeilenende. Dieser Sketch verwendet snprintf(), damit die Kapazität des Arrays an die Formatierungsfunktion übergeben werden kann, und prüft vor dem Senden, ob die vollständige Nachricht hineinpasst:

#include <cstdio>

#ifdef ARDUINO
#include <Arduino.h>
#else
class HostSerial {
 public:
  void begin(unsigned long) {}
  void println(const char* text) { std::puts(text); }
};
HostSerial Serial;
#endif

void setup() {
  Serial.begin(9600);
  char buffer[32];
  const int value = 42;
  const int length = std::snprintf(buffer, sizeof(buffer), "The answer is: %d", value);
  if (length >= 0 && static_cast<unsigned int>(length) < sizeof(buffer)) {
    Serial.println(buffer);
  }
}

void loop() {}

#ifndef ARDUINO
int main() {
  setup();
  return 0;
}
#endif
The answer is: 42

snprintf() gibt die Anzahl der Zeichen zurück, die geschrieben würden, ohne das abschließende Nullzeichen mitzuzählen. Ist diese Anzahl mindestens so groß wie die Array-Kapazität, sendet der Sketch keine unvollständige Nachricht. Prüfen Sie, ob die C-Bibliothek Ihrer ausgewählten Platine snprintf() wie erwartet bereitstellt; Verfügbarkeit und Verhalten formatierter Funktionen können je nach Platine und Core variieren.

Ausgabe mit Serial.print() zusammensetzen

Bei einfachen Bezeichnungen und Werten vermeiden direkte Aufrufe einen temporären Formatierungspuffer. Serial.print() setzt die Ausgabe in derselben Zeile fort; Serial.println() beendet die Zeile. Dieser Sketch setzt dieselbe Zeile mit seriellen Aufrufen zusammen:

#include <cstdio>

#ifdef ARDUINO
#include <Arduino.h>
#else
class HostSerial {
 public:
  void begin(unsigned long) {}
  void print(const char* text) { std::printf("%s", text); }
  void print(int value) { std::printf("%d", value); }
  void print(double value, int digits) { std::printf("%.*f", digits, value); }
  void println(const char* text) { std::printf("%s\n", text); }
};
HostSerial Serial;
#endif

void setup() {
  Serial.begin(9600);
  const int temperature = 25;
  const double humidity = 60.5;
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print(" C, Humidity: ");
  Serial.print(humidity, 1);
  Serial.println("%");
}

void loop() {}

#ifndef ARDUINO
int main() {
  setup();
  return 0;
}
#endif
Temperature: 25 C, Humidity: 60.5%

Der Platzhalter auf dem Host-Rechner bildet die hier verwendeten Aufrufe nach, sodass sich die Zeile des Sketches auch ohne Hardware anzeigen lässt; er ist kein Arduino-Core. Auf der Platine fordert Serial.print(humidity, 1) eine Stelle nach dem Dezimaltrennzeichen an. Welche Formatierung genau unterstützt wird, hängt von der Serial-Implementierung der Platine ab.

Gleitkommawerte und Puffergrenzen berücksichtigen

Die Formatierung von Gleitkommazahlen mit sprintf() verhält sich nicht bei allen Arduino-Cores gleich: Einige eingebettete C-Bibliotheken lassen die Gleitkommaumwandlung bei der formatierten Ein- und Ausgabe weg, um Programmspeicher zu sparen. Prüfen Sie den Ziel-Core, bevor Sie sich auf %f verlassen. Eine Alternative ist die direkte Form Serial.print(value, digits), sofern der Core die übliche Arduino-Implementierung von Print unterstützt.

Jede formatierte Ausgabe muss in das Zeichenarray passen, einschließlich des abschließenden \0. Verwenden Sie, sofern verfügbar, snprintf() mit der tatsächlichen Kapazität des Arrays und prüfen Sie den Rückgabewert, bevor Sie das Ergebnis verwenden. Ist der formatierte Text länger als das Array, vergrößern Sie den Puffer oder kürzen Sie die Nachricht. Ein größerer Puffer belegt mehr RAM, der auf vielen Platinen begrenzt ist.

Den passenden Ansatz wählen

Wählen Sie sprintf() oder snprintf(), wenn sich eine strukturierte Nachricht mit einer einzigen Formatzeichenfolge übersichtlicher erstellen lässt, und senden Sie das Ergebnis mit Serial.println(). Verwenden Sie Aufrufe von Serial.print(), wenn Sie nur einige Bezeichnungen und Werte verbinden möchten. Beide Ansätze senden Text über die serielle Schnittstelle; keiner garantiert auf jeder Platine dieselbe Formatierungsunterstützung. Prüfen Sie boardspezifische Methoden und das Verhalten bei Gleitkommazahlen anhand der Platine, für die Sie den Sketch kompilieren.