Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a MotionControlMode::angle_nocascade which uses a single PID for angle control #384

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions src/BLDCMotor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,14 @@ void BLDCMotor::init() {
if(_isset(phase_resistance) || torque_controller != TorqueControlType::voltage){
// velocity control loop controls current
PID_velocity.limit = current_limit;
P_angle.limit = current_limit; // for MotionControlType::angle_nocascade
}else{
// velocity control loop controls the voltage
PID_velocity.limit = voltage_limit;
P_angle.limit = voltage_limit; // for MotionControlType::angle_nocascade
}
P_angle.limit = velocity_limit;
if (controller!=MotionControlType::angle_nocascade) // if not MotionControlType::angle_nocascade angle PID output is limited by velocity limit
P_angle.limit = velocity_limit;

// if using open loop control, set a CW as the default direction if not already set
if ((controller==MotionControlType::angle_openloop
Expand Down Expand Up @@ -423,16 +426,23 @@ void BLDCMotor::move(float new_target) {
}
break;
case MotionControlType::angle:
case MotionControlType::angle_nocascade:
// TODO sensor precision: this calculation is not numerically precise. The target value cannot express precise positions when
// the angles are large. This results in not being able to command small changes at high position values.
// to solve this, the delta-angle has to be calculated in a numerically precise way.
// angle set point
shaft_angle_sp = target;
// calculate velocity set point
shaft_velocity_sp = feed_forward_velocity + P_angle( shaft_angle_sp - shaft_angle );
shaft_velocity_sp = _constrain(shaft_velocity_sp,-velocity_limit, velocity_limit);
// calculate the torque command - sensor precision: this calculation is ok, but based on bad value from previous calculation
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if voltage torque control
if (controller == MotionControlType::angle) {
// calculate velocity set point
shaft_velocity_sp = feed_forward_velocity + P_angle( shaft_angle_sp - shaft_angle );
shaft_velocity_sp = _constrain(shaft_velocity_sp,-velocity_limit, velocity_limit);
// calculate the torque command - sensor precision: this calculation is ok, but based on bad value from previous calculation
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if voltage torque control
}
else {
// no velocity control
current_sp = P_angle( shaft_angle_sp - shaft_angle );
}
// if torque controlled through voltage
if(torque_controller == TorqueControlType::voltage){
// use voltage if phase-resistance not provided
Expand Down
22 changes: 16 additions & 6 deletions src/StepperMotor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ void StepperMotor::init() {
if(_isset(phase_resistance)){
// velocity control loop controls current
PID_velocity.limit = current_limit;
P_angle.limit = current_limit; // for MotionControlType::angle_nocascade
}else{
PID_velocity.limit = voltage_limit;
P_angle.limit = voltage_limit; // for MotionControlType::angle_nocascade
}
P_angle.limit = velocity_limit;
if (controller!=MotionControlType::angle_nocascade) // if not MotionControlType::angle_nocascade angle PID output is limited by velocity limit
P_angle.limit = velocity_limit;

// if using open loop control, set a CW as the default direction if not already set
if ((controller==MotionControlType::angle_openloop
Expand Down Expand Up @@ -308,13 +311,20 @@ void StepperMotor::move(float new_target) {
else voltage.d = _constrain( -target*shaft_velocity*pole_pairs*phase_inductance, -voltage_limit, voltage_limit);
break;
case MotionControlType::angle:
case MotionControlType::angle_nocascade:
// angle set point
shaft_angle_sp = target;
// calculate velocity set point
shaft_velocity_sp = feed_forward_velocity + P_angle( shaft_angle_sp - shaft_angle );
shaft_velocity_sp = _constrain(shaft_velocity_sp, -velocity_limit, velocity_limit);
// calculate the torque command
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if voltage torque control
if (controller == MotionControlType::angle) {
// calculate velocity set point
shaft_velocity_sp = feed_forward_velocity + P_angle( shaft_angle_sp - shaft_angle );
shaft_velocity_sp = _constrain(shaft_velocity_sp, -velocity_limit, velocity_limit);
// calculate the torque command
current_sp = PID_velocity(shaft_velocity_sp - shaft_velocity); // if voltage torque control
}
else {
// no velocity control
current_sp = P_angle( shaft_angle_sp - shaft_angle );
}
// if torque controlled through voltage
// use voltage if phase-resistance not provided
if(!_isset(phase_resistance)) voltage.q = current_sp;
Expand Down
3 changes: 2 additions & 1 deletion src/common/base_classes/FOCMotor.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ enum MotionControlType : uint8_t {
velocity = 0x01, //!< Velocity motion control
angle = 0x02, //!< Position/angle motion control
velocity_openloop = 0x03,
angle_openloop = 0x04
angle_openloop = 0x04,
angle_nocascade = 0x05 //!< Position/angle motion control without velocity cascade
};

/**
Expand Down
6 changes: 5 additions & 1 deletion src/communication/Commander.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ void Commander::motion(FOCMotor* motor, char* user_cmd, char* separator){
break;
default:
// change control type
if(!GET && value >= 0 && (int)value < 5) // if set command
if(!GET && value >= 0 && (int)value <= 5) // if set command
motor->controller = (MotionControlType)value;
switch(motor->controller){
case MotionControlType::torque:
Expand All @@ -395,6 +395,9 @@ void Commander::motion(FOCMotor* motor, char* user_cmd, char* separator){
case MotionControlType::angle_openloop:
println(F("angle open"));
break;
case MotionControlType::angle_nocascade:
println(F("angle nocascade"));
break;
}
break;
}
Expand Down Expand Up @@ -505,6 +508,7 @@ void Commander::target(FOCMotor* motor, char* user_cmd, char* separator){
float pos, vel, torque;
char* next_value;
switch(motor->controller){
case MotionControlType::angle_nocascade:
case MotionControlType::torque: // setting torque target
torque = atof(strtok (user_cmd, separator));
motor->target = torque;
Expand Down
Loading