Skip to content

make foc_utils functions WEAK #262

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

Merged
merged 2 commits into from
Mar 22, 2023

Conversation

runger1101001
Copy link
Member

A change to enable alternative implementations of _sin() and _cos():

  • make these functions (and also normalizeAngle() and _sqrtApprox() ) weakly bound, so users can easily supply their own implementations
  • move the LUT array to be a static variable declared inside the function. The intent is that it gets compiled away when the WEAKly bound function isn't bound.

Tested this so far on STM32G4, where it has no impact on performance (none is expected since these are linker level things), and seems to work as expected in terms of the array: if I supply a different implementation of _sin() that just calls stdlib, the program size is 500 bytes smaller.

@askuric
Copy link
Member

askuric commented Mar 22, 2023

Makes sense, I like it. And would you be able to implement these functions in the arduino sketch?

@runger1101001
Copy link
Member Author

Yeah, in any cpp file that is part of the compile. But people can put them right in their sketch. I'm thinking of including an example also.

So if its ok, then I will merge this :-)

Then next I think we maybe have an optimised _sin() function - a little faster, a little more accurate and with built-in normalisation of the angle. I'm just testing it on various architectures. But I'll make a separate PR for you to examine when its ready.

@runger1101001 runger1101001 merged commit e72db3f into simplefoc:dev Mar 22, 2023
@FFiot
Copy link

FFiot commented Mar 26, 2023

What do you think of these simple codes?
https://github.com/FFiot/FF_FOC/tree/main/simpleFOC

@runger1101001
Copy link
Member Author

Hi @FFiot ,

Thank you for pointing this out!

I have tested it, and on the STM32G474 the arm_sin_f32 function is around 40-50% slower than the lookup table version we have. But it is more accurate than the lookup table version. It is considerably faster than the CORDIC for a single operation, but also a bit less accurate than the CORDIC.

It's certainly something people on ARM MCUs can consider using.

@runger1101001
Copy link
Member Author

For anyone interested here are my current timings on a STM32G474:

Timing CORDIC vs stdlib sin vs SimpleFOC Sine calculations...

CORDIC:
CORDIC Time (us) for 3217 steps: 6572
Result: 2048.00

SimpleFOC _sin:
SimpleFOC _sin time (us) for 3217 steps: 734
Result: 2048.00

stdlib sin:
stdlib sin time (us) for 3217 steps: 2714
Result: 2048.00

Deku sin:
Deku sin time (us) for 3217 steps: 793
Result: 2047.94

SimpleFOC sin + normalizeAngle:
SimpleFOC + normalizeAngle time (us) for 3217 steps: 2958
Result: 2048.00

Float257 Sine:
Float257 Sine time (us) for 3217 steps: 718
Result: 2048.00

Deku257 Sine:
Deku257 Sine time (us) for 3217 steps: 681
Result: 2048.00

Deku129 Sine:
Deku129 Sine time (us) for 3217 steps: 736
Result: 2047.99

Deku129i Sine:
Deku129i Sine time (us) for 3217 steps: 747
Result: 2047.93

ARM Sine:
ARM Sine time (us) for 3217 steps: 1099
Result: 2047.97

Comparing accuracy...
RMS difference between CORDIC and stdlib: 0.00000046
RMS difference between SimpleFOC and stdlib: 0.00125253
RMS difference between Deku256 Sine and stdlib: 0.00125757
RMS difference between Float Sine and stdlib: 0.00125250
RMS difference between Deku257 Sine and stdlib: 0.00125253
RMS difference between Deku129 Sine and stdlib: 0.00250501
RMS difference between Deku129i Sine and stdlib: 0.00003220
RMS difference between ARM Sine and stdlib: 0.00000971
Test complete.

@askuric
Copy link
Member

askuric commented Mar 27, 2023

Awesome overview @runger1101001,

I'd just like to add that when I wrote the _sin function I've verified that the error is under 0.001 radians against standard sin function.
However, this error can be greatly improved by by using a bigger more precise lookup table.

@FFiot
Copy link

FFiot commented May 17, 2023

Compare on stm32G431CBU6。
Function arm_sin_cos_f32(angle, &_sin, &_cos) used 272 tickets, input in degrees and output 2 values.
CORDIC used 172 tickets. Include input normalize and change to qint31, outputs change to float.
CORDIC is good at large volumes of data processing with DMA.

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

Successfully merging this pull request may close these issues.

3 participants