Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Say I have some variables that I want to print out to the terminal, what's the easiest way to print them in a string?

Currently I do something like this:

Serial.print("Var 1:");Serial.println(var1);
Serial.print(" Var 2:");Serial.println(var2);
Serial.print(" Var 3:");Serial.println(var3);

Is there a better way to do this?

share|improve this question
An idea, but I don't know if it would work, is some modification of this... Again, I don't know if this is supported on Arduino:… – apnorton Feb 13 '14 at 19:50
up vote 21 down vote accepted

ardprintf is a function that I hacked together which simulates printf over the serial connection. This function (given at the bottom) can be pasted in the beginning of the files where the function is needed. It should not create any conflicts.

It can be called similar to printf. See it in action in this example:

void setup()

void loop()
  int l=2;
  char *j = "test";
  long k = 123456789;
  char s = 'g';
  float f = 2.3;

  ardprintf("test %d %l %c %s %f", l, k, s, j, f);



The output as expected is:

test 2 123456789 g test 2.30

The function prototype is:

int ardprintf(char *, ...);

It returns the number of arguments detected in the function call.

This is the function definition:

#define ARDBUFFER 16
#include <stdarg.h>
#include <Arduino.h>

int ardprintf(char *str, ...)
  int i, count=0, j=0, flag=0;
  char temp[ARDBUFFER+1];
  for(i=0; str[i]!='\0';i++)  if(str[i]=='%')  count++;

  va_list argv;
  va_start(argv, count);
  for(i=0,j=0; str[i]!='\0';i++)
      temp[j] = '\0';
      temp[0] = '\0';

        case 'd': Serial.print(va_arg(argv, int));
        case 'l': Serial.print(va_arg(argv, long));
        case 'f': Serial.print(va_arg(argv, double));
        case 'c': Serial.print((char)va_arg(argv, int));
        case 's': Serial.print(va_arg(argv, char *));
        default:  ;
      temp[j] = str[i];
      j = (j+1)%ARDBUFFER;
        temp[ARDBUFFER] = '\0';
  return count + 1;

**To print the % character, use %%.*

Now, available on Github gists.

share|improve this answer
Nice idea, although I felt it could be more minimalist, so I rewrote this version to one without buffering. Anyone interested can check out the gist: – eleotlecram Sep 29 '14 at 23:32

I wouldn't normally put two answers to a question, but I only just found this today, where you can use printf without any buffer.

// Function that printf and related will use to print
int serial_putchar(char c, FILE* f) {
    if (c == '\n') serial_putchar('\r', f);
    return Serial.write(c) == 1? 0 : 1;

FILE serial_stdout;

void setup(){

    // Set up stdout
    fdev_setup_stream(&serial_stdout, serial_putchar, NULL, _FDEV_SETUP_WRITE);
    stdout = &serial_stdout;

    printf("My favorite number is %6d!\n", 12);

void loop() {
  static long counter = 0;
  if (millis()%300==0){
    printf("millis(): %ld\tcounter: %ld (%02X)\n", millis(), counter, counter++);

This still has the floating point limitation.

edit: I thought I would do a little testing on this, and it works quite well. I added a better test to the loop with formatted output.

share|improve this answer
Oh man, that's cool. printf is a whole lot safer than sprintf. It gives you format strings for free, which is great. Cool trick. Thanks. (Voted) – Duncan C Sep 30 '14 at 2:28
One question: In your serial_putchar function, why not make the return statement return !Serial.write(c);? Isn't that cleaner than a trinary operator for inverting the sense of a boolean return value? – Duncan C Sep 30 '14 at 2:31
That's a good point and I like it. The code wasn't mine and I pasted it as I found it. – Madivad Sep 30 '14 at 19:24
Thanks for the serial_putchar function. It works a treat. :-) Can you fix the floating point limitation? – Greenonline Feb 22 '15 at 6:54

This is probably not better, just different. You can use the String object for output. These objects allow concatenation and support automatic typecasting.

String label = "Var";
const byte nValues = 3;
int var[nValues] = {36, 72, 49};

for (int i = 0; i < nValues; i++) {
    String stuff = label + i + ": ";
    Serial.println(stuff + var[i]);
share|improve this answer
Obviously it's important to be careful of memory limits. Lots of concatenations and other string operations in one place can use a surprising amount of space. – Peter R. Bloomfield Feb 13 '14 at 22:24
@PeterR.Bloomfield Absolutely true! That's the reason why I mentioned that this variant isn't better ;) – Klaus Warzecha Feb 14 '14 at 6:05

I usually used Tabs to make things line up better in the Serial. Having things line up like I do allow the arduino to fire as fast as possible while being able to notice certain changes in the variables.

Try something like this:

Serial.println("Var 1:\tVar 2tVar 3:");

Or something like this:

Serial.print("Var 1:");Serial.println(var1);
Serial.print("\tVar 2:");Serial.println(var2);
Serial.print("\tVar 3:");Serial.println(var3);
share|improve this answer
Honestly, I do the same ("\t" and "\n") and normally avoid the code-bloating String object bells and whistles. – Klaus Warzecha Feb 14 '14 at 7:33
@KlausWarzecha, I rarely give the variable name as they're in nice columns. Also make it easier to see random print outs that don't match this syntax – Steven10172 Feb 14 '14 at 7:45

I usually (painfully) stick with multiple lines of Serial.print but when it becomes convoluted I go back to sprintf. It's annoying in that you have to have an available buffer for it.

Usage is as simple (??) as:

char buffer[35]; // you have to be aware of how long your data can be
                 // not forgetting unprintable and null term chars

A word of warning though, it doesn't (by default) support floating types.

share|improve this answer
sprintf is a horrible abomination. Not type safe, easy to overrun your buffers, etc, etc. It's a tool from the 1960s. That said, I use it too, but it is not for the faint of heart.... – Duncan C Sep 30 '14 at 2:27

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.