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

Thread: Teensy LC printf float options

  1. #1
    Member capricorn one's Avatar
    Join Date
    Oct 2014
    Location
    Los Angeles
    Posts
    51

    Teensy LC printf float options

    Trying to printf with %e and %f, looks like it's not included in the compiler options for the LC. Anyone know the flag to add it? Can't seem to find it in all my searching.

    I realize I may have to use dtostrf, but what I really need is dtostre, which doesn't appear to be included either. Any options out there for me to print in scientific notation without rewriting hundreds of lines of my program?

    EDIT

    Doing some digging, if you compile with optimization at FAST or greater, you get the printf floats, but in the smallest code optimization you don't. That's understandable, the difference unfortunately is huge. When compiling with FAST my code is 65K, when using SMALLEST, it's 35K. I know the floating point printf requires a lot of space, but I know it's less than 30K, would be nice to be able to add it while still optimizing the rest of the code for smallest. Anyone know how to do that?

    I've come across a lot of posts suggesting adding this flag to the linker : -u _printf_float

    Unfortunately, it compiles, but crashes when executing printf with a float.
    Last edited by capricorn one; 02-12-2019 at 09:38 PM.

  2. #2
    Senior Member pictographer's Avatar
    Join Date
    May 2013
    Location
    San Jose, CA
    Posts
    681
    I haven't been able to make Serial.printf() print floats on the Teensy LC with any of the compiler settings I've tried. Some settings produce no output. Some produce different memory garbage. The output below is from Tools > Optimize > Smallest code.

    Arduino 1.8.12
    Teensyduino 1.52-beta3

    Code:
    void setup() {  while (!Serial && millis() < 2000) ;
      float pi = 3.1415926;
      Serial.printf("Printing Pi\n");
      Serial.print("Using Serial.print: ");
      Serial.print(pi, 4);
      Serial.println();
      Serial.printf("Using Serial.printf: %f\n", pi);
    }
    
    
    void loop() {}
    The code above produces the following in the serial monitor

    Code:
    17:33:27.921 -> Printing Pi17:33:27.921 -> Using Serial.print: 3.1416
    17:33:27.921 -> Using Serial.printf: 
    17:33:27.921 -> $⸮ntf: 
    17:33:27.921 -> l.printf: 
    17:33:27.921 -> klight/desklight.ino
    17:33:27.921 -> 456789abcdef0123456789abcdef0123456789abcde⸮@⸮@4⸮@K⸮ ⸮ ⸮⸮⸮⸮⸮ ⸮=<&⸮
    17:33:27.921 ->  ⸮=l ⸮ ⸮ ⸮El ⸮ mE⸮ ⸮H⸮ @[8⸮L׿⸮⸮d5&⸮⸮⸮⸮j⸮o⸮>j⸮⸮⸮⸮< ⸮ ⸮>< ⸮⸮⸮⸮  `@⸮⸮⸮⸮⸮ @⸮@⸮>⸮⸮⸮⸮P@⸮ @@` ⸮ y⸮⸮8 x ⸮ ⸮⸮@⸮ ⸮⸮:⸮@
    ⸮ M
    L ⸮ ⸮⸮6@⸮!    @+0 j⸮⸮
    17:33:27.921 -> 4163⸮7
    Here's the compiler output.

    Code:
    /home/corbett/arduino-1.8.12/arduino-builder -dump-prefs -logger=machine -hardware /home/corbett/arduino-1.8.12/hardware -hardware /home/corbett/.arduino15/packages -tools /home/corbett/arduino-1.8.12/tools-builder -tools /home/corbett/arduino-1.8.12/hardware/tools/avr -tools /home/corbett/.arduino15/packages -built-in-libraries /home/corbett/arduino-1.8.12/libraries -libraries /home/corbett/Arduino/libraries -fqbn=teensy:avr:teensyLC:usb=serialhid,speed=48,opt=osstd,keys=en-us -vid-pid=0X16C0_0X0487 -ide-version=10812 -build-path /tmp/arduino_build_685234 -warnings=all -build-cache /tmp/arduino_cache_241954 -verbose /home/corbett/Arduino/printf_bug/printf_bug.ino/home/corbett/arduino-1.8.12/arduino-builder -compile -logger=machine -hardware /home/corbett/arduino-1.8.12/hardware -hardware /home/corbett/.arduino15/packages -tools /home/corbett/arduino-1.8.12/tools-builder -tools /home/corbett/arduino-1.8.12/hardware/tools/avr -tools /home/corbett/.arduino15/packages -built-in-libraries /home/corbett/arduino-1.8.12/libraries -libraries /home/corbett/Arduino/libraries -fqbn=teensy:avr:teensyLC:usb=serialhid,speed=48,opt=osstd,keys=en-us -vid-pid=0X16C0_0X0487 -ide-version=10812 -build-path /tmp/arduino_build_685234 -warnings=all -build-cache /tmp/arduino_cache_241954 -verbose /home/corbett/Arduino/printf_bug/printf_bug.ino
    Using board 'teensyLC' from platform in folder: /home/corbett/arduino-1.8.12/hardware/teensy/avr
    Using core 'teensy3' from platform in folder: /home/corbett/arduino-1.8.12/hardware/teensy/avr
    Warning: Board microduino:avr:mddevice doesn't define a 'build.board' preference. Auto-set to: AVR_MDDEVICE
    Detecting libraries used...
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-g++ -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti -mthumb -mcpu=cortex-m0plus -fsingle-precision-constant -D__MKL26Z64__ -DTEENSYDUINO=152 -DARDUINO=10812 -DARDUINO_TEENSYLC -DF_CPU=48000000 -DUSB_SERIAL_HID -DLAYOUT_US_ENGLISH -I/home/corbett/arduino-1.8.12/hardware/teensy/avr/cores/teensy3 /tmp/arduino_build_685234/sketch/printf_bug.ino.cpp -o /dev/null
    Generating function prototypes...
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-g++ -E -CC -x c++ -w -g -Wall -ffunction-sections -fdata-sections -nostdlib -fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti -mthumb -mcpu=cortex-m0plus -fsingle-precision-constant -D__MKL26Z64__ -DTEENSYDUINO=152 -DARDUINO=10812 -DARDUINO_TEENSYLC -DF_CPU=48000000 -DUSB_SERIAL_HID -DLAYOUT_US_ENGLISH -I/home/corbett/arduino-1.8.12/hardware/teensy/avr/cores/teensy3 /tmp/arduino_build_685234/sketch/printf_bug.ino.cpp -o /tmp/arduino_build_685234/preproc/ctags_target_for_gcc_minus_e.cpp
    /home/corbett/arduino-1.8.12/tools-builder/ctags/5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /tmp/arduino_build_685234/preproc/ctags_target_for_gcc_minus_e.cpp
    Compiling sketch...
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/precompile_helper /home/corbett/arduino-1.8.12/hardware/teensy/avr/cores/teensy3 /tmp/arduino_build_685234 /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-g++ -x c++-header -Os --specs=nano.specs -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti -mthumb -mcpu=cortex-m0plus -fsingle-precision-constant -D__MKL26Z64__ -DTEENSYDUINO=152 -DARDUINO=10812 -DARDUINO_TEENSYLC -DF_CPU=48000000 -DUSB_SERIAL_HID -DLAYOUT_US_ENGLISH -I/home/corbett/arduino-1.8.12/hardware/teensy/avr/cores/teensy3 /tmp/arduino_build_685234/pch/Arduino.h -o /tmp/arduino_build_685234/pch/Arduino.h.gch
    Using previously compiled file: /tmp/arduino_build_685234/pch/Arduino.h.gch
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-g++ -c -Os --specs=nano.specs -g -Wall -ffunction-sections -fdata-sections -nostdlib -MMD -fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti -mthumb -mcpu=cortex-m0plus -fsingle-precision-constant -D__MKL26Z64__ -DTEENSYDUINO=152 -DARDUINO=10812 -DARDUINO_TEENSYLC -DF_CPU=48000000 -DUSB_SERIAL_HID -DLAYOUT_US_ENGLISH -I/tmp/arduino_build_685234/pch -I/home/corbett/arduino-1.8.12/hardware/teensy/avr/cores/teensy3 /tmp/arduino_build_685234/sketch/printf_bug.ino.cpp -o /tmp/arduino_build_685234/sketch/printf_bug.ino.cpp.o
    Compiling libraries...
    Compiling core...
    Using precompiled core: /tmp/arduino_cache_241954/core/core_5717911a4185f2db23123722f53848aa.a
    Linking everything together...
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-gcc -Os --specs=nano.specs -Wl,--gc-sections,--relax,--defsym=__rtc_localtime=1601486967 -T/home/corbett/arduino-1.8.12/hardware/teensy/avr/cores/teensy3/mkl26z64.ld -lstdc++ -mthumb -mcpu=cortex-m0plus -fsingle-precision-constant -o /tmp/arduino_build_685234/printf_bug.ino.elf /tmp/arduino_build_685234/sketch/printf_bug.ino.cpp.o /tmp/arduino_build_685234/../arduino_cache_241954/core/core_5717911a4185f2db23123722f53848aa.a -L/tmp/arduino_build_685234 -larm_cortexM0l_math -lm
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /tmp/arduino_build_685234/printf_bug.ino.elf /tmp/arduino_build_685234/printf_bug.ino.eep
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-objcopy -O ihex -R .eeprom /tmp/arduino_build_685234/printf_bug.ino.elf /tmp/arduino_build_685234/printf_bug.ino.hex
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/stdout_redirect /tmp/arduino_build_685234/printf_bug.ino.lst /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-objdump -d -S -C /tmp/arduino_build_685234/printf_bug.ino.elf
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/stdout_redirect /tmp/arduino_build_685234/printf_bug.ino.sym /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-objdump -t -C /tmp/arduino_build_685234/printf_bug.ino.elf
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/teensy_post_compile -file=printf_bug.ino -path=/tmp/arduino_build_685234 -tools=/home/corbett/arduino-1.8.12/hardware/teensy/../tools/ -board=TEENSYLC
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/arm/bin/arm-none-eabi-size -A /tmp/arduino_build_685234/printf_bug.ino.elf
    Sketch uses 17804 bytes (28%) of program storage space. Maximum is 63488 bytes.
    Global variables use 4092 bytes (49%) of dynamic memory, leaving 4100 bytes for local variables. Maximum is 8192 bytes.
    /home/corbett/arduino-1.8.12/hardware/teensy/../tools/teensy_post_compile -file=printf_bug.ino -path=/tmp/arduino_build_685234 -tools=/home/corbett/arduino-1.8.12/hardware/teensy/../tools -board=TEENSYLC -reboot -port=/dev/ttyACM0 -portlabel=/dev/ttyACM0 -portprotocol=serial

  3. #3
    Senior Member pictographer's Avatar
    Join Date
    May 2013
    Location
    San Jose, CA
    Posts
    681
    Tried Paul's magic trick from https://forum.pjrc.com/threads/27827...ll=1#post65321 but no joy.

  4. #4
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,593
    Re: lightweight printf

    You might grab the ee_printf() from Paul's CoreMark (which works on LC)
    https://github.com/PaulStoffregen/CoreMark

    another ee_printf variation that works on LC from Arduino Zero in attached zip
    lcpf.zip
    Last edited by manitou; 10-06-2020 at 09:02 AM.

  5. #5
    Senior Member pictographer's Avatar
    Join Date
    May 2013
    Location
    San Jose, CA
    Posts
    681
    Thanks, manitou!

    Since my needs are modest, I'm getting by with Serial.println() which does print floats okay. Was reporting the bug in case there was interest in fixing it. I mean, I can understand not supporting floating point due to the code bloat, but a printf implementation that prints memory garbage or crashes with the %f specifier isn't great.

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,046
    Quote Originally Posted by capricorn one View Post
    I know the floating point printf requires a lot of space, but I know it's less than 30K, would be nice to be able to add it while still optimizing the rest of the code for smallest. Anyone know how to do that?
    Edit {Arduino}/hardware/teensy/avr/boards.txt.

    On Windows, the default Arduino location is C:/Program Files (x86)/Arduino. On Macintosh, control-click Arduino and "Show Package Contents", then look for "hardware" inside Contents/Java.

    Find this line:

    Code:
    teensyLC.menu.opt.osstd.build.flags.optimize=-Os --specs=nano.specs
    Delete "--specs=nano.specs", so it looks like this:

    Code:
    teensyLC.menu.opt.osstd.build.flags.optimize=-Os
    You'll need to restart Arduino for your change to take effect. You will get printf which supports floats, and the rest of your code will be compiled with size optimization. But I suspect you won't be so happy with how much code space printf and the non-nano version of the C library consumes.

  7. #7
    Senior Member pictographer's Avatar
    Join Date
    May 2013
    Location
    San Jose, CA
    Posts
    681
    I edited boards.txt and restarted arduino. Haven't been able to make it work. It appears the changes to boards.txt didn't take effect.

    Code:
    teensyLC.menu.opt.osstd=Smallest Code
    teensyLC.menu.opt.osstd.build.flags.optimize=-Os
    teensyLC.menu.opt.osstd.build.flags.ldspecs=
    • Ubuntu 20.04.1 LTS
    • Teensy LC
    • Serial + Mouse + Keyboard + Joystick
    • 48 MHz
    • Smallest Code


    The code

    Code:
    void setup() {  while (!Serial && millis() < 2000) ;
      float pi = 3.1415926;
      Serial.printf("Printing Pi\n");
      Serial.print("Using Serial.print: ");
      Serial.print(pi, 4);
      Serial.println();
      Serial.printf("Using Serial.printf: %f\n", pi);
    }
    
    
    void loop() {}
    The output

    Code:
    Printing Pi
    Using Serial.print: 3.1416
    Using Serial.printf: 
    Float: 
    ⸮⸮⸮⸮ ⸮J ⸮ ⸮ !X ⸮ ⸮J$  ⸮ $ X J⸮ ⸮OJ0⸮⸮⸮⸮⸮  ⸮ J⸮⸮⸮⸮⸮⸮X ⸮⸮⸮ ⸮LT U⸮ \ ⸮ @⸮⸮⸮⸮   ⸮⸮⸮⸮⸮ @B⸮⸮⸮⸮⸮⸮⸮⸮ ⸮ ⸮@B ⸮⸮⸮⸮⸮⸮⸮}⸮D
    E⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮o⸮⸮⸮⸮⸮' ⸮ @B⸮ @B⸮⸮B⸮⸮⸮⸮⸮⸮ ⸮ o ⸮⸮⸮⸮⸮⸮o⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮ ⸮⸮⸮⸮⸮⸮:⸮@⸮ 4 8 ⸮⸮⸮⸮58 A8 ⸮ ⸮⸮@@⸮!    @E⸮⸮
    I'll try upgrading arduino and teensyduino to the latest.

    When the user doesn't edit boards.txt, I still think printf("%f", pi) shouldn't print garbage. If it's not possible to generate a compiler error or runtime error, it should at least be possible to make %f, %e, and %g print the literals f, e, and g, similar to other undefined format specifiers. This said, I have a workaround and this isn't an important bug.

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,046
    Try turning on verbose output while compiling in File > Preferences. That will show you the full compiler commands Arduino is running. Then you can easily see whether it still has "--specs=nano.specs" in the command.

    Maybe try a full search of your computer for boards.txt. Perhaps you have more than 1 copy of Arduino installed on your machine?

  9. #9
    Senior Member pictographer's Avatar
    Join Date
    May 2013
    Location
    San Jose, CA
    Posts
    681
    Thanks, Paul.

    I did search for other copies of boards.txt and none of the others mentioned the Teensy LC. Haven't yet tried updating Arduino and Teensyduino. Verbose output still includes nano.specs, but maybe I missed something. I searched under /usr and /home.

    I'll report back later after I have a chance to upgrade.

  10. #10
    Senior Member pictographer's Avatar
    Join Date
    May 2013
    Location
    San Jose, CA
    Posts
    681
    I did have a second copy of arduino-1.8.12. When I sorted that and upgraded to Arduino 1.8.13 and Teensyduino 1.53, I was able to remove nano.spec, but on a Teensy LC,
    Code:
    Serial.printf("Using Serial.printf: %f\n", pi);
    still prints garbage from memory or crashes the Teensy.

  11. #11
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,887

    Cool

    FWIW, I've written a sketch that can measure power output, that I'm using to measure how much power is used by my Olympus and Panasonic cameras with external power under some circumstances. At the moment, I'm using a Teensy 4.0 mounted in an Adafruit Teensy -> Feather adapter, and I'm using an Adafruit featherwing display (SH110X) and an Adafruit featherwing INA219 power monitor.

    The *printf floating point support won't work in the LC as you have discovered. In addition, if I used the space optimization options (-Os) for the Teensys or I used a non-Teensy feather microprocessor the library doesn't support this either.

    So, I wrote this simple minded function to print floating point numbers to a string, that can then be printed. It relies on the fact that with power monitoring, 12 volts/2 amps/24 watts is as high as I will typically go, and I'm only interested in 1-3 digits of accuracy after the decimal point:

    Code:
    static const int	BUFFER_SIZE		= 40;
    static const unsigned	MAX_COUNTER		= 100;
    static unsigned int	display_counter		= MAX_COUNTER;
    
    // prevent compiler from optimizing sprintf test
    volatile float		ten			= 10.0f;
    
    // Convert a floating point number to a string with a %<m>.<n>f format.  Not all
    // versions of sprintf support floating point, so on the first call test to see
    // if it works, and if we don't get the expected result, do the conversion in
    // an alternate fashion.  This function is optimized for the range of values we
    // expect to see with the power meter.
    //
    // On the Teensy, if you optimize for space, a smaller library is used that
    // does not do have %f, %g, etc. formats.
    
    char *
    float_to_string (float number, char *buffer, int fract)
    {
      static bool first_time	= true;
      static bool sprintf_works;
    
      if (first_time) {
        first_time = false;
        strcpy (buffer, "no results");
        sprintf (buffer, "%6.3f", ten);
        sprintf_works = (strcmp (buffer, "10.000") == 0);
        if (!sprintf_works)
          Serial.printf ("sprintf does not work for floating point, '%s'\n", buffer);
      }
    
      if (sprintf_works)
        sprintf (buffer, "%*.*f", fract + 3, fract, number);
    
      else {
        bool negative	= (number < 0.0f);
        float number2	= fabs (number);
    
        if (fract == 0) {
          number2 += 0.5f;
          sprintf (buffer, "%2d.", (int) (negative ? -number2 : number2));
    
        } else if (fract == 1) {
          int number_x10	= (int) ((number2 * 10.0f) + 0.5f);
          int number_main	= number_x10 / 10;
          int number_fract	= number_x10 % 10;
    
          sprintf (buffer,
    	       "%2d.%c",
    	       negative ? -number_main : number_main,
    	       number_fract + '0');
    
        } else if (fract == 2) {
          int  number_x100	= (int) ((fabsf (number) * 100.0f) + 0.5f);
          int  number_main	= number_x100 / 100L;
          int  number_fract	= number_x100 % 100L;
    
          sprintf (buffer,
    	       "%2d.%c%c",
    	       negative ? -number_main : number_main,
    	       ((number_fract / 10)  % 10) + '0',
    	       ((number_fract / 1)   % 10) + '0');
    
        } else {
          int  number_x1000	= (int) ((fabsf (number) * 1000.0f) + 0.5f);
          int  number_main	= number_x1000 / 1000L;
          int  number_fract	= number_x1000 % 1000L;
    
          sprintf (buffer,
    	       "%2d.%c%c%c",
    	       negative ? -number_main : number_main,
    	       ((number_fract / 100) % 10) + '0',
    	       ((number_fract / 10)  % 10) + '0',
    	       ((number_fract / 1)   % 10) + '0');
        }
      }
    
      return buffer;
    }
    
    
    // Get power values each time, but only update the display every so often
    void
    update_power_display (void)
    {
      // Read voltage and current from INA219.
      float shuntvoltage	= ina219.getShuntVoltage_mV () / 1000.0f;
      float busvoltage	= ina219.getBusVoltage_V ();
      float amps		= ina219.getCurrent_mA () / 1000.0f;
    
      // Compute load voltage, power, and milliamp-hours.
      float volts		= busvoltage + shuntvoltage;
      float watts		= volts * amps;
    
      max_volts = fmaxf (volts, max_volts);
      max_amps  = fmaxf (amps,  max_amps);
      max_watts = fmaxf (watts, max_watts);
    
      // Only update the display every 1/2 second
      if (++display_counter >= MAX_COUNTER) {
        display_counter = 0;
    
        char volts_output [BUFFER_SIZE];
        char amps_output  [BUFFER_SIZE];
        char watts_output [BUFFER_SIZE];
        char float_buffer1[BUFFER_SIZE];
        char float_buffer2[BUFFER_SIZE];
    
        sprintf (volts_output,
    	     "V: %s max: %s",
    	     float_to_string (volts,     float_buffer1, 3),
    	     float_to_string (max_volts, float_buffer2, 3));
    
        sprintf (amps_output,
    	     "A: %s max: %s",
    	     float_to_string (amps,     float_buffer1, 3),
    	     float_to_string (max_amps, float_buffer2, 3));
    
        sprintf (watts_output,
    	     "W: %s max: %s",
    	     float_to_string (watts,     float_buffer1, 3),
    	     float_to_string (max_watts, float_buffer2, 3));
    
        Serial.printf ("%s, %s, %s\n",
    		   volts_output,
    		   amps_output,
    		   watts_output);
    
        display.clearDisplay ();
        display.setCursor (0, 0);
    
        display.println (volts_output);
        display.println (amps_output);
        display.print   (watts_output);
        display.display ();
      }
    }

Posting Permissions

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