Skip to content

Commit e3b903a

Browse files
committed
add alignment and cogging test
1 parent 3a59417 commit e3b903a

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <Arduino.h>
2+
#include <SimpleFOC.h>
3+
4+
BLDCMotor motor = BLDCMotor(9, 10, 11, 7);
5+
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);
6+
7+
8+
/**
9+
* This measures how closely sensor and electrical angle agree and how much your motor is affected by 'cogging'.
10+
* It can be used to investigate how much non linearity there is between what we set (electrical angle) and what we read (sensor angle)
11+
* This non linearity could be down to magnet placement, coil winding differences or simply that the magnetic field when travelling through a pole pair is not linear
12+
* An alignment error of ~10 degrees and cogging of ~4 degrees is normal for small gimbal.
13+
* The following article is an interesting read
14+
* https://hackaday.com/2016/02/23/anti-cogging-algorithm-brings-out-the-best-in-your-hobby-brushless-motors/
15+
*/
16+
void testAlignmentAndCogging(int direction) {
17+
18+
motor.setPhaseVoltage(motor.voltage_sensor_align, 0);
19+
20+
_delay(200);
21+
22+
float initialAngle = sensor.getAngle();
23+
24+
const int shaft_rotation = 720; // 720 deg test - useful to see repeating cog pattern
25+
int sample_count = int(shaft_rotation * motor.pole_pairs); // test every electrical degree
26+
27+
float stDevSum = 0;
28+
29+
float mean = 0.0;
30+
float prev_mean = 0.0;
31+
32+
33+
for (int i = 0; i < sample_count; i++) {
34+
35+
float electricAngle = (float) direction * i * motor.pole_pairs * shaft_rotation / sample_count;
36+
// move and wait
37+
motor.setPhaseVoltage(motor.voltage_sensor_align, electricAngle * PI / 180);
38+
_delay(5);
39+
40+
// measure
41+
float sensorAngle = (sensor.getAngle() - initialAngle) * 180 / PI;
42+
float sensorElectricAngle = sensorAngle * motor.pole_pairs;
43+
float electricAngleError = electricAngle - sensorElectricAngle;
44+
45+
// plot this - especially electricAngleError
46+
Serial.print(electricAngle);
47+
Serial.print("\t");
48+
Serial.print(sensorElectricAngle );
49+
Serial.print("\t");
50+
Serial.println(electricAngleError);
51+
52+
// use knuth standard deviation algorithm so that we don't need an array too big for an Uno
53+
prev_mean = mean;
54+
mean = mean + (electricAngleError-mean)/(i+1);
55+
stDevSum = stDevSum + (electricAngleError-mean)*(electricAngleError-prev_mean);
56+
57+
}
58+
59+
Serial.println();
60+
Serial.println("ALIGNMENT AND COGGING REPORT");
61+
Serial.println();
62+
Serial.print("Direction: ");
63+
Serial.println(direction);
64+
Serial.print("Mean error (alignment): ");
65+
Serial.print(mean);
66+
Serial.println(" deg (electrical)");
67+
Serial.print("Standard Deviation (cogging): ");
68+
Serial.print(sqrt(stDevSum/sample_count));
69+
Serial.println(" deg (electrical)");
70+
Serial.println();
71+
Serial.println("Plotting 3rd column of data (electricAngleError) will likely show sinusoidal cogging pattern with a frequency of 4xpole_pairs per rotation");
72+
Serial.println();
73+
74+
}
75+
76+
void setup() {
77+
78+
Serial.begin(115200);
79+
while (!Serial) ;
80+
81+
motor.voltage_power_supply = 9;
82+
motor.voltage_sensor_align = 3;
83+
motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
84+
motor.controller = ControlType::velocity;
85+
86+
sensor.init();
87+
motor.linkSensor(&sensor);
88+
89+
motor.useMonitoring(Serial);
90+
motor.init();
91+
motor.initFOC();
92+
93+
testAlignmentAndCogging(1);
94+
95+
motor.setPhaseVoltage(0, 0);
96+
Serial.println("Press any key to test in CCW direction");
97+
while (!Serial.available()) { }
98+
99+
testAlignmentAndCogging(-1);
100+
101+
Serial.println("Complete");
102+
103+
motor.setPhaseVoltage(0, 0);
104+
while (true) ; //do nothing;
105+
106+
}
107+
108+
109+
110+
111+
void loop() {
112+
113+
}

0 commit comments

Comments
 (0)