Debugging On The Arduino With An Improved Printf Command

It’s not a big thing – but I like my debugging statements to be robust!

On the Arduino, if you want to communicate back to the host computer (is ‘host’ the right term here?), then you need to use a statement like this:

// print single item, text, number, etc
Serial.print(/* something here */); 
// same as print() but adds n (newline) after
Serial.println(/* something here */); 

Fine – but these statements do one item at a time, which means typical debug statements end up like this:

Serial.print("item x=");
Serial.print(x);
Serial.print(", item y=");
Serial.println(y);

Instead of something like:

Serial.print("item x=%d, item y=%d",x,y);

So, I was looking out for a better print statement, one that could manage a whole string of parameters, just like I’m used to.

(Now I understand why the folks developing the code didn’t include it – the overhead of a regular print statement is pretty big, since it’s kind of a ‘kitchen sink’ tool. But for debugging it makes code much cleaner, and shorter – so I wanted one.)

Finally, after wondering on my own for far longer than I want to admit, I found one online (typical). It was on the Arduino forum, and was a simple buffer-style print:

#include <stdarg.h>
void p(char *fmt, ... ){
        char tmp[128]; // resulting string limited to 128 chars
        va_list args;
        va_start (args, fmt );
        vsnprintf(tmp, 128, fmt, args);
        va_end (args);
        Serial.print(tmp);
}

It’s almost ready to use – almost. One problem is that the buffer is not null terminated if it goes too long – a big no-no. Another is that the code assumes a Serial object – what if you’d rather use another serial object?

Based on those issues, here’s a modified version:

void SerialPrint(SoftwareSerial &output,char *format,...)
{
  char buff[128];
  va_list args;
  va_start (args,format);
  vsnprintf(buff,sizeof(buff),format,args);
  va_end (args);
  buff[sizeof(buff)/sizeof(buff[0])-1]='\0';
  output.print(buff);
}

You use it like this:

SerialPrint(Serial,"This string has %d items in it - GREAT%c",2,'!');

To get

This string has 2 items in it - GREAT!

The format is just like a typical print statement, but to the Serial object you choose. And if you worry about the buffer size, feel free to change its size from 128. Also, there’s no more need for a newline version, as you can just use the entry n in your string to force a newline.

Or, if you’re determined to use the current serial object, the same code can be a bit lighter:

void SerialPrint2(char *format,...)
{
  char buff[128];
  va_list args;
  va_start (args,format);
  vsnprintf(buff,sizeof(buff),format,args);
  va_end (args);
  buff[sizeof(buff)/sizeof(buff[0])-1]='\0';
  Serial.print(buff);
}

Either way, your debug statements (and any other serial printing you may want to do) is now straightforward – and on one line if you wish!

Note: for an update to this article, visit this page.

One thought on “Debugging On The Arduino With An Improved Printf Command