@@ -44,6 +44,8 @@ void BLDCMotor::init() {
44
44
PID_current_d.limit = voltage_limit;
45
45
// velocity control loop controls current
46
46
PID_velocity.limit = current_limit;
47
+ }else if (!current_sense && _isset (phase_resistance)){
48
+ PID_velocity.limit = current_limit;
47
49
}else {
48
50
PID_velocity.limit = voltage_limit;
49
51
}
@@ -101,32 +103,32 @@ int BLDCMotor::initFOC( float zero_electric_offset, Direction _sensor_direction
101
103
102
104
// aligning the current sensor - can be skipped
103
105
// checks if driver phases are the same as current sense phases
104
- // and checks the direction of measuremnt.
106
+ // and checks the direction of measuremnt.
105
107
_delay (500 );
106
- if (exit_flag){
108
+ if (exit_flag){
107
109
if (current_sense) exit_flag *= alignCurrentSense ();
108
110
else if (monitor_port) monitor_port->println (F (" MOT: No current sense." ));
109
111
}
110
-
112
+
111
113
if (exit_flag){
112
114
if (monitor_port) monitor_port->println (F (" MOT: Ready." ));
113
115
}else {
114
116
if (monitor_port) monitor_port->println (F (" MOT: Init FOC failed." ));
115
117
disable ();
116
118
}
117
-
119
+
118
120
return exit_flag;
119
121
}
120
122
121
123
// Calibarthe the motor and current sense phases
122
124
int BLDCMotor::alignCurrentSense () {
123
- int exit_flag = 1 ; // success
125
+ int exit_flag = 1 ; // success
124
126
125
127
if (monitor_port) monitor_port->println (F (" MOT: Align current sense." ));
126
128
127
129
// align current sense and the driver
128
130
exit_flag = current_sense->driverAlign (driver, voltage_sensor_align);
129
- if (!exit_flag){
131
+ if (!exit_flag){
130
132
// error in current sense - phase either not measured or bad connection
131
133
if (monitor_port) monitor_port->println (F (" MOT: Align error!" ));
132
134
exit_flag = 0 ;
@@ -143,7 +145,7 @@ int BLDCMotor::alignCurrentSense() {
143
145
int BLDCMotor::alignSensor () {
144
146
int exit_flag = 1 ; // success
145
147
if (monitor_port) monitor_port->println (F (" MOT: Align sensor." ));
146
-
148
+
147
149
// if unknown natural direction
148
150
if (!_isset (sensor_direction)){
149
151
// check if sensor needs zero search
@@ -169,7 +171,7 @@ int BLDCMotor::alignSensor() {
169
171
float end_angle = sensor->getAngle ();
170
172
setPhaseVoltage (0 , 0 , 0 );
171
173
_delay (200 );
172
- // determine the direction the sensor moved
174
+ // determine the direction the sensor moved
173
175
if (mid_angle == end_angle) {
174
176
if (monitor_port) monitor_port->println (F (" MOT: Failed to notice movement" ));
175
177
return 0 ; // failed calibration
@@ -180,7 +182,7 @@ int BLDCMotor::alignSensor() {
180
182
if (monitor_port) monitor_port->println (F (" MOT: sensor_direction==CW" ));
181
183
sensor_direction = Direction::CW;
182
184
}
183
- // check pole pair number
185
+ // check pole pair number
184
186
if (monitor_port) monitor_port->print (F (" MOT: PP check: " ));
185
187
float moved = fabs (mid_angle - end_angle);
186
188
if ( fabs (moved*pole_pairs - _2PI) > 0.5 ) { // 0.5 is arbitrary number it can be lower or higher!
@@ -193,7 +195,7 @@ int BLDCMotor::alignSensor() {
193
195
// zero electric angle not known
194
196
if (!_isset (zero_electric_angle)){
195
197
// align the electrical phases of the motor and sensor
196
- // set angle -90(270 = 3PI/2) degrees
198
+ // set angle -90(270 = 3PI/2) degrees
197
199
setPhaseVoltage (voltage_sensor_align, 0 , _3PI_2);
198
200
_delay (700 );
199
201
zero_electric_angle = _normalizeAngle (_electricalAngle (sensor_direction*sensor->getAngle (), pole_pairs));
@@ -212,7 +214,7 @@ int BLDCMotor::alignSensor() {
212
214
// Encoder alignment the absolute zero angle
213
215
// - to the index
214
216
int BLDCMotor::absoluteZeroSearch () {
215
-
217
+
216
218
if (monitor_port) monitor_port->println (F (" MOT: Index search..." ));
217
219
// search the absolute zero with small velocity
218
220
float limit_vel = velocity_limit;
@@ -243,7 +245,7 @@ int BLDCMotor::absoluteZeroSearch() {
243
245
// The faster it can be run the better
244
246
void BLDCMotor::loopFOC () {
245
247
// if disabled do nothing
246
- if (!enabled) return ;
248
+ if (!enabled) return ;
247
249
// if open-loop do nothing
248
250
if ( controller==MotionControlType::angle_openloop || controller==MotionControlType::velocity_openloop ) return ;
249
251
@@ -263,7 +265,7 @@ void BLDCMotor::loopFOC() {
263
265
// filter the value values
264
266
current.q = LPF_current_q (current.q );
265
267
// calculate the phase voltage
266
- voltage.q = PID_current_q (current_sp - current.q );
268
+ voltage.q = PID_current_q (current_sp - current.q );
267
269
voltage.d = 0 ;
268
270
break ;
269
271
case TorqueControlType::foc_current:
@@ -274,15 +276,15 @@ void BLDCMotor::loopFOC() {
274
276
current.q = LPF_current_q (current.q );
275
277
current.d = LPF_current_d (current.d );
276
278
// calculate the phase voltages
277
- voltage.q = PID_current_q (current_sp - current.q );
279
+ voltage.q = PID_current_q (current_sp - current.q );
278
280
voltage.d = PID_current_d (-current.d );
279
281
break ;
280
282
default :
281
283
// no torque control selected
282
284
if (monitor_port) monitor_port->println (F (" MOT: no torque control selected!" ));
283
285
break ;
284
286
}
285
-
287
+
286
288
// set the phase voltage - FOC heart function :)
287
289
setPhaseVoltage (voltage.q , voltage.d , electrical_angle);
288
290
}
@@ -294,7 +296,7 @@ void BLDCMotor::loopFOC() {
294
296
// - if target is not set it uses motor.target value
295
297
void BLDCMotor::move (float new_target) {
296
298
// if disabled do nothing
297
- if (!enabled) return ;
299
+ if (!enabled) return ;
298
300
// downsampling (optional)
299
301
if (motion_cnt++ < motion_downsample) return ;
300
302
motion_cnt = 0 ;
@@ -307,8 +309,8 @@ void BLDCMotor::move(float new_target) {
307
309
case MotionControlType::torque:
308
310
if (torque_controller == TorqueControlType::voltage) // if voltage torque control
309
311
if (!_isset (phase_resistance)) voltage.q = target;
310
- else voltage.q = target*phase_resistance;
311
- else
312
+ else voltage.q = target*phase_resistance;
313
+ else
312
314
current_sp = target; // if current/foc_current torque control
313
315
break ;
314
316
case MotionControlType::angle:
@@ -318,7 +320,7 @@ void BLDCMotor::move(float new_target) {
318
320
shaft_velocity_sp = P_angle ( shaft_angle_sp - shaft_angle );
319
321
// calculate the torque command
320
322
current_sp = PID_velocity (shaft_velocity_sp - shaft_velocity); // if voltage torque control
321
- // if torque controlled through voltage
323
+ // if torque controlled through voltage
322
324
if (torque_controller == TorqueControlType::voltage){
323
325
// use voltage if phase-resistance not provided
324
326
if (!_isset (phase_resistance)) voltage.q = current_sp;
@@ -331,7 +333,7 @@ void BLDCMotor::move(float new_target) {
331
333
shaft_velocity_sp = target;
332
334
// calculate the torque command
333
335
current_sp = PID_velocity (shaft_velocity_sp - shaft_velocity); // if current/foc_current torque control
334
- // if torque controlled through voltage control
336
+ // if torque controlled through voltage control
335
337
if (torque_controller == TorqueControlType::voltage){
336
338
// use voltage if phase-resistance not provided
337
339
if (!_isset (phase_resistance)) voltage.q = current_sp;
@@ -353,7 +355,7 @@ void BLDCMotor::move(float new_target) {
353
355
break ;
354
356
}
355
357
}
356
-
358
+
357
359
358
360
// Method using FOC to set Uq and Ud to the motor at the optimal angle
359
361
// Function implementing Space Vector PWM and Sine PWM algorithms
@@ -376,9 +378,9 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
376
378
};
377
379
// static int trap_120_state = 0;
378
380
sector = 6 * (_normalizeAngle (angle_el + _PI_6 ) / _2PI); // adding PI/6 to align with other modes
379
- // centering the voltages around either
380
- // modulation_centered == true > driver.volage_limit/2
381
- // modulation_centered == false > or Adaptable centering, all phases drawn to 0 when Uq=0
381
+ // centering the voltages around either
382
+ // modulation_centered == true > driver.volage_limit/2
383
+ // modulation_centered == false > or Adaptable centering, all phases drawn to 0 when Uq=0
382
384
center = modulation_centered ? (driver->voltage_limit )/2 : Uq;
383
385
384
386
if (trap_120_map[sector][0 ] == _HIGH_IMPEDANCE){
@@ -391,7 +393,7 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
391
393
Ub = center;
392
394
Uc = trap_120_map[sector][2 ] * Uq + center;
393
395
driver->setPhaseState (_ACTIVE, _HIGH_IMPEDANCE, _ACTIVE);// disable phase if possible
394
- }else {
396
+ }else {
395
397
Ua = trap_120_map[sector][0 ] * Uq + center;
396
398
Ub = trap_120_map[sector][1 ] * Uq + center;
397
399
Uc = center;
@@ -407,9 +409,9 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
407
409
};
408
410
// static int trap_150_state = 0;
409
411
sector = 12 * (_normalizeAngle (angle_el + _PI_6 ) / _2PI); // adding PI/6 to align with other modes
410
- // centering the voltages around either
411
- // modulation_centered == true > driver.volage_limit/2
412
- // modulation_centered == false > or Adaptable centering, all phases drawn to 0 when Uq=0
412
+ // centering the voltages around either
413
+ // modulation_centered == true > driver.volage_limit/2
414
+ // modulation_centered == false > or Adaptable centering, all phases drawn to 0 when Uq=0
413
415
center = modulation_centered ? (driver->voltage_limit )/2 : Uq;
414
416
415
417
if (trap_150_map[sector][0 ] == _HIGH_IMPEDANCE){
@@ -422,7 +424,7 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
422
424
Ub = center;
423
425
Uc = trap_150_map[sector][2 ] * Uq + center;
424
426
driver->setPhaseState (_ACTIVE, _HIGH_IMPEDANCE, _ACTIVE);// disable phase if possible
425
- }else {
427
+ }else {
426
428
Ua = trap_150_map[sector][0 ] * Uq + center;
427
429
Ub = trap_150_map[sector][1 ] * Uq + center;
428
430
Uc = center;
@@ -468,15 +470,15 @@ void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) {
468
470
// 1) Ualpha, Ubeta
469
471
// 2) Uout = sqrt(Ualpha^2 + Ubeta^2)
470
472
// 3) angle_el = atan2(Ubeta, Ualpha)
471
- //
473
+ //
472
474
// equivalent to 2) because the magnitude does not change is:
473
475
// Uout = sqrt(Ud^2 + Uq^2)
474
476
// equivalent to 3) is
475
477
// angle_el = angle_el + atan2(Uq,Ud)
476
478
477
479
float Uout;
478
480
// a bit of optitmisation
479
- if (Ud){ // only if Ud and Uq set
481
+ if (Ud){ // only if Ud and Uq set
480
482
// _sqrt is an approx of sqrt (3-4% error)
481
483
Uout = _sqrt (Ud*Ud + Uq*Uq) / driver->voltage_limit ;
482
484
// angle normalisation in between 0 and 2pi
@@ -562,16 +564,16 @@ float BLDCMotor::velocityOpenloop(float target_velocity){
562
564
// calculate the sample time from last call
563
565
float Ts = (now_us - open_loop_timestamp) * 1e-6 ;
564
566
// quick fix for strange cases (micros overflow + timestamp not defined)
565
- if (Ts <= 0 || Ts > 0.5 ) Ts = 1e-3 ;
567
+ if (Ts <= 0 || Ts > 0.5 ) Ts = 1e-3 ;
566
568
567
569
// calculate the necessary angle to achieve target velocity
568
- shaft_angle = _normalizeAngle (shaft_angle + target_velocity*Ts);
570
+ shaft_angle = _normalizeAngle (shaft_angle + target_velocity*Ts);
569
571
// for display purposes
570
572
shaft_velocity = target_velocity;
571
-
573
+
572
574
// use voltage limit or current limit
573
575
float Uq = voltage_limit;
574
- if (_isset (phase_resistance)) Uq = current_limit*phase_resistance;
576
+ if (_isset (phase_resistance)) Uq = current_limit*phase_resistance;
575
577
576
578
// set the maximal allowed voltage (voltage_limit) with the necessary angle
577
579
setPhaseVoltage (Uq, 0 , _electricalAngle (shaft_angle, pole_pairs));
@@ -591,7 +593,7 @@ float BLDCMotor::angleOpenloop(float target_angle){
591
593
// calculate the sample time from last call
592
594
float Ts = (now_us - open_loop_timestamp) * 1e-6 ;
593
595
// quick fix for strange cases (micros overflow + timestamp not defined)
594
- if (Ts <= 0 || Ts > 0.5 ) Ts = 1e-3 ;
596
+ if (Ts <= 0 || Ts > 0.5 ) Ts = 1e-3 ;
595
597
596
598
// calculate the necessary angle to move from current position towards target angle
597
599
// with maximal velocity (velocity_limit)
@@ -603,15 +605,15 @@ float BLDCMotor::angleOpenloop(float target_angle){
603
605
shaft_velocity = 0 ;
604
606
}
605
607
606
-
608
+
607
609
// use voltage limit or current limit
608
610
float Uq = voltage_limit;
609
- if (_isset (phase_resistance)) Uq = current_limit*phase_resistance;
611
+ if (_isset (phase_resistance)) Uq = current_limit*phase_resistance;
610
612
// set the maximal allowed voltage (voltage_limit) with the necessary angle
611
613
setPhaseVoltage (Uq, 0 , _electricalAngle (shaft_angle, pole_pairs));
612
614
613
615
// save timestamp for next call
614
616
open_loop_timestamp = now_us;
615
-
617
+
616
618
return Uq;
617
619
}
0 commit comments