Closed runger1101001 closed 1 year ago
Makes sense, I like it. And would you be able to implement these functions in the arduino sketch?
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.
What do you think of these simple codes? https://github.com/FFiot/FF_FOC/tree/main/simpleFOC
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.
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.
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.
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.
A change to enable alternative implementations of
_sin()
and_cos()
: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.