Hi,
Im 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 - lets 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:
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)??
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
Im 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 - lets 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:
Code:
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<LENGTH(atan_table); i++){
if(y < 0){
//Rotate counter-clockwise
x_new = x - (y >> i);
y_new = y + (x >> i);
angle = angle - atan_table[i];
}
else{
//Rotate clockwise
x_new = x + (y >> i);
y_new = y - (x >> i);
angle = angle + atan_table[i];
}
x = x_new;
y = y_new;
}
// End of CORDIC routine
return angle/cordic_scale;//local_cordic2bitwidth(angle);
}
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)??
Code:
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<LENGTH(atan_table); i++){
if( desired_angle > angle){
// Rotate counter-clockwise
x_new = x - (y >> i);
y_new = y + (x >> i);
angle = angle + atan_table[i];
}
else{
// Rotate clockwise
x_new = x + (y >> i);
y_new = y - (x >> i);
angle = angle - atan_table[i];
}
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
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