stdin/stdout

Do the Arduino libraries support the concept of stdin/stdout/stderr? If so, is there an easy way to re-direct them (to different Serial ports, Ethernet, etc.)?

Regards, Ray L.

Arduino libraries don't (as as far as I know) but avr-gcc does for serial I/O. Look up the fdev_setup_stream() function or the macro. Works with printf and scanf. This defines stdout only, to be the UART:

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

No, the arduino is considered a "stand-alone" and not a "hosted" environment. If you don't have an OS, the C-standard allows you to ignore things like stdxxx.

RayLivingston:
Do the Arduino libraries support the concept of stdin/stdout/stderr? If so, is there an easy way to re-direct them (to different Serial ports, Ethernet, etc.)?

Regards,
Ray L.

Here’s what I use:

Stdinout.cpp

/*
    Stdinout.cpp - connect various character devices to standard streams
    Part of Arduino - http://www.arduino.cc/

    Copyright (c) 2014, 2015 Roger A. Krupski <rakrupski@verizon.net>

    Last update: 26 April 2015

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <Stdinout.h>

static Stream *_stream_ptr;

// connect stdio to stream
void STDINOUT::open (Stream &str)
{
	close();
	_stream_ptr = &str;
	_fp = fdevopen (_putchar, _getchar);
}

// disconnect stdio from stream
void STDINOUT::close (void)
{
	if (_fp) {
		fclose (_fp);
		_fp = NULL;
		_stream_ptr = NULL;
	}
}

// function that printf and related will use to write a char
int STDINOUT::_putchar (char c, FILE *_fp)
{
	if (c == '\n') { // \n sends crlf
		_putchar ((char) '\r', _fp);
	}

	_stream_ptr->write (c);
	return 0;
}

// Function that scanf and related will use to read a char
int STDINOUT::_getchar (FILE *_fp)
{
	while (! (_stream_ptr->available()));

	return (_stream_ptr->read());
}

STDINOUT STDIO; // Preinstantiate STDIO object

// end of stdinout.cpp

Stdinout.h

/*
    Stdinout.h - connect various character devices to standard streams
    Part of Arduino - http://www.arduino.cc/

    Copyright (c) 2014, 2015 Roger A. Krupski <rakrupski@verizon.net>

    Last update: 26 April 2015

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef STD_IN_OUT_H
#define STD_IN_OUT_H

#include <Stream.h>

class STDINOUT {
	public:
		void open (Stream &);
		void close (void);
	private:
		FILE *_fp = NULL;
		static int _putchar (char, FILE *);
		static int _getchar (FILE *);
};

extern STDINOUT STDIO; // Preinstantiate STDIO object

#endif

// end of Stdinout.h

You can place these two files in your [b]arduino-x.x.x/hardware/arduino/cores/arduino[/b] directory and then either #include Stdinout.h or else add the include to your Arduino.h file. It doesn’t use any memory unless you actually connect the standard IO stream to the serial port.

Then to use it simply call the open function after defining your serial port, like this:

Serial.begin (115200); // as usual
STDIO.open (Serial); // connect serial port to stdin/out/err
//..... use ....
STDIO.close (); // release stdin/out/err when done with it

If you use a different com port, you can connect it to the standard IO stream using [b]STDIO.open (Serial1);[/b]No need to close the first instance since a close is called before an open anyway.

Hope this helps.

jremington: Arduino libraries don't (as as far as I know) but avr-gcc does for serial I/O. Look up the fdev_setup_stream() function or the macro. Works with printf and scanf. This defines stdout only, to be the UART:

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

Other character devices (LCD, etc...) can also be connected to the standard IO streams. A small modification is required to certain libraries though. For example the LiquidCrystal library needs to be changed from using "Print" to using "Stream" and dummy code for "available", "peek", "read" and "flush" needs to be added (they all just return 0).

With modified libraries, I can do a STDIO.open (Serial), send stuff to the serial monitor using "printf", then switch on the fly to STDIO.open (LCD) and use printf to display on an LCD, then STDIO.open (RTC) and sscanf() stuff from the real time clock, etc...

It's really handy and it avoids using dozens of "Serial.print()" calls to build up a single line of display,

KeithRB: No, the arduino is considered a "stand-alone" and not a "hosted" environment. If you don't have an OS, the C-standard allows you to ignore things like stdxxx.

You may be allowed to ignore them, but they are available if you wish to use them.