SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
foc_utils.cpp
Go to the documentation of this file.
1#include "foc_utils.h"
2
3
4// function approximating the sine calculation by using fixed size array
5// uses a 65 element lookup table and interpolation
6// thanks to @dekutree for his work on optimizing this
7__attribute__((weak)) float _sin(float a){
8 // 16bit integer array for sine lookup. interpolation is used for better precision
9 // 16 bit precision on sine value, 8 bit fractional value for interpolation, 6bit LUT size
10 // resulting precision compared to stdlib sine is 0.00006480 (RMS difference in range -PI,PI for 3217 steps)
11 static uint16_t sine_array[65] = {0,804,1608,2411,3212,4011,4808,5602,6393,7180,7962,8740,9512,10279,11039,11793,12540,13279,14010,14733,15447,16151,16846,17531,18205,18868,19520,20160,20788,21403,22006,22595,23170,23732,24279,24812,25330,25833,26320,26791,27246,27684,28106,28511,28899,29269,29622,29957,30274,30572,30853,31114,31357,31581,31786,31972,32138,32286,32413,32522,32610,32679,32729,32758,32768};
12 int32_t t1, t2;
13 unsigned int i = (unsigned int)(a * (64*4*256.0f/_2PI));
14 int frac = i & 0xff;
15 i = (i >> 8) & 0xff;
16 if (i < 64) {
17 t1 = (int32_t)sine_array[i]; t2 = (int32_t)sine_array[i+1];
18 }
19 else if(i < 128) {
20 t1 = (int32_t)sine_array[128 - i]; t2 = (int32_t)sine_array[127 - i];
21 }
22 else if(i < 192) {
23 t1 = -(int32_t)sine_array[-128 + i]; t2 = -(int32_t)sine_array[-127 + i];
24 }
25 else {
26 t1 = -(int32_t)sine_array[256 - i]; t2 = -(int32_t)sine_array[255 - i];
27 }
28 return (1.0f/32768.0f) * (t1 + (((t2 - t1) * frac) >> 8));
29}
30
31// function approximating cosine calculation by using fixed size array
32// ~55us (float array)
33// ~56us (int array)
34// precision +-0.005
35// it has to receive an angle in between 0 and 2PI
36__attribute__((weak)) float _cos(float a){
37 float a_sin = a + _PI_2;
38 a_sin = a_sin > _2PI ? a_sin - _2PI : a_sin;
39 return _sin(a_sin);
40}
41
42
43__attribute__((weak)) void _sincos(float a, float* s, float* c){
44 *s = _sin(a);
45 *c = _cos(a);
46}
47
48// fast_atan2 based on https://math.stackexchange.com/a/1105038/81278
49// Via Odrive project
50// https://github.com/odriverobotics/ODrive/blob/master/Firmware/MotorControl/utils.cpp
51// This function is MIT licenced, copyright Oskar Weigl/Odrive Robotics
52// The origin for Odrive atan2 is public domain. Thanks to Odrive for making
53// it easy to borrow.
54__attribute__((weak)) float _atan2(float y, float x) {
55 // a := min (|x|, |y|) / max (|x|, |y|)
56 float abs_y = fabsf(y);
57 float abs_x = fabsf(x);
58 // inject FLT_MIN in denominator to avoid division by zero
59 float a = min(abs_x, abs_y) / (max(abs_x, abs_y));
60 // s := a * a
61 float s = a * a;
62 // r := ((-0.0464964749 * s + 0.15931422) * s - 0.327622764) * s * a + a
63 float r =
64 ((-0.0464964749f * s + 0.15931422f) * s - 0.327622764f) * s * a + a;
65 // if |y| > |x| then r := 1.57079637 - r
66 if (abs_y > abs_x) r = 1.57079637f - r;
67 // if x < 0 then r := 3.14159274 - r
68 if (x < 0.0f) r = 3.14159274f - r;
69 // if y < 0 then r := -r
70 if (y < 0.0f) r = -r;
71
72 return r;
73 }
74
75
76// normalizing radian angle to [0,2PI]
77__attribute__((weak)) float _normalizeAngle(float angle){
78 float a = fmod(angle, _2PI);
79 return a >= 0 ? a : (a + _2PI);
80}
81
82// Electrical angle calculation
83float _electricalAngle(float shaft_angle, int pole_pairs) {
84 return (shaft_angle * pole_pairs);
85}
86
87// square root approximation function using
88// https://reprap.org/forum/read.php?147,219210
89// https://en.wikipedia.org/wiki/Fast_inverse_square_root
90__attribute__((weak)) float _sqrtApprox(float number) {//low in fat
91 union {
92 float f;
93 uint32_t i;
94 } y = { .f = number };
95 y.i = 0x5f375a86 - ( y.i >> 1 );
96 return number * y.f;
97}
@ angle
Position/angle motion control.
Definition FOCMotor.h:52
__attribute__((weak)) float _sin(float a)
Definition foc_utils.cpp:7
float a
Definition foc_utils.cpp:59
float _electricalAngle(float shaft_angle, int pole_pairs)
Definition foc_utils.cpp:83
float * s
Definition foc_utils.cpp:43
float abs_x
Definition foc_utils.cpp:57
float float * c
Definition foc_utils.cpp:43
float r
Definition foc_utils.cpp:63
float x
Definition foc_utils.cpp:54
float _sqrtApprox(float value)
float _atan2(float y, float x)
float _sin(float a)
#define _2PI
Definition foc_utils.h:29
#define _PI_2
Definition foc_utils.h:27
float _normalizeAngle(float angle)
float _cos(float a)
void _sincos(float a, float *s, float *c)