Decimal number in FreeRTOS

andrefeliciano wrote on Sunday, May 13, 2018:

Hi,

It may sound like a beast question. What kind of variable to represent decimal number?
I did not find it on the website www.freertos.org and in the book “Mastering the …”

heinbali01 wrote on Sunday, May 13, 2018:

What kind of variable to represent decimal number?

Isn’t this more like a general C question?

The simple answer would be that it should be big enough to hold the maximum value.
Also decide if the variable becomes signed or unsigned. Can it become negative? If it can, you must use a signed type. If it is always positive, you may still use a signed type, depending on the width needed.
You can decide to use a char, an short, an int or a long ( or the unsigned versions of these ).

Note that when you mix the usage of `char`s, `short`s and `int`s ( often seen in small embedded projects ), the compiler needs to insert lots of extra code to make things working.

Function parameters are often passed in single registers, there is no need to downscale the size of parameters to save memory:

``````    /* Calling the first function may result in more code
than calling the second function: */
void foo(char count);
/* Here 'count' will get the width of a CPU register. */
void foo(int count);
``````

Also care must be taken when signed-ness is mixed: the outcome of the expression `if( value_1 > value_2 )` depends on the the values and on the signed-ness of the two variables. You would ask for trouble if you compare signed with unsigned values.

In practice, the int type has many advantages: it normally has the size of a CPU register ( 16, 32, or 64 bits ), and therefore, code using ( unsigned ) `int` is very efficient. If all your variables can be stored in `int`s, you can keep your code really simple. The compiler won’t have to insert any (hidden) transformation of signed-ness or width.

Types with a known width:

``````#include <stdint.h>

/* defining types width a known width: */

int8_t
int16_t
int32_t
uint8_t
uint16_t
uint32_t
``````

Within the +TCP library, you will see an extensive usage of `uint32_t`, because that corresponds to the fields in the Internet packets.

And finally, consider using of `size_t` as often as applicable.

andrefeliciano wrote on Sunday, May 13, 2018:

Hein thanks.

The same program works normal in C, but when I implement in FreeRTOS and I do a simple division operating with two INT that is a FLOAT the value is lost.

I searched fast and did not find the type that replaces FLOAT in FreeRTOS.

richard_damon wrote on Sunday, May 13, 2018:

FreeRTOS uses the same C (or C++ if you use that) language, so the types are exactly the same. There is an issue with floating point types on some processors that you need to configure it as many applications don’t use floating point, and saving floating point state can be expensive, especially if it isn’t being used. Mentioning the processor could help someone to give advice if anything needs to be done to handle floating point on that machine.

heinbali01 wrote on Sunday, May 13, 2018:

When you wrote “decimal number”, I thought of integer numbers.

I do a simple division operating with two INT that is a FLOAT the value is lost

It would be helpful if you can show some sample code.

andrefeliciano wrote on Sunday, May 13, 2018:

Interesting. The microcontroller is the ESP8266 that comes installed on the nodeMCU

andrefeliciano wrote on Sunday, May 13, 2018:

Sorry, my English is not good

``````void adc_task (void * pvParameters) // reading the ACS712 sensor
{
float voltage = 0;
double current = 0;
double ACSoffset = 515;
int mVporAmp = 66;

while (1)
{
os_printf ("Value of the converter =% d \ n", valueLoad);

voltage = ((valueLoad/1024)*1030;             // voltage at the input of the ESP12
os_printf ("Voltage value =% d \ n", voltage);

current = ((voltage - ACSoffset) / mVporAmp);     // current measured by sensor
os_printf ("Current =% d mA \ n", current);

}
}
``````

If I put INT as the variables “voltage” and “current” in “os_printf” appears as “0”. If I put “FLOAT” appears wrong values.

rtel wrote on Sunday, May 13, 2018:

I think this is only a FreeRTOS question if the behaviour is different
when performing the calculation before the scheduler has started (i.e.
from main()) and after the scheduler has started.

I’ve never known there to be a difference with integer usage, but there
can be a difference in floating point usage if either:

1. The FreeRTOS port you are using does not give each FreeRTOS task
unless the application code explicitly requests one. This is not the
normal case though.

2. There is a stack alignment issue inside the FreeRTOS task. That was
once a problem with ARM ports, but fixed a very long time ago by
increasing the stack alignment to 8 (which is what it should have been),
and more recently on PIC32MZ ports, but that has been fixed too.

rtel wrote on Sunday, May 13, 2018:

Just read further up the thread that this is an ESP32 - I’m afraid that
is a third party Tensilica port so I don’t know how it handles floating
point or stack alignment.

richard_damon wrote on Sunday, May 13, 2018:

This looks like a fundamental misunderstanding of C.

You have all sorts of extra spaces, but %d is a format that need to be given an int value (not a float), to print a float value, you generally would use a %f format. Sending a float value to the %d format will give you strange numbers.

In C, when you divide and integer by another interger, the fractional part will be discarded, so the expression (valueLoad/1024)*1030 will give you possibe values of 0, 1030, 2060, 3090 and so on.

if you did instead valueLoad * 1030L ./ 1024 you will get closer to the value you expect (the L is added to the end of the number to make sure the multiplication doesn’t overlow the range of an int).

I would actually tend to use(valueLoad * 1030L + 512)/1024 to round the value if I knew that valueLoad was always positive.

andrefeliciano wrote on Tuesday, May 15, 2018:

Richard,

1. Could it be that the FreeRTOS I’m using do not support the floating point?

2. Do you have any link or website explaining the stack alignment?

andrefeliciano wrote on Tuesday, May 15, 2018:

Richard,

Some reason FreeRTOS does not accept % f ou %. 2f. For example a simple task:

``````void adc_task (void *pvParameters)
{
float voltage = 0.52;
float current = 0.64;

while (1)
{
os_printf ("Voltage value = %.2f \n", voltage);
os_printf ("Current value = %.2f \n", current);

}
}
``````

The result in the Serial Terminal is

Voltage Value = 2f
Current value = 2f

richard_damon wrote on Tuesday, May 15, 2018:

That says that os_printf doesn’t support floating point numbers. os_printf isn’t part of standard C or FreeRTOS (sounds like a vendor os wrapper function), These sorts of functions often reduce their size by not supporting floating point, as very many embedded application don’t need floating point (or at least not printf support for them).

andrefeliciano wrote on Tuesday, May 15, 2018:

Unfortunately. Do you have any tips to solve this problem?

richard_damon wrote on Tuesday, May 15, 2018:

Since you are using a 3rd party port, and not one in the standard distribution, it is unclear if the port will actually support (or what is needed to support) tasks using floating point. That is the first issue, and you will need to read the documentation (or ask the supplier of it) about that.

Second, since os_printf doesn’t seem to support %f, you would need to find a function that does. sprintf in the standard C library could be usable (if provided).

The other option, like I mentioned earlier, is by understanding how integer math works in C, you can often replace floating point numbers (with reasonably know ranges) with fixed point math. This is actually what I find works best in many cases.

andrefeliciano wrote on Thursday, May 17, 2018:

In Kolban’s book on ESP8266 it says that os_printf does not accept% f for FLOAT and DOUBLE.

I’ll go find some other library.

thank you all for the support