Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] float calculations in #define

Status
Not open for further replies.

ashugtiwari

Full Member level 4
Joined
Dec 12, 2008
Messages
218
Helped
45
Reputation
90
Reaction score
44
Trophy points
1,308
Activity points
3,310
Hello All,
Im working on BLDC motor speed control project using MCU. So, i have declared some of #defines as follows:

#define RATED_SPEED 8500L
#define Vmax 9L
#define Vmotor 24L
#define Q12_MAX 4095L
#define SPEED_CONV 5000000L

#define SPEED_Vmax (int)((RATED_SPEED*Vmax/Vmotor)+100L)
#define COUNT_TO_SPEED (long)((SPEED_CONV*Q12_MAX)/SPEED_Vmax)

As, at compile time, all other formulae's are evaluated to their integer value but above two constants are resulting into float value. The first formula is giving an output of 3287.5 and next one is 6229084.2713720717979920900517189 when SPEED_Vmax is truncated to 3287.

So, when keeping these values directly into #define, my system and feedback control works just fine but when i use the formula's directly, the system feedback controls does not work correctly. Why is it happening? And is there a way i can directly use the formula and round these values, so that i can also use these values into other #defines? As far as i know compiler only does integer math. Im using MPLABX with XC8 compiler.

Any ideas? The project is confidential so i cannot share any more info, i hope this explains my question well.

Thanks for replies
Ashutosh
 

#define expressions aren't but macros evaluated as test strings in the C preprocessor. Behavioral differences might occur if the operator precedence becomes different than expected. All composite macros should get enclosing parantheses.

E.g. a leading type cast is not the operator with highest priority.

If this comment doesn't solve the issue, you need to show the expression where the problem occurs, together with all involved type specifications.

Of course you may also experience a compiler bug.
 
Hello FvM, thats for reply
As far as i know, the preprocessor is replaced by numbers during precompilation step i.e.
for eg.
int a, b;
b=27000;
a=COUNT_TO_SPEED/b;

so, in preprocessing step, the COUNT_TO_SPEED is replaced by formula and the contents of formula are replaced by numbers if they are constants. SO, when actual compilation happens, if the compiler sees something like this (300/100), it calculates the formula and substitutes 3 in code memory. In most of my constants this is happening except the one i have noted above. So, as in code snippet above shown, that is how im using COUNT_TO_SPEED in .c code file for calculation. But, actually, this #define constant seem not to be evaluated at compilation since the result of this computation is a floating point number which is not ending after decimal point. The result in above variable a is at ceiling of int range, hence im getting always 100% duty cycle and cannot vary the controlled variable. But im not completely sure of this...

Thats why i am looking for solution to this, if i can truncate or round this in some way?

Im not experiencing any compiler error BTW.
 

But, actually, this #define constant seem not to be evaluated at compilation since the result of this computation is a floating point number which is not ending after decimal point.
Where do you see this?

but above two constants are resulting into float value. The first formula is giving an output of 3287.5 and next one is 6229084.2713720717979920900517189
How can a constant "result" in a float value?
 
But, actually, this #define constant seem not to be evaluated at compilation since the result of this computation is a floating point number which is not ending after decimal point. The result in above variable a is at ceiling of int range, hence im getting always 100% duty cycle and cannot vary the controlled variable.

Both of the #defines, SPEED_Vmax and COUNT_TO_SPEED in the following #define:

Code:
#define SPEED_Vmax [COLOR="#FF0000"](int)[/COLOR]((RATED_SPEED*Vmax/Vmotor)+100L)
#define COUNT_TO_SPEED [COLOR="#FF0000"](long)[/COLOR]((SPEED_CONV*Q12_MAX)/SPEED_Vmax)

Are explicitly cast as integers, standard integer and long integer, respectfully.

Therefore, during the preprocessing phase the results of the #defines are integers, not floating point.

As COUNT_TO_SPEED is explicity cast as a long integer type and the left hand receiving variable, a, is defined as standard integer, during runtime evaluation of the following statement:

Code:
a=COUNT_TO_SPEED/b;

Results in the implicit conversion of the right hand result to a standard integer type, truncating the right hand result to fit within the standard integer type before being stored in variable a, a standard integer type.

BigDog
 
Thanks FvM and bigdogguru, ur comments actually made me think twice and solved the issue, the problem was in
#define COUNT_TO_SPEED ((SPEED_CONV*Q12_MAX)/SPEED_Vmax)
the term (SPEED_CONV*Q12_MAX)=5000000*4095 is crossing the 2^32 long value ceiling i.e. highest long value and so, it is making it Q32 max but, when i changed the above formula to
#define COUNT_TO_SPEED ((long)(SPEED_CONV/SPEED_Vmax)*Q12_MAX)
i.e. first 5000000/3287, then truncate it and multiply by 4095, so its not crossing the highest long value and the result in b variable is accurate as expected.

Thanks for ur helpful comments buddies :) , u rock
 

A possible workaround to avoid unexpected over- or underflow in constant expressions is to use float for constants. It will be automatically converted to the target data type on assignment.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top