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!-

  • 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()? – Edgar Bonet May 19 '15 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 '15 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. – Edgar Bonet May 20 '15 at 6:02
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

  • 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 '15 at 20:52
  • Compiles fine for me. What are you using? – Majenko May 19 '15 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 '15 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 '15 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 '15 at 21:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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