@@ -24,7 +24,6 @@ BLDCMotor::BLDCMotor(int phA, int phB, int phC, int pp, int en)
2424 PI_velocity.P = DEF_PI_VEL_P;
2525 PI_velocity.I = DEF_PI_VEL_I;
2626 PI_velocity.timestamp = _micros ();
27- PI_velocity.voltage_limit = voltage_power_supply;
2827 PI_velocity.voltage_ramp = DEF_PI_VEL_U_RAMP;
2928 PI_velocity.voltage_prev = 0 ;
3029 PI_velocity.tracking_error_prev = 0 ;
@@ -37,8 +36,11 @@ BLDCMotor::BLDCMotor(int phA, int phB, int phC, int pp, int en)
3736 // position loop config
3837 // P controller constant
3938 P_angle.P = DEF_P_ANGLE_P;
39+
4040 // maximum angular velocity to be used for positioning
41- P_angle.velocity_limit = DEF_P_ANGLE_VEL_LIM;
41+ velocity_limit = DEF_P_ANGLE_VEL_LIM;
42+ // maximum voltage to be set to the motor
43+ voltage_limit = voltage_power_supply;
4244
4345 // index search velocity
4446 velocity_index_search = DEF_INDEX_SEARCH_TARGET_VELOCITY;
@@ -56,6 +58,8 @@ BLDCMotor::BLDCMotor(int phA, int phB, int phC, int pp, int en)
5658
5759 // monitor_port
5860 monitor_port = nullptr ;
61+ // sensor
62+ sensor = nullptr ;
5963}
6064
6165// init hardware pins
@@ -73,7 +77,7 @@ void BLDCMotor::init() {
7377 _setPwmFrequency (pwmA, pwmB, pwmC);
7478
7579 // sanity check for the voltage limit configuration
76- if (PI_velocity. voltage_limit > voltage_power_supply) PI_velocity. voltage_limit = voltage_power_supply;
80+ if (voltage_limit > voltage_power_supply) voltage_limit = voltage_power_supply;
7781
7882 _delay (500 );
7983 // enable motor
@@ -187,10 +191,14 @@ int BLDCMotor::absoluteZeroAlign() {
187191*/
188192// shaft angle calculation
189193float BLDCMotor::shaftAngle () {
194+ // if no sensor linked return 0
195+ // if(!sensor) return 0;
190196 return sensor->getAngle ();
191197}
192198// shaft velocity calculation
193199float BLDCMotor::shaftVelocity () {
200+ // if no sensor linked return 0
201+ // if(!sensor) return 0;
194202 float Ts = (_micros () - LPF_velocity.timestamp ) * 1e-6 ;
195203 // quick fix for strange cases (micros overflow)
196204 if (Ts <= 0 || Ts > 0.5 ) Ts = 1e-3 ;
@@ -269,6 +277,18 @@ void BLDCMotor::move(float new_target) {
269277 shaft_velocity_sp = target;
270278 voltage_q = velocityPI (shaft_velocity_sp - shaft_velocity);
271279 break ;
280+ case ControlType::velocity_openloop:
281+ // velocity control in open loop
282+ // loopFOC should not be called
283+ shaft_velocity_sp = target;
284+ velocityOpenloop (shaft_velocity_sp);
285+ break ;
286+ case ControlType::angle_openloop:
287+ // angle control in open loop
288+ // loopFOC should not be called
289+ shaft_angle_sp = target;
290+ angleOpenloop (shaft_angle_sp);
291+ break ;
272292 }
273293}
274294
@@ -364,9 +384,9 @@ void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
364384 }
365385
366386 // calculate the phase voltages and center
367- Ua = Ta*voltage_power_supply;// + (voltage_power_supply - Uq) / 2;
368- Ub = Tb*voltage_power_supply;// + (voltage_power_supply - Uq) / 2;
369- Uc = Tc*voltage_power_supply;// + (voltage_power_supply - Uq) / 2;
387+ Ua = Ta*voltage_power_supply;
388+ Ub = Tb*voltage_power_supply;
389+ Uc = Tc*voltage_power_supply;
370390 break ;
371391 }
372392
@@ -376,14 +396,13 @@ void BLDCMotor::setPhaseVoltage(float Uq, float angle_el) {
376396
377397
378398
379-
380399// Set voltage to the pwm pin
381400void BLDCMotor::setPwm (float Ua, float Ub, float Uc) {
382401 // calculate duty cycle
383402 // limited in [0,1]
384- float dc_a = (Ua < 0 ) ? 0 : (Ua >= voltage_power_supply) ? 1 : Ua / voltage_power_supply;
385- float dc_b = (Ub < 0 ) ? 0 : (Ub >= voltage_power_supply) ? 1 : Ub / voltage_power_supply;
386- float dc_c = (Uc < 0 ) ? 0 : (Uc >= voltage_power_supply) ? 1 : Uc / voltage_power_supply;
403+ float dc_a = constrain (Ua / voltage_power_supply, 0 , 1 );
404+ float dc_b = constrain (Ub / voltage_power_supply, 0 , 1 );
405+ float dc_c = constrain (Uc / voltage_power_supply, 0 , 1 );
387406 // hardware specific writing
388407 _writeDutyCycle (dc_a, dc_b, dc_c, pwmA, pwmB, pwmC );
389408}
@@ -419,7 +438,7 @@ float BLDCMotor::controllerPI(float tracking_error, PI_s& cont){
419438 float voltage = cont.voltage_prev + (tmp + cont.P ) * tracking_error + (tmp - cont.P ) * cont.tracking_error_prev ;
420439
421440 // antiwindup - limit the output voltage_q
422- if ( abs ( voltage) > cont. voltage_limit ) voltage = voltage > 0 ? cont. voltage_limit : -cont. voltage_limit ;
441+ voltage = constrain ( voltage, - voltage_limit, voltage_limit) ;
423442 // limit the acceleration by ramping the the voltage
424443 float d_voltage = voltage - cont.voltage_prev ;
425444 if (abs (d_voltage)/Ts > cont.voltage_ramp ) voltage = d_voltage > 0 ? cont.voltage_prev + cont.voltage_ramp *Ts : cont.voltage_prev - cont.voltage_ramp *Ts;
@@ -440,10 +459,51 @@ float BLDCMotor::positionP(float ek) {
440459 // calculate the target velocity from the position error
441460 float velocity_target = P_angle.P * ek;
442461 // constrain velocity target value
443- if ( abs ( velocity_target) > P_angle. velocity_limit ) velocity_target = velocity_target > 0 ? P_angle. velocity_limit : -P_angle. velocity_limit ;
462+ velocity_target = constrain ( velocity_target, - velocity_limit, velocity_limit) ;
444463 return velocity_target;
445464}
446465
466+ // Function (iterative) generating open loop movement for target velocity
467+ // - target_velocity - rad/s
468+ // it uses voltage_limit variable
469+ void BLDCMotor::velocityOpenloop (float target_velocity){
470+ // get current timestamp
471+ long now_us = _micros ();
472+ // calculate the sample time from last call
473+ float Ts = (now_us - open_loop_timestamp) * 1e-6 ;
474+
475+ // calculate the necessary angle to achieve target velocity
476+ shaft_angle += target_velocity*Ts;
477+ // set the maximal allowed voltage (voltage_limit) with the necessary angle
478+ setPhaseVoltage (voltage_limit, electricAngle (shaft_angle));
479+
480+ // save timestamp for next call
481+ open_loop_timestamp = now_us;
482+ }
483+
484+ // Function (iterative) generating open loop movement towards the target angle
485+ // - target_angle - rad
486+ // it uses voltage_limit and velocity_limit variables
487+ void BLDCMotor::angleOpenloop (float target_angle){
488+ // get current timestamp
489+ long now_us = _micros ();
490+ // calculate the sample time from last call
491+ float Ts = (now_us - open_loop_timestamp) * 1e-6 ;
492+
493+ // calculate the necessary angle to move from current position towards target angle
494+ // with maximal velocity (velocity_limit)
495+ if (abs ( target_angle - shaft_angle ) > abs (velocity_limit*Ts))
496+ shaft_angle += _sign (target_angle - shaft_angle) * abs ( velocity_limit )*Ts;
497+ else
498+ shaft_angle = target_angle;
499+
500+ // set the maximal allowed voltage (voltage_limit) with the necessary angle
501+ setPhaseVoltage (voltage_limit, electricAngle (shaft_angle));
502+
503+ // save timestamp for next call
504+ open_loop_timestamp = now_us;
505+ }
506+
447507/* *
448508 * Monitoring functions
449509 */
@@ -498,17 +558,20 @@ int BLDCMotor::command(String user_command) {
498558 switch (cmd){
499559 case ' P' : // velocity P gain change
500560 case ' I' : // velocity I gain change
501- case ' L' : // velocity voltage limit change
502561 case ' R' : // velocity voltage ramp change
503562 if (monitor_port) monitor_port->print (" PI velocity| " );
504563 break ;
505564 case ' F' : // velocity Tf low pass filter change
506565 if (monitor_port) monitor_port->print (" LPF velocity| " );
507566 break ;
508567 case ' K' : // angle loop gain P change
509- case ' N' : // angle loop gain velocity_limit change
510568 if (monitor_port) monitor_port->print (" P angle| " );
511569 break ;
570+ case ' L' : // velocity voltage limit change
571+ case ' N' : // angle loop gain velocity_limit change
572+ if (monitor_port) monitor_port->print (" Limits| " );
573+ break ;
574+
512575 }
513576
514577 // apply the the command
@@ -525,8 +588,8 @@ int BLDCMotor::command(String user_command) {
525588 break ;
526589 case ' L' : // velocity voltage limit change
527590 if (monitor_port) monitor_port->print (" volt_limit: " );
528- if (!GET)PI_velocity. voltage_limit = value;
529- if (monitor_port) monitor_port->println (PI_velocity. voltage_limit );
591+ if (!GET)voltage_limit = value;
592+ if (monitor_port) monitor_port->println (voltage_limit);
530593 break ;
531594 case ' R' : // velocity voltage ramp change
532595 if (monitor_port) monitor_port->print (" volt_ramp: " );
@@ -545,8 +608,8 @@ int BLDCMotor::command(String user_command) {
545608 break ;
546609 case ' N' : // angle loop gain velocity_limit change
547610 if (monitor_port) monitor_port->print (" vel_limit: " );
548- if (!GET) P_angle. velocity_limit = value;
549- if (monitor_port) monitor_port->println (P_angle. velocity_limit );
611+ if (!GET) velocity_limit = value;
612+ if (monitor_port) monitor_port->println (velocity_limit);
550613 break ;
551614 case ' C' :
552615 // change control type
@@ -612,36 +675,4 @@ int BLDCMotor::command(String user_command) {
612675 }
613676 // return 0 if error and 1 if ok
614677 return errorFlag;
615- }
616-
617-
618- // set velocity in open loop
619- // - velocity - rad/s
620- // - voltage - V
621- void BLDCMotor::velocityOpenloop (float vel, float voltage){
622- float Ts = (_micros () - open_loop_timestamp) * 1e-6 ;
623-
624- shaft_angle += vel*Ts;
625-
626- setPhaseVoltage (voltage, electricAngle (shaft_angle));
627-
628- open_loop_timestamp = _micros ();
629- }
630-
631- // set angle in open loop
632- // - angle - rad
633- // - velocity - rad/s
634- // - voltage - V
635- void BLDCMotor::angleOpenloop (float angle, float vel, float voltage){
636- float Ts = (_micros () - open_loop_timestamp) * 1e-6 ;
637-
638- if (abs (angle- shaft_angle) > abs (vel*Ts)){
639- shaft_angle += _sign (angle - shaft_angle) * abs (vel)*Ts;
640- }else {
641- shaft_angle = angle;
642- }
643-
644- setPhaseVoltage (voltage, electricAngle (shaft_angle));
645-
646- open_loop_timestamp = _micros ();
647678}
0 commit comments