Using stdin, stdout, printf, scanf, etc

When people either get fed up with using a series of Serial.print()s or want to do things the Print library cannot (like constant width numbers), common advice on the forums is to use sprintf to print to a buffer and then use Serial.print(buf). However, there are several things wrong with that. The first is that it's kind of annoying -- it takes at least three lines to just print out one line. The second, and more important problem, is that you need to anticipate the largest size print you'll need (easily possible, but again annoying) and have that much free RAM (which may be impossible). However, there is a way around it -- by using printf directly and having it print one character at a time to the Serial stream.

This page: http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html is where I found most of the information needed to do this. It isn't too hard to set this up for your own sketch:

// 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(){
    Serial.begin(115200);

    // Set up stdout
    fdev_setup_stream(&serial_stdout, serial_putchar, NULL, _FDEV_SETUP_WRITE);
    stdout = &serial_stdout;
    
    printf("My favorite number is %6d!", 12);
}

void loop() {
    
}

However, I then thought about making this so that it would be easier to use. I tried two things: the first was modifying wiring.c to add the setting up to the init() function. This ended up working (although I had to compile wiring.c as a c++ file: the result is here), and I think it's not unreasonable to suggest that this change is incorporated into the main IDE (thoughts?) However, I then thought about making it into a library, and with a little trickery I managed to get it to work (although I think there's more overhead than necessary). The link to the library is here: https://github.com/WizenedEE/arduino/tree/master/libraries/stdinout and here's a sketch where I use both printf and scanf heavily (it controls a robot with a PID loop): https://github.com/WizenedEE/arduino/blob/master/rover5/PIDTest/PIDTest.ino

When using the library, remember that the %f flag doesn't work unless you add some linker options, described on the nongnu page.

Any suggestions on how to call the setup_stdin_stdout() without user interaction would be nice. The method I use is described in Thinking in C++ volume 1, chapter 10. I also tried putting the function in the .init section, but it didn't appear to work (stdin and stdout were not set up)

void setup_stdin_stdout() __attribute__ ((section (".init8")));

I tried making a class with the constructor calling the function and then making an instance local to the .cpp file, but that didn't appear to call it either (and it's hard to debug because Serial isn't setup until the setup() function is called)

struct blah {
    blah() { setup_stdin_stdout(); }
};
static blah myblah;

There, I hoped that helped anyone wanting to use printf, will influence a future version of the IDE, and will get me some help on how to make the library. Thanks for reading.

Did you ever make any progress with this?

I'm thinking about doing something similar for the STM32 board using the Arduino 1.5.x IDE

However I was going to make a new method of Serial.printf

I was stumped about how you configure a stream to output via a specific function, but it looks like
the code I need in in your post i.e

fdev_setup_stream(&serial_stdout, serial_putchar, NULL, _FDEV_SETUP_WRITE);

So I'll give it a whirl

Thanks

Roger

Here is a good library for using STDIN, STDOUT:

There's a couple of great little C++ methods for printing without wanting to hang yourself. One is variadic templates

#include <type_traits>
#include <iostream>
#include <etk/etk.h>

void put(char c) //a pretend serial port
{
 cout << c;
}

class HardwareSerial
{
public:

 void print(const char* cstr)
 {
 while(*cstr != '\0')
 put(*cstr++);
 }
 
 template<typename T> void print(T v)
 {
 char buf[20];
 etk::Rope rope(buf, 20);
 rope << v;
 for(uint32_t i = 0; i < rope.length(); i++)
 put(buf[i]);
 }

 template<typename T, typename... Args> void print(T first, Args... args) 
 {
 print(first);
 print(args...);
 }
};

HardwareSerial Serial;

int main()
{
 Serial.print("Hello world ", 56, ' ', 53.43);
}

The other is overloading the chomp operator

#include <type_traits>
#include <iostream>
#include <etk/etk.h>

void put(char c) //a pretend serial port
{
 cout << c;
}

class HardwareSerial
{
public: 
 HardwareSerial& operator << (const char* s)
 {
 uint32_t l = etk::Rope::c_strlen(s, 1024);
 for(uint32_t i = 0; i < l; i++)
 put(s[i]);
 return *this;
 }
 
 template<typename T> HardwareSerial& operator << (T s)
 {
 char buf[20];
 etk::Rope rope(buf, 20);
 rope << s;
 for(uint32_t i = 0; i < rope.length(); i++)
 put(buf[i]);
 return *this;
 }
 
};

HardwareSerial Serial;

int main()
{
 Serial << "Hello world " << 56 << ' ' << 53.43; //chomp chomp chomp
}

Both are a lot more modern and user friendly (AND SAFER) than sprintf. Variadic templates are the most intuitive IMO, but are only available with C++11 which the AVR compiler doesn't support. g++-arm-none, on the other hand, is actually not junk and does C++14 . AFAIK all methods will require a small buffer when putting ints and floats to a stream.

@camel, you might be interested in my PrintEx library, it contains both these methods for use with any Print/Stream object.

Also there is no need for any buffers with my methods.

C++11 has been enabled since IDE 1.6.6 and can be enabled in 1.5.7 and above.

pYro_65:
@camel, you might be interested in my PrintEx library, it contains both these methods for use with any Print/Stream object.

Also there is no need for any buffers with my methods.

GitHub - Chris--A/PrintEx: An extension to the Arduino Print library, and much, much more...

C++11 has been enabled since IDE 1.6.6 and can be enabled in 1.5.7 and above.

Now that is brilliant.

I've got to ask, how do you get away with printing ints and floats to streams without a temporary buffer?

All the methods use the built in conversion functions (in the Arduino Print library). They are printed directly to the stream/output.

The methods are here.

The manipulators build up a proxy object which is used to store the formatting features. Due to the manipulators being types, they are all compile time constants. The stream functionality is optimized simply to xx.print(...) calls.

I have had a peek at your StaticString lib and it is something I was thinking of replicating a while ago. However PrintEx contains a string which can be printed or streamed to (different take on a string).

E.g.

  char buffer[100];
  
  //SRAM printable.
  GString str = buffer;
  
  str.println( "Hi" );
  
  str << "A hex value:" << ios::hex << 12345 << ios::endl;
  
  //EEPROM printable.
  EString estr = 0;
  
  estr << "My EE string" << 12345;

I have only just realized, I have not attached the stream in interface to E/G/PString. I'll do that now.

That's interesting, your GString is similar in function to my Rope class only Rope doesn't have manipulators like GString. It's a pretty good way to handle strings IMO. Does GString know where the end of the buffer is? My biggest gripe against C string functions is that they will happily chew up memory they shouldn't.

No, it'll happily overrun the buffer. Its entirely up to the user to ensure they provide the correct amount of storage.

I've thought about a 'safe' version however I haven't seen really any circumstances where code can't be factored to appropriately provide initial storage (embedded systems anyway). I thought of adding debug error handling which would provide errors on overrun allowing a user to change their buffers. Then use the more efficient method in release (no error checking).

Yeah, I guess it's generally not too hard to make buffers big enough. It's mostly things like sprintf(buf, "%s", a_string_of_unknown_length_that_possibly_isnt_null_terminated); that get you - and there's a lot of that posted on these forums.

I'll look over your code over the next couple of days, hopefully I'll learn more about manipulators.

The streaming functionality in PrintEx is my own design. The standard implementation most probably does it differently, so if you have questions just ask.

Most of the features in PrintEx are implemented as 'plugin' modules using a concept called CRTP (curiously recurring template pattern).