Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

basic example uses analogWrite(outputpin,DOUBLE) ! #129

Open
StefanL38 opened this issue Jan 4, 2023 · 6 comments
Open

basic example uses analogWrite(outputpin,DOUBLE) ! #129

StefanL38 opened this issue Jan 4, 2023 · 6 comments

Comments

@StefanL38
Copy link

Hi everybody,

the example
https://github.com/br3ttb/Arduino-PID-Library/blob/master/examples/PID_Basic/PID_Basic.ino
defines output as double (=double-precision floating-point)

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

and then uses this floating-point-variable in analogwrite

analogWrite(PIN_OUTPUT, Output);

that is a BIG BUG !

@JacobChrist
Copy link

I'm curious as to what problem this causing? Most of the time analogWrite is not better than 12 bits and a single precision float has 23 bits of mantissa.

@StefanL38
Copy link
Author

The representation of a float is totally different than the representation of an integer
image

https://forum.arduino.cc/t/how-to-covert-4-bytes-to-float/612320
How can this representation ever work with a function that expects an integer??

@ottobonn
Copy link

ottobonn commented Jan 5, 2023

When you pass a floating point variable as a function argument where the function expects an integer, the compiler will automatically promote the float to an integer as if you had assigned a float to an integer variable. You can find details here, section 6.5.2.2 paragraph 7: https://stackoverflow.com/questions/1255775/default-argument-promotions-in-c-function-calls

When you assign a float to an integer variable in C, the result is that the fractional part of the float is discarded (truncated), so the number is rounded down. If that truncated result is too large to be represented by the integer it's being assigned to, the result is undefined behavior, which generally means it depends on the compiler. https://learn.microsoft.com/en-us/cpp/c-language/conversions-from-floating-point-types?view=msvc-170

In this sketch, if we assume the values of the float don't get larger than the integer type can represent, the result of the type conversion is just that we discard the fractional part of the value when writing it to the pin.

@JacobChrist
Copy link

JacobChrist commented Jan 5, 2023

Another way to put what ottobonn is saying is that the compiler automatically type casts the float to an int when passed to the function. So the effective code is:

    analogWrite(PIN_OUTPUT, (int)Output);

@JacobChrist
Copy link

@StefanL38 My original question to you was "I'm curious as to what problem this causing?". Because a float or a double can be much larger or smaller than what an int can hold, so when it is converted to an int there could be an issue. But I suspect that you haven't tried to code because I know it worked for me the last time I tried it.

I do understand why your confused. But to get the bits to align the and they way your thinking you would actually need to do some funny casting, maybe something like this:

int i = *((int *)&Output);

The above code is not tested, but this would probably line up all the float bit such that they would not make sense as an integer. But this is good to think about since if you want to transmit a float over a serial line you can convert it to an integer, then back.

float f = *((float *)&i); 

@br3ttb
Copy link
Owner

br3ttb commented Jan 6, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants