Maker.io main logo

How To Streamline Your Arduino Code: Use sprintf to Declutter Serial Calls

2023-07-05 | By Maker.io Staff

Arduino

A previous article outlined why we should avoid adding debug outputs in our production code and ‎how we can achieve that goal with minimal program adjustments. However, programs ‎sometimes need to write data to the serial console — for example, when a program is ‎communicating with other microcontrollers. In these specific cases, the output statements may ‎take up many lines of code in the program. This article outlines how to use the string print ‎formatted (sprintf) function to prevent cluttering the code with many individual print calls when ‎outputting data on an Arduino’s serial port.

How To Streamline Your Arduino Code Use sprintf to Declutter Serial Calls

The Problems of Using Standard Serial Output Calls

Before discussing why using sprintf makes sense, the following example outlines the problems ‎of making outputs using the standard serial print functions. Suppose the program should transmit ‎the value of four variables separated by semicolons. The loop function could look like this:

Copy Code
int day = 11;
int month = 8;
float temperature = 78.25;
float brightness = 12.6;

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

void loop() {

  // Update variable values

  Serial.print(day);
  Serial.print("; ");
  Serial.print(month);
  Serial.print("; ");
  Serial.print(temperature);
  Serial.print("; ");
  Serial.println(brightness);

  // Some other tasks going on...

  delay(2500);
}

As this simple example shows, even writing the value of four variables in such a manner already ‎requires seven lines of code, which, in the long run, can lead to overly complex, long, and ‎unreadable programs.

Using sprintf to Reduce the Required Number of Lines

However, what if there was a method to condense the seven lines of code from above into three ‎lines? Doing so would make the resulting program much shorter and easier to both read and ‎understand. You can utilize sprintf, a C++ standard function that lets you specify a formatted ‎string containing multiple blanks to fill in, to accomplish this goal:

Copy Code
int day = 11;
int month = 8;
float temperature = 78.25;
float brightness = 12.6;

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

void loop() {

  // Update variable values

  char buff[21];
  sprintf(buff, "%i; %i; %f; %f", day, month, temperature, brightness);
  Serial.println(buff);

  // Some other tasks going on...

  delay(2500);
}

While the second example may initially look more complicated, it only takes up three lines of ‎code that can be broken down into the following three parts. The first line defines a buffer that ‎must be large enough to store the resulting string. In this example, the array must be able to hold ‎at most 21 characters. The first two numbers will always contain at most two digits, the ‎semicolon and space separators take up six additional spots, and the temperature and brightness ‎both require five extra slots. Finally, the string termination character, which is automatically ‎appended, needs another free place in the array. The buffer may always be larger than ‎necessary, but it shouldn’t be massively oversized, as doing so takes up unnecessary memory ‎space.

The sprintf call itself can be broken down into the following three parts. First is the target buffer, ‎created just one line above. Then comes the formatted string itself. This string contains ‎placeholders denoted by the percentage sign and a single character describing the type of value ‎that can be filled in. Think of it as a form containing pre-defined text and blanks that you can ‎complete. The method requires programmers to pass the variables to fill in the blanks defined in ‎the formatted string. Note that the variables must occur in the same order as they should be ‎inserted into the blanks in the final text:

How To Streamline Your Arduino Code Use sprintf to Declutter Serial Calls The formatted string can mix regular characters and blanks, defined using the so-called format ‎and character specifiers. The programmer needs to supply an appropriate number of variables ‎to fill in all the blanks in the string.

The sprintf method replaces the blanks with the variable values and stores the result in the buffer. ‎The last line of this example is a regular serial output call. However, note that only a single call is ‎required this time, and the program passes in the pre-assembled array.

Understanding sprintf’s Character Specifiers

But what exactly are these ominous character specifiers used in the formatted string? These ‎specifiers become easy to understand once you know what they mean. In order to fill in the ‎blanks, sprintf needs to know what type of data it should expect for each blank. For example, ‎programmers could tell the method that it should fill in a specific blank with a number. Character ‎specifiers let programmers define the type of data that will be present in the finished string so ‎that sprintf can choose the correct output representation when building the string. Note that ‎supplying the wrong character specifier will usually not lead to errors. However, it will often result ‎in incorrectly formatted output. Luckily, you don’t have to memorize many complicated ‎combinations, as the following three are the most commonly used character specifiers:

How To Streamline Your Arduino Code Use sprintf to Declutter Serial Calls

Keep in mind that many more formatting options exist. It is, for example, possible to instruct ‎sprintf to convert numbers to their hexadecimal representation before inserting the result into the ‎string. At the same time though, you should not concern yourself with remembering all possible ‎specifiers, as you can easily refer to the manual to look for a more specialized output format.

Arduino’s sprintf implementation may not support all specifiers. It does, for instance, also require ‎programmers to use the %s specifier and supply floating-point numbers converted to strings on ‎some Arduinos.

Summary

Sending variable values over an Arduino’s serial port can drastically increase the length of ‎Arduino programs when using single serial print commands, as it’s often done. Therefore, using ‎sprintf can significantly reduce the number of lines of code required to send data over the serial ‎port.

Instead of printing one variable at a time, the sprintf command allows programmers to define a ‎prepared string that contains blanks needing to be filled in with variable values. For that purpose, ‎though, the programmer must know how many characters the string will occupy once ‎assembled, and they must also ensure that the final text never overflows the buffer.

How To Streamline Your Arduino Code Use sprintf to Declutter Serial Calls The Arduino IDE’s serial monitor shows the result of the modified program making use of the ‎sprintf call

When defining the formatted string, programmers can use specifiers that let sprintf know how to ‎treat the variable values when filling in prepared text blank spaces. While supplying an incorrect ‎specifier will often not result in immediate errors, doing so will typically lead to malformed output ‎and potential errors further down the line.

制造商零件编号 A000005
ARDUINO NANO ATMEGA328 EVAL BRD
Arduino
制造商零件编号 A000062
ARDUINO DUE ATSAM3X8E EVAL BRD
Arduino
制造商零件编号 ABX00012
ARDUINO MKR ZERO W/ HDR ATSAMD21
Arduino
制造商零件编号 ABX00062
ARDUINO UNO MINI LE
Arduino
制造商零件编号 A000066
ARDUINO UNO R3 ATMEGA328P BOARD
Arduino
制造商零件编号 A000057
ARDUINO LEONARDO W/ HDRS ATMEGA3
Arduino
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum