Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 20 of 20

Thread: Printf revisited?

  1. #1
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764

    Printf revisited?

    Hi all. Printf does not seem to be working even if I do a Serial.printf or do a #define printf Serial.printf which I saw on another thread. All I am doing in a loop is Serial.printf("This is a test\n"); and nothing is printed.

    Yes I know I can switch to sprintf or snprintf but would rather not if I don't have to since its embedded in this function:
    Code:
    /*
     * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
     */
    
    #ifndef UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    #define UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    
    #include <uavcan/util/templates.hpp>
    #include <cstdio>
    #include <Arduino.h>
    //#define printf Serial.printf 
    
    namespace uavcan
    {
    /**
     * Compact replacement for ostream for use on embedded systems.
     * Can be used for printing UAVCAN messages to stdout.
     *
     * Relevant discussion: https://groups.google.com/forum/#!topic/px4users/6c1CLNutN90
     *
     * Usage:
     *      OStream::instance() << "Hello world!" << OStream::endl;
     */
    class UAVCAN_EXPORT OStream : uavcan::Noncopyable
    {
        OStream() { }
    
    public:
        static OStream& instance()
        {
            static OStream s;
            return s;
        }
    
        static OStream& endl(OStream& stream)
        {
            printf("\n");
            return stream;
        }
    };
    
    inline OStream& operator<<(OStream& s, long long x)          { printf("%lld", x);  return s; }
    inline OStream& operator<<(OStream& s, unsigned long long x) { printf("%llu", x); return s; }
    
    inline OStream& operator<<(OStream& s, long x)           { printf("%ld", x); return s; }
    inline OStream& operator<<(OStream& s, unsigned long x)  { printf("%lu", x); return s; }
    
    inline OStream& operator<<(OStream& s, int x)            { printf("%d", x);  return s; }
    inline OStream& operator<<(OStream& s, unsigned int x)   { printf("%u", x);  return s; }
    
    inline OStream& operator<<(OStream& s, short x)          { return operator<<(s, static_cast<int>(x)); }
    inline OStream& operator<<(OStream& s, unsigned short x) { return operator<<(s, static_cast<unsigned>(x)); }
    
    inline OStream& operator<<(OStream& s, long double x) { printf("%Lg", x); return s; }
    inline OStream& operator<<(OStream& s, double x)      { printf("%g", x);  return s; }
    inline OStream& operator<<(OStream& s, float x)       { return operator<<(s, static_cast<double>(x)); }
    
    inline OStream& operator<<(OStream& s, char x)        { printf("%c", x); return s; }
    inline OStream& operator<<(OStream& s, const char* x) { printf("%s", x); return s; }
    
    inline OStream& operator<<(OStream& s, OStream&(*manip)(OStream&)) { return manip(s); }
    
    }
    
    #endif // UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    Who knows this might be a handy function for a cout replacement. I also don't think the Streaming library handles all the types listed.

    Thanks

    Mike

  2. #2
    Senior Member brtaylor's Avatar
    Join Date
    Mar 2016
    Location
    Portland, OR
    Posts
    324
    Quote Originally Posted by mjs513 View Post
    Hi all. Printf does not seem to be working even if I do a Serial.printf or do a #define printf Serial.printf which I saw on another thread. All I am doing in a loop is Serial.printf("This is a test\n"); and nothing is printed.

    Yes I know I can switch to sprintf or snprintf but would rather not if I don't have to since its embedded in this function:
    Code:
    /*
     * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
     */
    
    #ifndef UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    #define UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    
    #include <uavcan/util/templates.hpp>
    #include <cstdio>
    #include <Arduino.h>
    //#define printf Serial.printf 
    
    namespace uavcan
    {
    /**
     * Compact replacement for ostream for use on embedded systems.
     * Can be used for printing UAVCAN messages to stdout.
     *
     * Relevant discussion: https://groups.google.com/forum/#!topic/px4users/6c1CLNutN90
     *
     * Usage:
     *      OStream::instance() << "Hello world!" << OStream::endl;
     */
    class UAVCAN_EXPORT OStream : uavcan::Noncopyable
    {
        OStream() { }
    
    public:
        static OStream& instance()
        {
            static OStream s;
            return s;
        }
    
        static OStream& endl(OStream& stream)
        {
            printf("\n");
            return stream;
        }
    };
    
    inline OStream& operator<<(OStream& s, long long x)          { printf("%lld", x);  return s; }
    inline OStream& operator<<(OStream& s, unsigned long long x) { printf("%llu", x); return s; }
    
    inline OStream& operator<<(OStream& s, long x)           { printf("%ld", x); return s; }
    inline OStream& operator<<(OStream& s, unsigned long x)  { printf("%lu", x); return s; }
    
    inline OStream& operator<<(OStream& s, int x)            { printf("%d", x);  return s; }
    inline OStream& operator<<(OStream& s, unsigned int x)   { printf("%u", x);  return s; }
    
    inline OStream& operator<<(OStream& s, short x)          { return operator<<(s, static_cast<int>(x)); }
    inline OStream& operator<<(OStream& s, unsigned short x) { return operator<<(s, static_cast<unsigned>(x)); }
    
    inline OStream& operator<<(OStream& s, long double x) { printf("%Lg", x); return s; }
    inline OStream& operator<<(OStream& s, double x)      { printf("%g", x);  return s; }
    inline OStream& operator<<(OStream& s, float x)       { return operator<<(s, static_cast<double>(x)); }
    
    inline OStream& operator<<(OStream& s, char x)        { printf("%c", x); return s; }
    inline OStream& operator<<(OStream& s, const char* x) { printf("%s", x); return s; }
    
    inline OStream& operator<<(OStream& s, OStream&(*manip)(OStream&)) { return manip(s); }
    
    }
    
    #endif // UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    Who knows this might be a handy function for a cout replacement. I also don't think the Streaming library handles all the types listed.

    Thanks

    Mike
    Mike, unsigned long long, long long, and long double are not handled by the Streaming library. Having an easy way to direct printf to Serial.println() would be great! I often find myself developing C code methods on my PC that I want to use as part of Teensy projects and the lack of printf is a bit of nuisance.

    Brian

  3. #3
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    Brian. When I get it working I will definitely posted the update code here for testing.

    UPDATE: ok I ran this sketch:
    Code:
    #include <uavcan.h>
    
    //#include <uavan/uavcan.h>
    #include <uavcan/helpers/ostream.hpp>
    using namespace uavcan;
    
    double test = 98.9987485;
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);
      
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      OStream::instance() << "Hello world!" << ", " << test << OStream::endl; 
    
    }
    with this function:
    Code:
    /*
     * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
     */
    
    #ifndef UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    #define UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    
    #include <uavcan/util/templates.hpp>
    #include <cstdio>
    #include <Arduino.h>
    #define printf Serial.printf 
    
    namespace uavcan
    {
    /**
     * Compact replacement for ostream for use on embedded systems.
     * Can be used for printing UAVCAN messages to stdout.
     *
     * Relevant discussion: https://groups.google.com/forum/#!topic/px4users/6c1CLNutN90
     *
     * Usage:
     *      OStream::instance() << "Hello world!" << OStream::endl;
     */
    class UAVCAN_EXPORT OStream : uavcan::Noncopyable
    {
        OStream() { }
    
    public:
        static OStream& instance()
        {
            static OStream s;
            return s;
        }
    
        static OStream& endl(OStream& stream)
        {
            printf("\n");
            return stream;
        }
    };
    
    inline OStream& operator<<(OStream& s, long long x)          { printf("%lld", x);  return s; }
    inline OStream& operator<<(OStream& s, unsigned long long x) { printf("%llu", x); return s; }
    
    inline OStream& operator<<(OStream& s, long x)           { printf("%ld", x); return s; }
    inline OStream& operator<<(OStream& s, unsigned long x)  { printf("%lu", x); return s; }
    
    inline OStream& operator<<(OStream& s, int x)            { printf("%d", x);  return s; }
    inline OStream& operator<<(OStream& s, unsigned int x)   { printf("%u", x);  return s; }
    
    inline OStream& operator<<(OStream& s, short x)          { return operator<<(s, static_cast<int>(x)); }
    inline OStream& operator<<(OStream& s, unsigned short x) { return operator<<(s, static_cast<unsigned>(x)); }
    
    inline OStream& operator<<(OStream& s, long double x) { printf("%Lg", x); return s; }
    inline OStream& operator<<(OStream& s, double x)      { printf("%g", x);  return s; }
    inline OStream& operator<<(OStream& s, float x)       { return operator<<(s, static_cast<double>(x)); }
    
    inline OStream& operator<<(OStream& s, char x)        { printf("%c", x); return s; }
    inline OStream& operator<<(OStream& s, const char* x) { printf("%s", x); return s; }
    
    inline OStream& operator<<(OStream& s, OStream&(*manip)(OStream&)) { return manip(s); }
    
    }
    
    #endif // UAVCAN_HELPERS_OSTREAM_HPP_INCLUDED
    and it worked fine.
    Code:
    Hello world!, 98.9987
    Hello world!, 98.9987
    Hello world!, 98.9987
    Hello world!, 98.9987
    Hello world!, 98.9987
    So something else must be going on that I have to trace.
    Last edited by mjs513; 08-12-2018 at 06:14 PM.

  4. #4
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    Ok. Looking and looking but no clue. Anyone have any idea what could possibly cause printf not to print to serial?

    UPDATE: Figured it out. After looking at this post https://forum.pjrc.com/threads/24795...e%28%29+printf and embedding it in the sketch it led to a conflict. Looking at my sketch I found an old piece of code extern "C"{
    int _getpid(){ return -1;}
    int _kill(int pid, int sig){ return -1; }
    int _write(){return -1;}
    }
    that caused the conflict. Once I removed that didn't need the fix in the other post and it worked like a charm

    Mike
    Last edited by mjs513; 08-12-2018 at 08:19 PM.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    17,886
    Glad you found it.

  6. #6
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    Thanks, me too, something simple, so frustrating

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    6,622
    I see it working? IIRC T_LC has the printf code truncated due to space - is this with a T_LC?

    I tried it in the time sync sample [ where I ignored printf and called out to sprint ] Brian put out and it doesn't truncate to 32 bit: Serial.printf( "\t%llu", ttime_nanos*10000 );

    I had used the macro printf >> Serial.printf before I thought but compiler yelled at me today so I just did find&replace in samples I got from web below.

    I just haphazardly gathered some printf'y stuff here and it all seems to work T_3.1 and T_3.5:

    Code:
    void setup() {
      // put your setup code here, to run once:
      while (!Serial && millis() < 5000 );
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
    
    
      Serial.printf( "1\n" );
      Serial.printf( "1:%d\n", 1 );
      uint64_t x = 1234567890LL;
      Serial.printf("%lld\n", x);
      Serial.printf("%lld\n", x + x);
      Serial.printf("%lld\n", x * x);
    
      uint64_t z = 50596132LL;
      Serial.printf( "llu>> \t%llu\n", z );
      Serial.printf( "\t%llu\n", z * 10000 + 333 );
    
      int ii;
      uint32_t mm = 1;
      for ( ii = 0; ii <= 32; ii++ ) {
        Serial.printf( "\tmmu>>  %u", mm );
        mm *=2;
        if ( !(ii%4) ) Serial.println();
      }
    
      uint64_t nn = 1;
      for ( ii = 0; ii <= 64; ii++ ) {
        Serial.printf( "\tnnLLu>> %llu", nn ); // requires ll
        nn *=2;
        if ( !(ii%4) ) Serial.println();
      }
    
      float testf = 98.9987485;
      for ( ii = 0; ii <= 12; ii++ ) {
        Serial.printf( "\ttest f>> %f", testf );
        testf *=10;
        if ( !(ii%3) ) Serial.println();
      }
      double test = 98.9987485;
      for ( ii = 0; ii <= 12; ii++ ) {
        Serial.printf( "\ttest d>> %f", test );
        test *=10;
        if ( !(ii%3) ) Serial.println();
      }
    
      uint64_t zb = 50596132L;
      Serial.printf( "zb>> \t%llu\n", zb );
      Serial.printf( "\t%llu\n", zb * 10000 + 333 );
    
    
      float y = 12345.67890f;
      Serial.printf("%lld\n", y);
    
      Serial.printf("Characters: %c %c \n", 'a', 65);
      Serial.printf("Decimals: %d %ld\n", 1977, 650000L);
      Serial.printf("Preceding with blanks: %10d \n", 1977);
      Serial.printf("Preceding with zeros: %010d \n", 1977);
      Serial.printf("Some different radices: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100);
      Serial.printf("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
      Serial.printf("Width trick: >%*d< \n", 5, 10);
      Serial.printf("%s \n", "A string");
    
      Serial.printf("Strings:\n");
      const char* s = "Hello";
      Serial.printf("\t.%10s.\n\t.%-10s.\n\t.%*s.\n", s, s, 10, s);
    
      Serial.printf("Characters:\t%c %%\n", 65);
    
      Serial.printf("Integers\n");
      Serial.printf("Decimal:\t%i %d %.6i %i %.0i %+i %i\n", 1, 2, 3, 0, 0, 4, -4);
      Serial.printf("Hexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6);
      Serial.printf("Octal:\t%o %#o %#o\n", 10, 10, 4);
    
      Serial.printf("Floating point\n");
      Serial.printf("Rounding:\t%f %.0f %.32f\n", 1.5, 1.5, 1.3);
      Serial.printf("Padding:\t%05.2f %.2f %5.2f\n", 1.5, 1.5, 1.5);
      Serial.printf("Scientific:\t%E %e\n", 1.5, 1.5);
      Serial.printf("Hexadecimal:\t%a %A\n", 1.5, 1.5);
    
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }

  8. #8
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    Hi Tim. No it was with a T3.5 and T3.6 but I think you missed the post where I got it working - https://forum.pjrc.com/threads/53423...l=1#post185150. There was a conflict with another piece of outdated code in the sketch that came from the example I was using. Once I got rid of that old code it worked

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    6,622
    I see that now - my browser didn't update right - I was watching Shark Week and playing with printf ... did my post and saw Pauls' post - and your update still didn't draw ... really wondered what the fix was ... then after refresh ...

    Either way - I learned to trust printf to work where I had been avoiding it and code bloat on T_3.5/3.6 not so much a worry for the features it offers!

    33KB for that post #7 pile of nothing on T_3.5:
    Sketch uses 33060 bytes (6%) of program storage space. Maximum is 524288 bytes.
    Global variables use 5320 bytes (2%) of dynamic memory, leaving 256816 bytes for local variables. Maximum is 262136 bytes.
    And on T_3.2 - with 256KB Flash it is okay too ::
    Sketch uses 32784 bytes (12%) of program storage space. Maximum is 262144 bytes.
    Global variables use 4984 bytes (7%) of dynamic memory, leaving 60552 bytes for local variables. Maximum is 65536 bytes.
    Last edited by defragster; 08-12-2018 at 11:49 PM.

  10. #10
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    Done that myself Tim. Cross posts always got me.

    Either way - I learned to trust printf to work where I had been avoiding it and code bloat on T_3.5/3.6 not so much a worry for the features it offers!
    Didn't make much of a difference in the sketch size with the T3.5/T3.6 and printf does make it easier.

  11. #11
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    6,622
    Those were both with printf code.

    A simple print pair is a 12K sketch, making them printf jumps to 30K. ... that's why it is off by default in T_LC with 64K.

  12. #12
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    @defragster. I just did a compile on the T3.6 with the UAVcan code and the difference in using the Ostream function was only about 700bytes. I will have to give it a test as a separate function.

  13. #13
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    6,622
    Quote Originally Posted by mjs513 View Post
    @defragster. I just did a compile on the T3.6 with the UAVcan code and the difference in using the Ostream function was only about 700bytes. I will have to give it a test as a separate function.
    Let me know if there is a min set needed to try. I saw there was the #include of a library and wasn't sure if that was required to try it.

    Code:
    #include <uavcan.h>
    #include <uavcan/helpers/ostream.hpp>
    … and wasn't sure where the 2nd code block in that post #3 went and it has:
    Code:
    #include <uavcan/util/templates.hpp>
    #include <cstdio>

  14. #14
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    I am going to try and make it stand alone so I can use it in any sketch and will let you know. Running into a few other problems now Probably will make that a separate post.

  15. #15
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    6,622
    Will look fir it

    Notr sure if you saw my LTO Debug thread - printf works except with LTO

  16. #16
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    Notr sure if you saw my LTO Debug thread - printf works except with LTO
    No I didn't see that one. Will have to see if I can find it. Anyway here is the standalone version with OStream.

    Have fun...
    Attached Files Attached Files

  17. #17
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    6,622
    It is here: https://forum.pjrc.com/threads/53451...296#post185296

    <edit> - that is pretty FAT!

    Sketch uses 31652 bytes (3%) of program storage space. Maximum is 1048576 bytes.
    Global variables use 5568 bytes (2%) of dynamic memory, leaving 256576 bytes for local variables.


    Comment out the loop line:

    Sketch uses 9204 bytes (0%) of program storage space. Maximum is 1048576 bytes.
    Global variables use 4072 bytes (1%) of dynamic memory, leaving 258072 bytes for local variables.

    ODDLY that compiles with printf code compiled with LTO - unlike my like sketch

  18. #18
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    ODDLY that compiles with printf code compiled with LTO - unlike my like sketch
    Not sure if that's good or bad.

    Wonder why the bloat when its in the loop? Something not clearing?

  19. #19
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    6,622
    Bloat is from added printf code pulled in. Not from being 'in' loop - would be the same if moved one time to setup()

  20. #20
    Senior Member
    Join Date
    Jul 2014
    Location
    New York
    Posts
    1,764
    Interesting thing is that I added and deleted addition prints in loop and didn't change the size noticeably. Once you call it, not much additional is added for addition stream cases. Have to do a test.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •