Frage zu Serial.Println

Hallo,

ganz kurze Frage , zum "Debuggen" habe ich den Arduino ja am USB angeschlossen und benutze Serial.Println um mir etwas auszugeben.
Natürlich mache ich nicht jedesmal die Abfrage If Serial.available.

Wenn ich fertig bin soll der Arduino nur noch am Netzwerk angeschlossen sein.

Muss ich da nun die ganzen Serial.Println löschen oder auskommentieren oder kann ich die ohne Probleme drin lassen ?

Matthias

mroschk:
kann ich die ohne Probleme drin lassen ?

ja

Serial.available gib zurück wieviele Byte Daten im Eingangsbuffer der seriellen Schnittstelle vorhanden sind und noch auszulesen sind.

Das hat nichts mit Serial.print zu Tun, der gibt Daten in den Ausgangsbuffer.

Jedes Versenden von Daten auf der Seriellen Schnittstelle verbraucht Zeit in der Programmausführung.

Am einfachsten ist es die seriellen Ausgaben durch bedingte Kompilierung im endgültigen Coder herauszuhalten:

#define serialon 

...
loop()
{
...
#ifdef serialon
{
  Serial.print("...");
} 
#endif
...}

wenn Du "#define serialon" auskommentierst werden alle #ifdef nicht mitkompiliert.

Grüße UWe

Oder noch komfortabler:

#define ENABLE_DEBUG    //diese Zeile auskommentieren

#ifdef ENABLE_DEBUG
  #define debugBegin(...)  Serial.begin(__VA_ARGS__)
  #define debugPrint(...)   Serial.print(__VA_ARGS__)
  #define debugPrintln(...)   Serial.println(__VA_ARGS__)
#else
  #define debugBegin(...)
  #define debugPrint(...)
  #define debugPrintln(...)
#endif

void setup()
{
  debugBegin(115200);

  debugPrint("Test"); debugPrintln();
  debugPrintln(10.5459, 2);
  debugPrintln(1234);
}

void loop() 
{ 
}

Dann muss man nicht bei jeder einzelnen Ausgabe extra Anweisungen hinschreiben. Der Präprozessor ersetzt den Text dann einfach durch "nichts" und es wird nicht ausgeführt

Serenifly:
Oder noch komfortabler:

#define ENABLE_DEBUG    //diese Zeile auskommentieren

#ifdef ENABLE_DEBUG
 #define debugBegin(...)  Serial.begin(VA_ARGS)
 #define debugPrint(...)   Serial.print(VA_ARGS)
 #define debugPrintln(...)   Serial.println(VA_ARGS)
#else
 #define debugBegin(...)
 #define debugPrint(...)
 #define debugPrintln(...)
#endif

void setup()
{
 debugBegin(115200);

debugPrint("Test"); debugPrintln();
 debugPrintln(10.5459, 2);
 debugPrintln(1234);
}

void loop()
{
}





Dann muss man nicht bei jeder einzelnen Ausgabe extra Anweisungen hinschreiben. Der Präprozessor ersetzt den Text dann einfach durch "nichts" und es wird nicht ausgeführt

KARMA++ daumen hoch

Das lässt sich auch sehr komfortabel mit sprintf kombinieren:

#ifdef debug
    #warning "Debug-printing is active"
    #define DB_PRINT( x, ... ) {char dbgBuf[80]; sprintf_P( dbgBuf, PSTR( x ), ##__VA_ARGS__ ) ; Serial.println( dbgBuf ); }
#else
    #define DB_PRINT( x, ... ) ;
#endif

Alle strings landen automatisch im flash und man hat den kompletten Komfort des printf.

Aufrufbeispiel:

   DB_PRINT("Servoattach: pwmNbr=%d, servoIx=%d, Pin=%d", _servoData.pwmNbr, _servoData.servoIx, pinArg );
#define DEBUG_STREAM  Serial 


#ifdef DEBUG_STREAM
  #define debugBegin(...)    DEBUG_STREAM.begin(__VA_ARGS__)
// und so weiter

MicroBahner:
Das lässt sich auch sehr komfortabel mit sprintf kombinieren:

Gute Idee, aber wäre snprintf_P nicht sicherer?

Gruß Tommy

Serenifly:
Oder noch komfortabler:

#define ENABLE_DEBUG    //diese Zeile auskommentieren

#ifdef ENABLE_DEBUG
 #define debugBegin(...)  Serial.begin(VA_ARGS)
 #define debugPrint(...)   Serial.print(VA_ARGS)
 #define debugPrintln(...)   Serial.println(VA_ARGS)
#else
 #define debugBegin(...)
 #define debugPrint(...)
 #define debugPrintln(...)
#endif

void setup()
{
 debugBegin(115200);

debugPrint("Test"); debugPrintln();
 debugPrintln(10.5459, 2);
 debugPrintln(1234);
}

void loop()
{
}





Dann muss man nicht bei jeder einzelnen Ausgabe extra Anweisungen hinschreiben. Der Präprozessor ersetzt den Text dann einfach durch "nichts" und es wird nicht ausgeführt

Hallo,
danke euch für die vielen Antworten.
Das werd ich heute abend mal testen.
Ich hab noch nicht so viel Ahnung von der Arduino Sprache :slight_smile: , kann ich den obigen Code direkt so nehmen oder muss da noch was geändert werden ... ich meine z.B. das hier: debugBegin(...) bleibt das so stehen oder müssen die 3 Punkte ersetzt werden?
Sorry für die blöde Frage, aber jeder hat mal angefangen :slight_smile:
Ich kanns erst heute Abend testen...blöde Arbeit :slight_smile:

Matthias

ich meine z.B. das hier: debugBegin(...) bleibt das so stehen oder müssen die 3 Punkte ersetzt werden?

Die drei Punkte werden vom Präprozessor ersetzt/verarbeitet.
Das sind so genannte "Variadic Macros"

Ich hab noch nicht so viel Ahnung von der Arduino Sprache :slight_smile:

Ich weiß ....

Die " Arduino Sprache " ist übrigens C++
Nur, falls du das "hab noch nicht so viel Ahnung" mal ändern möchtest.

Hallo,

defines sind doch C++ unwürdig. :wink:

enum class state : byte {RELEASE, DEBUG};  
const state debugging = state::DEBUG;       // Serielle aktivieren

void setup (void)
{  
  if (debugging == state::DEBUG)
  {
    Serial.begin(250000);
    Serial.println("\nStart");
  }

  if (debugging == state::DEBUG)
  {
    Serial.println("USART ist aktiv");
  }
}

void loop (void)
{
  
}

Dann muss man aber bei jeder Ausgabe eine extra Abfrage hinschreiben. Das macht viel Arbeit und der Code wird unleserlich, da viele Zeilen entstehen die eigentlich nichts tun.

Das ist ein Fall wo Makros auch in C++ ihre Berechtigung haben

bleibt das so stehen oder müssen die 3 Punkte ersetzt werden?

Die Punkte sorgen dafür dass du eine beliebige Anzahl von Argumenten übergeben kannst. Man muss also nicht Versionen mit einem oder zwei Parametern unterscheiden

Hallo,

du hast schon recht, es war auch nicht so ernst gemeint und doch schon ernst gemeint. :wink:
Man will ja in C++ möglichst weg von Makro Orgien, damit es sicherer wird.
Allerdings wird dabei der Code unleserlicher, genau wie du sagst. Merkt man schnell mit den C++ cast Operatoren.
Am Ende muss man für sich entscheiden wieviel C++ man wirklich schreibt. :slight_smile:
Ich muss aber auch zugeben, dass ich mich bei manchen neuen C++ Dingen auch frage, warum wird das immer komplizierter statt einfacher. Aber das ist ein anderes Thema.

Tommy56:
Gute Idee, aber wäre snprintf_P nicht sicherer?

Stimmt, wäre ja auch einfach, da der Puffer unmittelbar vorher im Makro definiert wird. Da kann man die Größe auch gleich bei snprintf_P mit angeben. Werde ich zukünftig so machen.

Doc_Arduino:
Man will ja in C++ möglichst weg von Makro Orgien, damit es sicherer wird.
Allerdings wird dabei der Code unleserlicher, genau wie du sagst.

Die Makro-Variante hat auch den Vorteil, dass ohne debug da gar kein Code generiert wird, und damit die Release-Version schlanker wird.
Ich nutze ähnliche Makros z.B. auch um in Interrupts Testpulse für den LA zu erzeugen. Da kann man ja keine Debug-Prints nutzen und es geht auch eher um Zeitmessungen. Da ist es schon gut, wenn da in der Release-Version der Testcode gar nicht vorhanden ist.

Auch in C++ hat der Präprozessor durchaus seine Berechtigung.

Hallo,

ich bin endlich dazu gekommen das zu testen und es funktioniert super.

Danke euch
Matthias

MicroBahner:
Die Makro-Variante hat auch den Vorteil, dass ohne debug da gar kein Code generiert wird, und damit die Release-Version schlanker wird.

Das kann ich entkräften. Nimm mein Bsp. Code und vergleiche mit RELEASE Einstellung. Danach nimmste const weg und vergleichst nochmal.

Doc_Arduino:
Das kann ich entkräften. Nimm mein Bsp. Code und vergleiche mit RELEASE Einstellung.

Klar, in so einem Mini-Code kann der Compiler das noch prima optimieren. Da brauche ich das aber eigentlich gar nicht.
Mach das mal bei einer Lib-Entwicklung, die aus vielen cpp-Dateien besteht ( Und wo Du das trotzdem zentral ein- bzw. ausschalten willst ). Mal abgesehen davon, dass deine Variante da schnell unübersichtlich wird. Mit den Makros bleibt es immer eine einzige Print-Zeile, die sich per '//' auch schnell mal lokal ausschalten lässt, während die anderen aktiv bleiben. Und auf den printf-Komfort möchte ich auch nicht verzichten.
Weiterer Vorteil: Wenn das Ganze für verschiedene Plattformen funktionieren soll, lässt sich das Makro zentral anpassen, die Print-Zeile im Code bleibt immer gleich.

Hallo,

das hat mit Mini Code gar nichts zu tun. Mir scheint du hast das noch nie probiert.
Ob ich nun zwei Striche tippe oder zwischen Debug/Release wechsel ist der Rede gar nicht wert.
Das der Rest im Code mehr Zeilen erfordert stimmt. Ist dafür astreines C++ und sauberes C++ erfordert generell mehr Tipperei.

Das Andere ist mir alles zu weit hergeholt. Ich weiß gar nicht was es mit einer Hochsprache bei einem Plattformwechsel für ein Problem geben soll - diesbezüglich. Eben weil es C++ Standard ist.

Am Ende ist es mir völlig egal ob jemand defines nimmt oder nicht. Ich hatte nur eine reine C++ Variante gezeigt. Mehr wollte ich auch nicht. Das war laut meiner Auffassung mit Serenifly schon alles klargestellt wurden.

Es gibt noch mehr reine C++ Lösungen für diese Problemlage, allerdings ist das "Arduino System" nicht sonderlich gut dafür vorbereitet.
Damit sind Defines schon ein recht effektiver Weg.

Diese Alternative hat vielleicht ein paar Features mehr, ist aber auch nicht wirklich schlank

#include <Streaming.h>

class DummyPrinter: public Print
{
  public:
  virtual size_t write(uint8_t) override
  {
    return 1;
  }
} noDebug;

// such dir einen aus.. kann auch ein File, Lcd, 
// oder irgendein anderer Stream sein
//Print &Debug {Serial};
//Print &Debug {Serial1};
Print &Debug {noDebug};
Print &DebugLevel1 {Serial};

void setup()
{
  Serial.begin(9600);

  Debug.print("Test");  Debug.println();
  Debug.println(10.5459, 2);
  Debug.println(1234);
  DebugLevel1 << __FILE__ << "  " << __DATE__ << endl;
}

void loop()
{
}