Software CORDIC

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
hafnthom
Employee
Employee
Welcome! First question asked
Hi,

I’m working on an autocalibration algorithm for analog GMR angle sensor products.
I wanted to implement a (software-) cordic to calculate the angle out of the raw cos and sin values.
For orthogonality compensation I also have to calculate cos and sin components of the 45° and 135° angles.
And for some reason for small angles - let’s say 1° the sin and cos components are not right - compared to the math.h (double) functions.
As an input I have a 13bit angle 0-8191. (or -4095 (-4096) to 4095)

My atan2 cordic looks like following:

int local_cordic_atan2(int y, int x){
int angle = 0;
int x_new = 0;
int y_new = 0;

//Start of CORDIC routine
if( x < 0 ){
angle = ANGLE_180_DEE * cordic_scale;
x = -x;
y = -y;
}
else if( y < 0){
angle = ANGLE_360_DEE * cordic_scale;
}
for(int i = 0; i if(y < 0){
//Rotate counter-clockwise
x_new = x - (y >> i);
y_new = y + (x >> i);
angle = angle - atan_table;
}
else{
//Rotate clockwise
x_new = x + (y >> i);
y_new = y - (x >> i);
angle = angle + atan_table;
}
x = x_new;
y = y_new;
}
// End of CORDIC routine
return angle/cordic_scale;//local_cordic2bitwidth(angle);
}

with ANGLE_180_DEE = 4096 and ANGLE_360_DEE = 8192,
cordic_scale = 256
int atan_table[] = {262144,154753,81767, 41506, 20834, 10427, 5215, 2608, 1304, 652, 326, 163, 81, 41, 20};// for angle_bit values 0-8191 * cordic scle (256) for higher resolution
--> atan(1/2^0) = 45° = 1024LSB13 --> *265 (for higher resolution in cordic rotation) = 262144
--> atan(1/2^1) = 26.565 = 604LSB13 --> *256 = 154753
and so on...
The atan2 seems to work as expected - compared with math.h atan2

However the cordic for sin and cos calculation does not work for small angles ~1° (22LSB13)??

void local_cordic_sincos(int desired_angle, int *cordic_sin, int *cordic_cos){
int angle = 0;
int x = 0;
int y = 0;
int x_new = 0;
int y_new = 0;

//Start of CORDIC routine
y = 0;
x = 155;// cordic_scale * cordic_gain
if( desired_angle > ANGLE_90_DEE*cordic_scale){
angle = ANGLE_180_DEE*cordic_scale;
}
if( desired_angle > ANGLE_270_DEE*cordic_scale){
angle = ANGLE_360_DEE*cordic_scale;
}
for(int i = 0; i if( desired_angle > angle){
// Rotate counter-clockwise
x_new = x - (y >> i);
y_new = y + (x >> i);
angle = angle + atan_table;
}
else{
// Rotate clockwise
x_new = x + (y >> i);
y_new = y - (x >> i);
angle = angle - atan_table;
}
x = x_new;
y = y_new;
}
if((desired_angle > ANGLE_90_DEE*cordic_scale) && (desired_angle < ANGLE_270_DEE*cordic_scale)){
x = -x;
y = -y;
}
*cordic_cos = x;
*cordic_sin = y;
// End of CORDIC routine

with ANGLE_90_DEE = 2048 and ANGLE_270_DEE = 6144

If now the input angle equals 22LSB13 the ideal output would be cos = 255 and sin = 4.
But with the cordic routine the output is cos = 253 and sin = 7 ??? which will give me a total wrong compensation value!

I can change the starting value of x to a higher value but this does not affect the output.

Hopefully I described it in a way that someone of you understands it.
Does someone of you have an idea what could be wrong?

Now I wanted to test it with the park transform function of the MOTORLIB (as it is very similar).
I scaled the angle to match the input of this function (angle<<19?) and also changed the starting value of x to 155 (256*= 0.607252935)
But the output is the same?

If you need any further information for better understanding just let me know.

thanks in advance.

kind reagards
Thomas
0 Likes
2 Replies
Not applicable
Hi,
Is the input within the valid input range for the atan function?
0 Likes
Not applicable
Hi Thomas,

1. The (atan_table) seems to be using a 21bit representation for 360 degrees. Consider increasing the representation to 32 bit.
2. The arguments are using int. Consider to use int32 to improve the resolution.
3. The CORIDC Iteration used is 15 based on your table. In our MOTORLIB, we are also using 15 as the iteration, the maximum iteration allows is 23. For your code, you can also increase the iteration to get better accuracy.

Hopefully this helps.

Regards,
Daryl
0 Likes