0

I recently came across this nice SerialPrint() implementation:

void StreamPrint_progmem(Print &out,PGM_P format,...)
{
  // program memory version of printf - copy of format string and result share a buffer
  // so as to avoid too much memory use
  char formatString[128], *ptr;
  strncpy_P( formatString, format, sizeof(formatString) ); // copy in from program mem
  // null terminate - leave last char since we might need it in worst case for result's \0
  formatString[ sizeof(formatString)-2 ]='\0'; 
  ptr=&formatString[ strlen(formatString)+1 ]; // our result buffer...
  va_list args;
  va_start (args,format);
  vsnprintf(ptr, sizeof(formatString)-1-strlen(formatString), formatString, args );
  va_end (args);
  formatString[ sizeof(formatString)-1 ]='\0'; 
  out.print(ptr);
}

#define Serialprint(format, ...) StreamPrint_progmem(Serial,PSTR(format),##__VA_ARGS__)
#define Streamprint(stream,format, ...) StreamPrint_progmem(stream,PSTR(format),##__VA_ARGS__)

I want to use it in my more complex projects to save precious RAM space.

This works really well when I have just one *.ino file where I'm using the SerialPrint() function. When I try to use it in my more complext projects, which consist of a central *.ino files and several .cpp/.h files (mostly one cpp/h pair per class). The problem is if I put the code below into the *.ino file, it will not be known inside any of the *.cpp files. The compiler is not complanining, but I'm never seeing the serial output of my code.

Any ideas how to fix it? I've tried putting this code in a central global.cpp/h file which I include everywhere, but it does not seem to work (no output on serial).

Thanks in advance!-

3
  • This looks to me like an inefficient emulation of vsnprintf_P(). Also, if you want to use printf-style formatting, why not just use printf()? May 19, 2015 at 11:23
  • @EdgarBonet: Correct me if I'm wrong but I don't think the functions you mention are availabe in the arduino IDE. The code I linked to allows use of printf() like functionality with the added extra that it puts the formatting strings in progmem, saving precious RAM in the process.
    – Alex
    May 19, 2015 at 20:44
  • They are available. On AVR-based boards, like the Uno, the Arduino library is built atop avr-libc, and all the functionality of this library is available. The only caveat is that you have to set up stdout before using it, c.f. the documentation on stdio.h. You can have the formatting string in progmem too by using printf_P() and the other _P variants. May 20, 2015 at 6:02

1 Answer 1

3

Have you thought of turning it into a small library?

libraries/StreamPrint/StreamPrint.cpp:

#include <StreamPrint.h>

void StreamPrint_progmem(Print &out,PGM_P format,...)
{
  // program memory version of printf - copy of format string and result share a buffer
  // so as to avoid too much memory use
  char formatString[128], *ptr;
  strncpy_P( formatString, format, sizeof(formatString) ); // copy in from program mem
  // null terminate - leave last char since we might need it in worst case for result's \0
  formatString[ sizeof(formatString)-2 ]='\0'; 
  ptr=&formatString[ strlen(formatString)+1 ]; // our result buffer...
  va_list args;
  va_start (args,format);
  vsnprintf(ptr, sizeof(formatString)-1-strlen(formatString), formatString, args );
  va_end (args);
  formatString[ sizeof(formatString)-1 ]='\0'; 
  out.print(ptr);
}

libraries/StreamPrint/StreamPrint.h:

#include <Arduino.h>

extern void StreamPrint_progmem(Print &out,PGM_P format,...);

#define Serialprint(format, ...) StreamPrint_progmem(Serial,PSTR(format),##__VA_ARGS__)
#define Streamprint(stream,format, ...) StreamPrint_progmem(stream,PSTR(format),##__VA_ARGS__)

Then in your code, wherever you want to use it:

#include <StreamPrint.h>

You can read more about writing libraries here: http://www.arduino.cc/en/Hacking/LibraryTutorial

5
  • Thanks for your answer. I tried this but got some compiler errors: StreamPrint.h:6:68: error: initializer fails to determine size of '__c' StreamPrint.h:6:68: error: array must be initialized with a brace-enclosed initializer StreamPrint.h:6:94: error: invalid initialization of non-const reference of type 'Print&' from an rvalue of type 'const char*' StreamPrint.h:3:13: error: in passing argument 1 of 'void StreamPrint_progmem(Print&, const char*, ...)'
    – Alex
    May 19, 2015 at 20:52
  • Compiles fine for me. What are you using?
    – Majenko
    May 19, 2015 at 21:07
  • Normally visual studio 2013 with VisualMicro, but I tried in arduino IDE 1.6.1 and got the same error
    – Alex
    May 19, 2015 at 21:13
  • It must be the code surrounding it then, since I can't get it to fail at all. Try posting your test code.
    – Majenko
    May 19, 2015 at 21:14
  • Yep I had borked it... I started a new test sketch and suddenly everything works. Found out I had the code also still in my main *.ino file of my other big project.. Thanks for your help!
    – Alex
    May 19, 2015 at 21:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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