[Solved]Printf needs SPI.h to run

I use the printf() function often so as to put multiple values on one line. I’ve discovered that the SPI.h header needs to be included. Some sketches use SPI.h and others do not need it. This is probably not SPI itself but something in it that printf() needs. Can someone tell me what needs to be included so that I don’t need SPI.h when I only want the printf() function to run?

Here is my test sketch. It runs OK if SPI.h is included.

#include <SPI.h>
#include "printf.h"

void setup() 
{
    Serial.begin( 250000 ); // Start the monitor
    printf_begin();         // Start printf function
}

void loop() 
{
    uint8_t a = 7;
    printf( "The value of 'a' = %d\n\r", a );
    delay( 1000 );
}

Here is the error statements when SPI.h is not included.

In file included from PrintfTest.ino:2:0:
C:\Users\Root2\Documents\Arduino\libraries\printf/printf.h:22:26: error: 'FILE' has not been declared
 int serial_putc( char c, FILE * )
                          ^
C:\Users\Root2\Documents\Arduino\libraries\printf/printf.h: In function 'int serial_putc(char, int*)':
C:\Users\Root2\Documents\Arduino\libraries\printf/printf.h:24:3: error: 'Serial' was not declared in this scope
   Serial.write( c );
   ^
C:\Users\Root2\Documents\Arduino\libraries\printf/printf.h: In function 'void printf_begin()':
C:\Users\Root2\Documents\Arduino\libraries\printf/printf.h:31:29: error: 'fdevopen' was not declared in this scope
   fdevopen( &serial_putc, 0 );
                             ^
void setup()
{
    Serial.begin( 115200 ); // Start the monitor
}

void loop()
{
    uint8_t a = 7;
    printf( "The value of 'a' = %d\n\r", a );
    delay( 1000 );
}

Removing the two include statements and the printf_begin now stops all output to the serial monitor. Including printf_begin in setup() triggers the error messages.

Not on my Mega or my Due. Which Arduino board are you using?

Mega2560 with IDE 1.6.5-rc5. I'll try it with an Uno.

Same problem with the Uno.

Is all of the SPI library compiled and uploaded or just the parts needed. If the later, I can live with the behavior.

It appears to work only on my Due. The Mega compiles it, but you are correct. It doesn’t display anything.

edit: However, this works.

    uint8_t a = 7;
    Serial.print( "The value of 'a' = ");
    Serial.println(a);

That's the method I'm trying to avoid, multiple lines for one variable and identifier.

I found a clue but haven't tried it yet. The verbose window says it found multiple printf.h libraries. The one I'm using is from ManiacBug and is part of the RF24 series which uses SPI.h. There may be inter-dependencies among his three libraries. I'm going to delete his from my library folder and see if the compiler picks up another, which has all the components included.

PS
Tried it but that's not the answer. It compiles without the library from ManiacBug so there's another one embedded somewhere. However, I get no output and including printf_begin() without the #include triggers the compile errors again.

Unless someone can find the solution, I'll just include SPI.h for now.

I don't have the include file, so I can't compile your code. Have you checked whether it is more memory efficient to use printf rather than two Serial.prints?

The printf() version uses 4376 bytes while the Serial.print uses 2412, a big difference. Apparently, the entire SPI library gets compiled and uploaded. One could use the printf() while testing a sketch then comment out the SPI.h and printf.h #includes and all printf() lines. Seems like a lot of hassle but could be solved by making prinft.h include all and only what is needed. The library I have is dated 2011 so perhaps there's one newer. Will do more searching.

The code compiles for me on a NANO or MEGA 2560 when I remove the include of SPI.h
This is with the latest IDE 1.6.7
Perhaps your problem is that you are still using 1.6.5

Pete

Oh, that printf.h is in your local libraries directory. Where did you get it from?
I also have one but it is part of a modified RF24 library.

Pete

I tried 1.6.6 and 1.6.7 and had numerous problems. I had to remove them completely and start over with 1.6.5-rc5. That's the only thing that solved my problems. Also, the latest board package for Zero and Due had to use only 1.6.2 and 1.6.4 respectively. I'll have to stay with 1.6.5.

The printf library came from ManiacBug and is dated 2011.

I'm trying to use SerialPrint2 again but cannot get it to work. One of problems I had previously was that the function code had to precede it's use. There's supposed to be a way of declaring it near the top of the sketch and define it further down but I haven't figured that part out yet.

Here's the new code. // Something went wrong

Got the SerialPrint2() to work but it has more overhead than Serial.print but less than printf() and it’s two dependencies. This one is 3726 bytes.

#include <stdarg.h>

void SerialPrint2(char *format,...)
{
 char buff[128];
 va_list args;
 va_start (args,format);
 vsnprintf(buff,sizeof(buff),format,args);
 va_end (args);
 buff[sizeof(buff)/sizeof(buff[0])-1]='\0';
 Serial.print(buff);
}

void setup() 
{
   Serial.begin( 250000 ); // Start the monitor
}

void loop() 
{
   uint8_t a = 7;
   SerialPrint2( "The value of 'a' = %d\n\r", a );
   delay( 1000 );
}

It turns out that the definition of the function had to be positioned before any use. This clutters the top of the sketch. The solution is to declare the function near the top with one line of code but define it’s actions further down as you would a normal function or procedure. Here is the final code.

#include <stdarg.h>

void SerialPrint2(char *format,...); // Declare function here but code further down

void setup() 
{
    Serial.begin( 250000 ); // Start the monitor
}

void loop() 
{
    uint8_t a = 7;
    SerialPrint2( "The value of 'a' = %d\n\r", a );
    delay( 1000 );
}

void SerialPrint2(char *format,...)
{
  char buff[128];
  va_list args;
  va_start (args,format);
  vsnprintf(buff,sizeof(buff),format,args);
  va_end (args);
  buff[sizeof(buff)/sizeof(buff[0])-1]='\0';
  Serial.print(buff);
}