Skip to content

Commit 84269cd

Browse files
committed
commander refactorred and separated motion control into a new callback
1 parent 34c0399 commit 84269cd

File tree

9 files changed

+564
-106
lines changed

9 files changed

+564
-106
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ Therefore this is an attempt to:
2222
<p class="heading">FUTURE RELEASE 📢: <span class="simple">Simple<span class="foc">FOC</span>library</span> v2.2.1 </p>
2323
<ul>
2424
<li>Sensor class init bugfix #121</li>
25-
<li>Added the new motion control interface to the commander- possible to set the position, velocity and torque target at once</li>
25+
<li>Added the new motion control interface to the commander
26+
<ul>
27+
<li>New target setting - possible to set the position, velocity and torque target at once</li>
28+
<li>Separated the motion control interface from full motor callback - only motion control and torque control type, enable disable and target setting</li>
29+
</ul>
2630
<li>NRF52 series mcus support by <a href="https://github.com/Polyphe">@Polyphe</a></li>
2731
<li>Voltage/current limit handling bugs #118</li>
2832
<li>Generic position and current sense classes - to implement a new sensor only implement one function</li>

examples/hardware_specific_examples/SimpleFOCShield/version_v2/single_full_control_example/single_full_control_example.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, A0, A2);
1717

1818
// commander communication instance
1919
Commander command = Commander(Serial);
20-
void doTarget(char* cmd){ command.scalar(&motor.target, cmd); }
20+
void doMotion(char* cmd){ command.motion(&motor, cmd); }
2121
// void doMotor(char* cmd){ command.motor(&motor, cmd); }
2222

2323
void setup() {
@@ -74,7 +74,7 @@ void setup() {
7474
motor.target = 2;
7575

7676
// subscribe motor to the commander
77-
command.add('T', doTarget, "target");
77+
command.add('T', doMotion, "motion control");
7878
// command.add('M', doMotor, "motor");
7979

8080
// Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/**
2+
* Utility arduino sketch which finds pole pair number of the motor
3+
*
4+
* To run it just set the correct pin numbers for the BLDC driver and encoder A and B channel as well as the encoder PPR value.
5+
*
6+
* The program will rotate your motor a specific amount and check how much it moved, and by doing a simple calculation calculate your pole pair number.
7+
* The pole pair number will be outputted to the serial terminal.
8+
*
9+
* If the pole pair number is well estimated your motor will start to spin in voltage mode with 2V target.
10+
*
11+
* If the code calculates negative pole pair number please invert your encoder A and B channel pins or motor connector.
12+
*
13+
* Try running this code several times to avoid statistical errors.
14+
* > But in general if your motor spins, you have a good pole pairs number.
15+
*/
16+
#include <SimpleFOC.h>
17+
18+
// BLDC motor instance
19+
BLDCMotor motor = BLDCMotor(10);
20+
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
21+
22+
// Encoder(int encA, int encB , int cpr, int index)
23+
Encoder encoder = Encoder(2, 3, 2048);
24+
// interrupt routine intialisation
25+
void doA(){encoder.handleA();}
26+
void doB(){encoder.handleB();}
27+
28+
// current sensor
29+
// shunt resistor value
30+
// gain value
31+
// pins phase A,B, (C optional)
32+
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50.0, A0, A2);
33+
34+
void setup() {
35+
36+
// initialise encoder hardware
37+
encoder.init();
38+
// hardware interrupt enable
39+
encoder.enableInterrupts(doA, doB);
40+
// link the motor to the sensor
41+
motor.linkSensor(&encoder);
42+
43+
// power supply voltage
44+
// default 12V
45+
driver.voltage_power_supply = 12;
46+
driver.init();
47+
motor.linkDriver(&driver);
48+
49+
// initialize motor
50+
motor.init();
51+
// monitoring port
52+
Serial.begin(115200);
53+
54+
// initialise the current sensing
55+
current_sense.init();
56+
57+
// pole pairs calculation routine
58+
Serial.println("Pole pairs (PP) estimator");
59+
Serial.println("-\n");
60+
61+
float pp_search_voltage = 4; // maximum power_supply_voltage/2
62+
float pp_search_angle = 8*M_PI; // search electrical angle to turn
63+
float pp_vel_limit = 1;
64+
65+
// move motor to the electrical angle 0
66+
motor.controller = MotionControlType::angle_openloop;
67+
motor.voltage_limit = pp_search_voltage;
68+
motor.velocity_limit = pp_vel_limit;
69+
motor.move(0);
70+
_delay(1000);
71+
72+
// move the motor slowly to the electrical angle pp_search_angle
73+
float a_max=0,b_max=0,c_max=0;
74+
while(motor_angle <= pp_search_angle){
75+
motor.move(pp_search_angle);
76+
PhaseCurrent_s c = current_sense.getPhaseCurrents();
77+
a_max = fabs(c.a) > a_max ? fabs(c.a) : a_max;
78+
b_max = fabs(c.b) > b_max ? fabs(c.b) : b_max;
79+
c_max = fabs(c.c) > c_max ? fabs(c.c) : c_max;
80+
}
81+
_delay(1000);
82+
83+
Serial.print(a_max);
84+
Serial.print("\t");
85+
Serial.print(b_max);
86+
Serial.print("\t");
87+
Serial.println(b_max);
88+
89+
return;
90+
// calculate the pole pair number
91+
int pp = round((pp_search_angle)/(angle_end-angle_begin));
92+
93+
Serial.print(F("Estimated PP : "));
94+
Serial.println(pp);
95+
Serial.println(F("PP = Electrical angle / Encoder angle "));
96+
Serial.print(pp_search_angle*180/M_PI);
97+
Serial.print("/");
98+
Serial.print((angle_end-angle_begin)*180/M_PI);
99+
Serial.print(" = ");
100+
Serial.println((pp_search_angle)/(angle_end-angle_begin));
101+
Serial.println();
102+
103+
104+
// a bit of monitoring the result
105+
if(pp <= 0 ){
106+
Serial.println(F("PP number cannot be negative"));
107+
Serial.println(F(" - Try changing the search_voltage value or motor/encoder configuration."));
108+
return;
109+
}else if(pp > 30){
110+
Serial.println(F("PP number very high, possible error."));
111+
}else{
112+
Serial.println(F("If PP is estimated well your motor should turn now!"));
113+
Serial.println(F(" - If it is not moving try to relaunch the program!"));
114+
Serial.println(F(" - You can also try to adjust the target voltage using serial terminal!"));
115+
}
116+
117+
118+
// set FOC loop to be used
119+
motor.controller = MotionControlType::torque;
120+
// set the pole pair number to the motor
121+
motor.pole_pairs = pp;
122+
//align encoder and start FOC
123+
motor.initFOC();
124+
_delay(1000);
125+
126+
Serial.println(F("\n Motor ready."));
127+
Serial.println(F("Set the target voltage using serial terminal:"));
128+
}
129+
130+
// uq voltage
131+
float target_voltage = 2;
132+
133+
void loop() {
134+
135+
// main FOC algorithm function
136+
// the faster you run this function the better
137+
// Arduino UNO loop ~1kHz
138+
// Bluepill loop ~10kHz
139+
motor.loopFOC();
140+
141+
// Motion control function
142+
// velocity, position or voltage (defined in motor.controller)
143+
// this function can be run at much lower frequency than loopFOC() function
144+
// You can also use motor.move() and set the motor.target in the code
145+
motor.move(target_voltage);
146+
147+
// communicate with the user
148+
serialReceiveUserCommand();
149+
}
150+
151+
152+
// utility function enabling serial communication with the user to set the target values
153+
// this function can be implemented in serialEvent function as well
154+
void serialReceiveUserCommand() {
155+
156+
// a string to hold incoming data
157+
static String received_chars;
158+
159+
while (Serial.available()) {
160+
// get the new byte:
161+
char inChar = (char)Serial.read();
162+
// add it to the string buffer:
163+
received_chars += inChar;
164+
// end of user input
165+
if (inChar == '\n') {
166+
167+
// change the motor target
168+
target_voltage = received_chars.toFloat();
169+
Serial.print("Target voltage: ");
170+
Serial.println(target_voltage);
171+
172+
// reset the command buffer
173+
received_chars = "";
174+
}
175+
}
176+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/**
2+
* Utility arduino sketch which finds pole pair number of the motor
3+
*
4+
* To run it just set the correct pin numbers for the BLDC driver and sensor CPR value and chip select pin.
5+
*
6+
* The program will rotate your motor a specific amount and check how much it moved, and by doing a simple calculation calculate your pole pair number.
7+
* The pole pair number will be outputted to the serial terminal.
8+
*
9+
* If the pole pair number is well estimated your motor will start to spin in voltage mode with 2V target.
10+
*
11+
* If the code calculates negative pole pair number please invert your motor connector.
12+
*
13+
* Try running this code several times to avoid statistical errors.
14+
* > But in general if your motor spins, you have a good pole pairs number.
15+
*/
16+
#include <SimpleFOC.h>
17+
18+
// BLDC motor instance
19+
// its important to put pole pairs number as 1!!!
20+
BLDCMotor motor = BLDCMotor(1);
21+
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
22+
// Stepper motor instance
23+
// its important to put pole pairs number as 1!!!
24+
//StepperMotor motor = StepperMotor(1);
25+
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);
26+
27+
// magnetic sensor instance - SPI
28+
MagneticSensorSPI sensor = MagneticSensorSPI(10, 14, 0x3FFF);
29+
// magnetic sensor instance - I2C
30+
//MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0X0C, 4);
31+
// magnetic sensor instance - analog output
32+
// MagneticSensorAnalog sensor = MagneticSensorAnalog(A1, 14, 1020);
33+
34+
void setup() {
35+
36+
// initialise magnetic sensor hardware
37+
sensor.init();
38+
// link the motor to the sensor
39+
motor.linkSensor(&sensor);
40+
41+
// power supply voltage
42+
// default 12V
43+
driver.voltage_power_supply = 12;
44+
driver.init();
45+
motor.linkDriver(&driver);
46+
47+
// initialize motor hardware
48+
motor.init();
49+
50+
// monitoring port
51+
Serial.begin(115200);
52+
53+
// pole pairs calculation routine
54+
Serial.println("Pole pairs (PP) estimator");
55+
Serial.println("-\n");
56+
57+
float pp_search_voltage = 4; // maximum power_supply_voltage/2
58+
float pp_search_angle = 6*M_PI; // search electrical angle to turn
59+
60+
// move motor to the electrical angle 0
61+
motor.controller = MotionControlType::angle_openloop;
62+
motor.voltage_limit=pp_search_voltage;
63+
motor.move(0);
64+
_delay(1000);
65+
// read the sensor angle
66+
sensor.update();
67+
float angle_begin = sensor.getAngle();
68+
_delay(50);
69+
70+
// move the motor slowly to the electrical angle pp_search_angle
71+
float motor_angle = 0;
72+
while(motor_angle <= pp_search_angle){
73+
motor_angle += 0.01f;
74+
sensor.update(); // keep track of the overflow
75+
motor.move(motor_angle);
76+
_delay(1);
77+
}
78+
_delay(1000);
79+
// read the sensor value for 180
80+
sensor.update();
81+
float angle_end = sensor.getAngle();
82+
_delay(50);
83+
// turn off the motor
84+
motor.move(0);
85+
_delay(1000);
86+
87+
// calculate the pole pair number
88+
int pp = round((pp_search_angle)/(angle_end-angle_begin));
89+
90+
Serial.print(F("Estimated PP : "));
91+
Serial.println(pp);
92+
Serial.println(F("PP = Electrical angle / Encoder angle "));
93+
Serial.print(pp_search_angle*180/M_PI);
94+
Serial.print(F("/"));
95+
Serial.print((angle_end-angle_begin)*180/M_PI);
96+
Serial.print(F(" = "));
97+
Serial.println((pp_search_angle)/(angle_end-angle_begin));
98+
Serial.println();
99+
100+
101+
// a bit of monitoring the result
102+
if(pp <= 0 ){
103+
Serial.println(F("PP number cannot be negative"));
104+
Serial.println(F(" - Try changing the search_voltage value or motor/sensor configuration."));
105+
return;
106+
}else if(pp > 30){
107+
Serial.println(F("PP number very high, possible error."));
108+
}else{
109+
Serial.println(F("If PP is estimated well your motor should turn now!"));
110+
Serial.println(F(" - If it is not moving try to relaunch the program!"));
111+
Serial.println(F(" - You can also try to adjust the target voltage using serial terminal!"));
112+
}
113+
114+
115+
// set motion control loop to be used
116+
motor.controller = MotionControlType::torque;
117+
// set the pole pair number to the motor
118+
motor.pole_pairs = pp;
119+
//align sensor and start FOC
120+
motor.initFOC();
121+
_delay(1000);
122+
123+
Serial.println(F("\n Motor ready."));
124+
Serial.println(F("Set the target voltage using serial terminal:"));
125+
}
126+
127+
// uq voltage
128+
float target_voltage = 2;
129+
130+
void loop() {
131+
132+
// main FOC algorithm function
133+
// the faster you run this function the better
134+
// Arduino UNO loop ~1kHz
135+
// Bluepill loop ~10kHz
136+
motor.loopFOC();
137+
138+
// Motion control function
139+
// velocity, position or voltage (defined in motor.controller)
140+
// this function can be run at much lower frequency than loopFOC() function
141+
// You can also use motor.move() and set the motor.target in the code
142+
motor.move(target_voltage);
143+
144+
// communicate with the user
145+
serialReceiveUserCommand();
146+
}
147+
148+
149+
// utility function enabling serial communication with the user to set the target values
150+
// this function can be implemented in serialEvent function as well
151+
void serialReceiveUserCommand() {
152+
153+
// a string to hold incoming data
154+
static String received_chars;
155+
156+
while (Serial.available()) {
157+
// get the new byte:
158+
char inChar = (char)Serial.read();
159+
// add it to the string buffer:
160+
received_chars += inChar;
161+
// end of user input
162+
if (inChar == '\n') {
163+
164+
// change the motor target
165+
target_voltage = received_chars.toFloat();
166+
Serial.print("Target voltage: ");
167+
Serial.println(target_voltage);
168+
169+
// reset the command buffer
170+
received_chars = "";
171+
}
172+
}
173+
}

examples/utils/calibration/find_pole_pair_number/encoder/find_pole_pairs_number/find_pole_pairs_number.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ void setup() {
7373
while(motor_angle <= pp_search_angle){
7474
motor_angle += 0.01f;
7575
motor.move(motor_angle);
76+
_delay(1);
7677
}
7778
_delay(1000);
7879
// read the encoder value for 180

examples/utils/calibration/find_pole_pair_number/magnetic_sensor/find_pole_pairs_number/find_pole_pairs_number.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ void setup() {
7373
motor_angle += 0.01f;
7474
sensor.update(); // keep track of the overflow
7575
motor.move(motor_angle);
76+
_delay(1);
7677
}
7778
_delay(1000);
7879
// read the sensor value for 180

0 commit comments

Comments
 (0)