Serial.print Program Lag

Using Serial.print for debugging significantly slows down a sketch. Once I have a sketch working as I want (for now), I may use find and replace and change Serial.print to //Serial.print and this speeds everything up.

Do i need to do this or simply comment out the Serial.begin?

If I do just comment out the Serial.begin, will the Serial.print commands still use processing power?

Should I comment out both Serial.begin and Serial.print commands for optimal performance?

Serial print blocks if the buffer fills up.

If you use 9600 baud then the serial monitor can send about 960 characters a second, any more than that (or even if you get close) then it will block.

Ways to avoid this:

  • Set the baud rate to 115200
  • Don't send too much to the buffer

Without seeing your complete code it is difficult to offer better advice.

Consider using the #define DEBUG macro. Comment out one line at the top of the code and all statements between

#ifdef DEBUG
  ... code to be ignored ...
#endif

do not compile

Also see Post #10 here

I've now run the experiment and got part of my answer.

I am trying to see how long a single 3.2v lifepo battery will last on a Lolin 32 lite. To save battery, i put the esp32 into deep sleep every 12 seconds after writing sensor values to an array. After 120 seconds the sensor values are averaged and saved to SPIFFS, and it goes to sleep again.

By commenting out the Serial.begin and Serial.print lines, it saves 30% of the time it is awake.

I assume that this will extend battery life.

Any more than 63 characters within any 65mS period of time can cause blocking.

1 Like

Do you just switch this on or off by editing #ifndef to:

DEBUG

Or

NO_DEBUG

I found this which appears a bit clearer, and simpler to understand. Sometimes too much choice/information can be too confusing.

Will this work for arduino?

// Debugging switches and macros
#define DEBUG 0 // Switch debug output on and off by 1 or 0

#if DEBUG
#define PRINTS(s)   { Serial.print(F(s)); }
#define PRINT(s,v)  { Serial.print(F(s)); Serial.print(v); }
#define PRINTX(s,v) { Serial.print(F(s)); Serial.print(F("0x")); Serial.print(v, HEX); }
#else
#define PRINTS(s)
#define PRINT(s,v)
#define PRINTX(s,v)
#endif

Can you tell me what I am missing? It doesn't make any difference if the #define NO_DEBUG is comented out or not, the Serial.prints always execute.

I am obviously missing an important point.

//Libraries
#include <ESP32Time.h>
#include <WiFi.h>
#include <time.h>



//#define NO_DEBUG

#ifndef NO_DEBUG
    #define P(x) Serial.print(F(x))
    #define PL(x) Serial.println(F(x))
    #define PF(...) Serial.printf(__VA_ARGS__)

#else
    #define P(x)
    #define PL(x)
    #define PF(...)
#endif

//Functions
void wifiTime();
void initWiFi();
unsigned long getTime();


// Variables
const char *ntpServer = "pool.ntp.org";
unsigned long epochTime;
bool BST=0;
int triggerClockupdate;
long timer,timer2;

//NTPtime NTPch("ch.pool.ntp.org");   // Choose server pool as required
char *ssid = "Utopia";            // Set you WiFi SSID
char *password = "GillyBob1965";  // Set you WiFi password
bool resetClock = 1;
ESP32Time rtc;



////////////////////////////////////////////////////////
void setup() 
{
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  clockSetup();
  triggerClockupdate=rtc.getHour();
}
///////////////////////////////////////////////////////
void loop() 
{

  if (resetClock) {

    clockSetup();
    resetClock = 0;
  }
  Serial.println(rtc.getTime("%A, %B %d %Y %H:%M:%S"));  // (String) returns time with specified format
  Serial.println(rtc.getTime());
  if (abs(triggerClockupdate-rtc.getHour())>=6)
  {
    resetClock = 1;
    triggerClockupdate=rtc.getHour();
  }
  delay(5000);
 
}
////////////////////////////////////////////////////////////
void clockSetup()
{
  
  initWiFi(); 
  long timer = millis();
 
  epochTime = getTime();

  rtc.setTime(epochTime);
  
  BSTUK();
  timer2=millis()-timer;

  Serial.print("Epoch Time: ");
  Serial.println(epochTime);

  Serial.print(timer2);
  Serial.println(" time taken to reset time in milliseconds");
  configTime(3600*BST, 0, ntpServer);// May need amending for BST
  WiFi.disconnect(true);
  if (WiFi.status() != WL_CONNECTED) 
  {
    Serial.println("WiFi disconnected");
  }
}
//////////////////////////////////////////////////////
// Initialize WiFi
void initWiFi() 
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) 
  {    
    digitalWrite(LED_BUILTIN, LOW);
    Serial.print('.');
    delay(250);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(250);
  }
  Serial.println(WiFi.localIP());
}


//////////////////////////////////////////////////////
// getTime() epochTime
unsigned long getTime() 
{
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) 
  {
    Serial.println("Failed to obtain time");
    return (0);
  }
  time(&now);
  return now;
}


/////////////////////////////////////////////////////////////////
void BSTUK()
{
  
  int year = rtc.getYear();
  rtc.setTime(0, 0, 0, 25, 3, year); 
  int dayOfWeek=int(rtc.getDayofWeek());
  int day=(25+7-dayOfWeek);
  rtc.setTime(0, 0, 0, day, 3, year);
  int springHour = rtc.getDayofYear()*24+1;

  rtc.setTime(0, 0, 0, 25, 10, year); 
  dayOfWeek=int(rtc.getDayofWeek());
  day=(25+7-dayOfWeek);
  rtc.setTime(0, 0, 0, day, 10, year);
  int autumnHour = rtc.getDayofYear()*24+2;

  rtc.setTime(epochTime);
  int nowHour = rtc.getDayofYear()*24+1;
  if (nowHour>springHour && nowHour<autumnHour) // Check for British Summer Time
  {
    BST=1;
  }
  else
  {
    BST=0;
  }

  return;
}

You have to replace all of your Serial.print(foo); debug statements with PRINTS(foo)' and etc.

I like

 static const DEBUG = 0;
#define debugPrint(...) do (if (DEBUG) Serial.print(__VA_ARGS__) while (0)
#define debugPrintln(...) do (if (DEBUG) Serial.println(__VA_ARGS__) while (0)

This way, if you make DEBUG a static const as above the compiler optimization will give you either a simple Serial.print, or nothing, but you also have the option of making DEBUG a variable that you can change at runtime.

Thanks for that, I'll give it a try.

logical: You have defined some makros but you are not using them.
You still print with Serial.print.
You should adopt your Serial.print to one of your makros.

by the way ... don't use so short makros ... everytime you would write PL in your code it will be replaced by the makro ... use something like debugPrint ... and only use that for your debug messages.

I think that the penny has dropped.

When you define the macros, you are basically telling IDE to replace what ever chatacters that you have defined with the ones that you specify. Is this correct?

So if I use #define PRINTS(s) { Serial.print(F(s)); } and #define PRINTS(s), I would need to find and replace my 'Serial.print' commands and replace them with 'PRINTS'?

I misunderstood, I thought that these macros were instructing IDE to ignore the Serial.print command.

basically yes, but see the examples with the variadic makros

VA_ARGS

then the and amount of parameters will be solved. For example to print in ,HEX or a float with 3 decimals ... all with ONE makro.

I'm often using this for debug

#define DEBUG 1    // SET TO 0 OUT TO REMOVE TRACES

#if DEBUG
#define D_SerialBegin(...) Serial.begin(__VA_ARGS__)
#define D_print(...)       Serial.print(__VA_ARGS__)
#define D_write(...)       Serial.write(__VA_ARGS__)
#define D_println(...)     Serial.println(__VA_ARGS__)
#define D_printf(...)      Serial.printf(__VA_ARGS__)
#else
#define D_SerialBegin(...)
#define D_print(...)
#define D_write(...)
#define D_println(...)
#define D_printf(...) 
#endif

instead of Serial.print() or Serial.write() you use D_print() and D_write()

Then all forms deal with variable arguments

That's great every one, I've got it working.

One day, I may know what I am doing.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.