Go Down

Topic: Adding printf (Read 6294 times) previous topic - next topic

Okio



If you find using multiple serial.print() per printed line cumbersome, or simply want a formatted print function then give this a try.
It'll allow you to use printf() in place of serial.print(). Although intended for Serial/SerialUSB, it could easily be directed towards the TFT library of choice.

   
Usage:
add: include <printf.h>
and to use: printf(format string, argument(s) list).
printfn(): As above but appends a new line on each print; aka serial.println()
   
eg; printf("%.2f, 0x%X", 1234.5678f, 32768);
   

Configure:
Set a buffer size with _PRINTF_BUFFER_LENGTH_, default is 64 bytes, or about a single line
Set output stream with _Stream_Obj_. eg; SerialUSB


For a detailed list on printf specifiers:
http://www.cplusplus.com/reference/cstdio/printf/
and
http://man7.org/linux/man-pages/man3/printf.3.html


Tested with the Arduino Due 1.6.6



Code: [Select]



/*

Using printf on the Arduino.
by Michael McElligott

Usage:
Set a buffer size with _PRINTF_BUFFER_LENGTH_, default is 64 bytes, or about a single line
Set output stream with _Stream_Obj_. eg; SerialUSB

printf(format string, argument(s) list).
printfn(): As above but appends a new line on each print; aka serial.println()

eg; printf("%.2f, 0x%X", 1234.5678f, 32768);

For a detailed list on printf specifiers:
http://www.cplusplus.com/reference/cstdio/printf/
and
http://man7.org/linux/man-pages/man3/printf.3.html



Tested with the Arduino Due 1.6.6
Jan 2016

*/




#ifndef _printf_h_
#define _printf_h_

#define _PRINTF_BUFFER_LENGTH_ 64
#define _Stream_Obj_ Serial




#if 1
static char _pf_buffer_[_PRINTF_BUFFER_LENGTH_];
#else
extern char _pf_buffer_[_PRINTF_BUFFER_LENGTH_];
#endif


#define printf(a,...) \
do{ \
snprintf(_pf_buffer_, sizeof(_pf_buffer_), a, ##__VA_ARGS__); \
_Stream_Obj_.print(_pf_buffer_); \
}while(0)

#define printfn(a,...) \
do{ \
snprintf(_pf_buffer_, sizeof(_pf_buffer_), a"\r\n", ##__VA_ARGS__); \
_Stream_Obj_.print(_pf_buffer_); \
}while(0)



#endif



pYro_65

You might be interested in my PrintEx library (in library manager). It'll allow you to use printf with any Print based object (more than one at a time) and the data doesn't require a buffer (printed straight out).

There is also support for floating point, PROGMEM, and EEPROM data in the printf function.
Forum Mod anyone?
https://arduino.land/Moduino/

Okio

pYro_65,

Tried it, or at least tried to try it. It didn't compile and looking through the source it came across as slightly bloated for its intended use, IMHO of course.

Adding printf is quite a small task, it need not require a library.

pYro_65

pYro_65,

Tried it, or at least tried to try it. It didn't compile and looking through the source it came across as slightly bloated for its intended use, IMHO of course.

Adding printf is quite a small task, it need not require a library.
Code size is not relative to compiled size.

My library includes far more features than just printf, it is one of many tools you can use. It uses very efficient methods, including my own implementation of printf (yours trips up on memory use, floating point data, and other features missing from a standard printf implementation). You can also use streaming which can replace printf and its overhead altogether.

As for it not compiling, the example compiles straight out of the box. On old IDE's and newer ones using C++11.

Your version is a good attempt at something simple, if you do not need all the features of printf, or are happy being limited to a certain buffer size. But as soon as you use multiple interfaces or, require large amounts of buffer space, then its use can become more of a burden than just using simple print statements.

And for those applications that require a tight nit solution, there is at least one out there.
Forum Mod anyone?
https://arduino.land/Moduino/

Okio

#4
Jan 09, 2016, 01:32 pm Last Edit: Jan 09, 2016, 02:45 pm by Okio
I don't wish to turn this in to a ' mines better than yours' argument. I've better things to do.

Take it for what it is. Adding and using printf() should not be a difficult task: Include the header, set a buffer length which best suits your expected usage, profit :).


As a side note:
I use the Arduino Due, only, with IDE 1.6.6  (latest for the Due) for little more than 1 month. Neither sprintf nor snprintf (what this printf wraps around) have produced any observable indication that either have been thumbling their parsing of double and float types. ie; printf("%.2f", PI) will generate 3.14, as expected.

From my current project (viewable elsewhere on the forum), free memory stands at 40739 bytes. I can afford 64 of those.




Marttyn

I was waiting the implementation of printf in core:
https://github.com/arduino/Arduino/pull/5938
But unluckily ive found that it will not be done because Massimo Banzi "dont believe" it should be part of Arduino.

I like both approaches suggested here, but could not make work pYro's library. Instead solution proposed by Okio is simple and straightforward... Just im not sure what is this for:

Code: [Select]
#if 1
static char _pf_buffer_[_PRINTF_BUFFER_LENGTH_];
#else
extern char _pf_buffer_[_PRINTF_BUFFER_LENGTH_];
#endif

Marttyn

This days i used a lot the Okio aproach for printf, and its working great!
I removed the _streamObj_ define, and instead used a user defined object each time.
Code: [Select]

#define _PRINTF_BUFFER_LENGTH_  64

#if 1
static char _pf_buffer_[_PRINTF_BUFFER_LENGTH_];
#else
extern char _pf_buffer_[_PRINTF_BUFFER_LENGTH_];
#endif

#define printf(_obj_,a,...)                                                   \
  do{                                                                   \
    snprintf(_pf_buffer_, sizeof(_pf_buffer_), a, ##__VA_ARGS__);       \
    _obj_.print(_pf_buffer_);                                    \
  }while(0)

#define printfn(_obj_,a,...)                                                  \
  do{                                                                   \
    snprintf(_pf_buffer_, sizeof(_pf_buffer_), a"\r\n", ##__VA_ARGS__); \
    _obj_.print(_pf_buffer_);                                    \
  }while(0)

So now i can do:
Code: [Select]
printf(Serial, "%s", "Print to Serial");
printf(tft, "%s", "Print to TFT");


This simple modification allows to print on any stream object, not just one.

Go Up