Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

printf and float rhapsody (aka, yet another printf and floating topic)

MotooTanaka
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

Hi,

Although I'm relatively new here, I've already seen a plenty of questions

about how to print a float value and/or using printf(), including myself.

For a small MCU such as PSoC 4, using a float, especially "%f" format is an expensive operation.

So not providing printf() nor "%f" for default seems to be a reasonable decision for PSoC 4.

But for those who have been grown with Unix/Linux and/or Windows absence of those seem to be critical.

This reminds me the days of my early C language study when BDS-C was the only choice 😜

Anyway, hoping that following memo can be a reference for such questions I'm writing this.

To print out a floating value with PSoC 4, I think there are (at least) 4 methods.

I'm trying to show them in order of cost, which is memory/CPU usage as well as steps

required to implement the method.

  (1) Using UART_UartPutString and sprintf with only "%d"

  (2) Using UART_UartPutString and sprintf with "%f"

  (3) Using iprintf with only "%d"

  (4) Using printf with "%f"

Following are my sample trials.

(1) Using UART_UartPutString() and "%d"

(1.1) if the f_value is always equals to 0.0 or greater

sprintf(str, "%d.%02d", (int)(f_value), ((int)(f_value * 100))%100) ;

UART_UartPutString(str) ;

(1.2) if you want to round the f_value

sprintf(str, "%d.%02d", (int)(f_value + 0.005), ((int)(f_value * 100 + 0.5))%100) ;

UART_UartPutString(str) ;

(1.3) if the value can be negative

char sign = ' ' ;

if (f_value < 0.0) {

   sign = '-' ;

}

sprintf(str, "%c%d.%02d", sign, (int)(f_value + 0.005), ((int)(f_value * 100 + 0.5))%100) ;

UART_UartPutString(str) ;

002_UART_UartPutString_d.JPG

(2) Using UART_UartPutString() and "%f"

In the source code you can print f_value by

sprintf(str, "%f", f_value) ;

UART_UartPutString(str) ;

But to achieve this we need following 2 steps.

(2.1) In the Project > Build Settings > Linker > General

Set "User newlib-nano Float Formatting" as "True"

000-Use_newlib_nano_Float_Formatting.JPG

(2.2) Expand the heap

Project > Design Wide Resources > System

Heap Size (byte) 0x80 -> 0x200 (value may vary depending on your requirement)

001-Heap_0x200.JPG

003_UART_UartPutString_f.JPG

(3) Using iprintf with "%d"

In the source code you can print f_value by

    iprintf("%d.%02d\r\n", (int)f_value, ((int)(f_value * 100))%100) ;

(3.1) implement _write() for your UART

int _write(int file, char *ptr, int len)

{

    int i ;

    file = file ;

    for (i = 0; i < len ; i++ ) {

        UART_UartPutChar(*ptr++) ;

    }

    return len ;

}

(3.2) expand heap (may be required)

004_iprintf.JPG

(4) Using printf() with "%f"

In the source code you can print f_value by

    printf("%f\r\n", f_value) ;

(4.1)  implement _write() for your UART

int _write(int file, char *ptr, int len)

{

    int i ;

    file = file ;

    for (i = 0; i < len ; i++ ) {

        UART_UartPutChar(*ptr++) ;

    }

    return len ;

}

(4.2) In the Project > Build Settings > Linker > General

Set "User newlib-nano Float Formatting" as "True"

Please refer to (2.2)

(4.2) Expand the heap

Project > Design Wide Rerouces > System

Heap Size (byte) 0x80 -> 0x400

Please refer to (2.3)

004_printf.JPG

Attached are my sample programs for CY8CKIT-044.

moto

0 Likes
2 Replies
Vasanth
Moderator
Moderator
Moderator
250 sign-ins 500 solutions authored First question asked

Hello Moto san,

Such an informative post ! Thanks for your contribution to the community.

Best Regards,
VRS

0 Likes
MotooTanaka
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

OOPS!

For (1.3) one line was missing.

In the attached project it was OK, though.

(1.3) if the value can be negative

char sign = ' ' ;

if (f_value < 0.0) {

   sign = '-' ;

   f_value = -f_value ; // <-- this line was missing!

}

moto

0 Likes