00001 #include "feedback_motor.h" 00002 00003 extern Serial pc; 00004 00005 FeedbackMotor::FeedbackMotor(bool internal_pwm, uint8_t external_speed_pin, 00006 PinName internal_speed_pin, PinName microswitch_pin, 00007 PinMode microswitch_mode) : 00008 Motor(internal_pwm, external_speed_pin, internal_speed_pin, microswitch_pin, microswitch_mode) 00009 { 00010 dt_ = 0; 00011 position_error_ = 0; 00012 target_position_ = 0; 00013 target_velocity_ = 0; 00014 integral_error_ = 0; 00015 control_enabled_ = false; 00016 p_gain_ = 0; 00017 i_gain_ = 0; 00018 d_gain_ = 0; 00019 i_saturation_ = 0; 00020 max_pwm_ = 0; 00021 velocity_threshold_ = 0; 00022 pwm_ = 0; 00023 } 00024 00025 FeedbackMotor::~FeedbackMotor() {} 00026 00027 void FeedbackMotor::updateMotor() 00028 { 00029 if (control_enabled_ && !update_in_progress_ && desired_move_duration_ > 0) 00030 { 00031 dt_ = move_duration_.read(); 00032 if(dt_ > desired_move_duration_) 00033 dt_ = desired_move_duration_; 00034 00035 //find the base trajectory term 00036 float base_term = (dt_ * desired_distance_) / (desired_move_duration_ * desired_move_duration_); 00037 //find the position trajectory 00038 target_position_ = (desired_encoder_ - desired_distance_) + 00039 (3.0) * (dt_ * base_term) - 00040 (2.0) * (dt_ * dt_ * base_term) / (desired_move_duration_); 00041 //find the velocity trajectory 00042 target_velocity_ = (6.0) * (base_term) - 00043 (6.0) * (dt_ * base_term) / (desired_move_duration_); 00044 00045 //find position error 00046 position_error_ = target_position_ - encoder_; 00047 00048 //find integral error 00049 integral_error_ = integral_error_ + position_error_; 00050 if (integral_error_ > i_saturation_) 00051 integral_error_ = i_saturation_; 00052 else if (integral_error_ < - i_saturation_) 00053 integral_error_ = - i_saturation_; 00054 00055 //compute pwm 00056 pwm_ = p_gain_*position_error_ + i_gain_*integral_error_ + d_gain_*target_velocity_; 00057 //add a constant velocity offset if required by static friction 00058 if (velocity_threshold_ > 0) 00059 { 00060 if (pwm_ > 0) 00061 pwm_ += velocity_threshold_; 00062 else if (pwm_ < 0) 00063 pwm_ -= velocity_threshold_; 00064 } 00065 00066 //limit the maximum and minimum pwm 00067 if (pwm_ > max_pwm_) 00068 pwm_ = max_pwm_; 00069 else if (pwm_ < - max_pwm_) 00070 pwm_ = - max_pwm_; 00071 00072 setPWMDuty(pwm_); 00073 } 00074 } 00075 00076 bool FeedbackMotor::setControlParameters(uint8_t length, uint8_t *data) 00077 { 00078 bool success = false; 00079 if (length == PARAMETER_MESSAGE_LENGTH) 00080 { 00081 control_enabled_ = true; 00082 update_in_progress_ = true; 00083 success = true; 00084 00085 p_gain_ = ((float) ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3] )) / 100000.0; 00086 i_gain_ = ((float) ((data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7] )) / 100000.0; 00087 d_gain_ = ((float) ((data[8] << 24) | (data[9] << 16) | (data[10] << 8) | data[11])) / 100000.0; 00088 i_saturation_ = ((float) ((data[12] << 24) | (data[13] << 16) | (data[14] << 8) | data[15])) / 100000.0; 00089 max_pwm_ = ((float) ((data[16] << 24) | (data[17] << 16) | (data[18] << 8) | data[19])) / 100000.0; 00090 velocity_threshold_ = ((float) ((data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23])) / 100000.0; 00091 00092 update_in_progress_ = false; 00093 } 00094 delete[] data; 00095 return success; 00096 } 00097 00098 uint8_t * FeedbackMotor::readControlParameters(uint8_t & length) 00099 { 00100 length = PARAMETER_MESSAGE_LENGTH; 00101 uint8_t * data = new uint8_t[PARAMETER_MESSAGE_LENGTH]; 00102 int index = 0; 00103 long parameter = 0; 00104 00105 //p_gain_ 00106 parameter = (long) (p_gain_*100000.0); 00107 data[index++] = (parameter >> 24) & 0xFF; 00108 data[index++] = (parameter >> 16) & 0xFF; 00109 data[index++] = (parameter >> 8) & 0xFF; 00110 data[index++] = (parameter ) & 0xFF; 00111 //i_gain_ 00112 parameter = (long) (i_gain_*100000.0); 00113 data[index++] = (parameter >> 24) & 0xFF; 00114 data[index++] = (parameter >> 16) & 0xFF; 00115 data[index++] = (parameter >> 8) & 0xFF; 00116 data[index++] = (parameter ) & 0xFF; 00117 //d_gain_ 00118 parameter = (long) (d_gain_*100000.0); 00119 data[index++] = (parameter >> 24) & 0xFF; 00120 data[index++] = (parameter >> 16) & 0xFF; 00121 data[index++] = (parameter >> 8) & 0xFF; 00122 data[index++] = (parameter ) & 0xFF; 00123 //i_saturation_ 00124 parameter = (long) (i_saturation_*100000.0); 00125 data[index++] = (parameter >> 24) & 0xFF; 00126 data[index++] = (parameter >> 16) & 0xFF; 00127 data[index++] = (parameter >> 8) & 0xFF; 00128 data[index++] = (parameter ) & 0xFF; 00129 //max_pwm_ 00130 parameter = (long) (max_pwm_*100000.0); 00131 data[index++] = (parameter >> 24) & 0xFF; 00132 data[index++] = (parameter >> 16) & 0xFF; 00133 data[index++] = (parameter >> 8) & 0xFF; 00134 data[index++] = (parameter ) & 0xFF; 00135 //velocity_threshold_ 00136 parameter = (long) (velocity_threshold_*100000.0); 00137 data[index++] = (parameter >> 24) & 0xFF; 00138 data[index++] = (parameter >> 16) & 0xFF; 00139 data[index++] = (parameter >> 8) & 0xFF; 00140 data[index++] = (parameter ) & 0xFF; 00141 00142 return data; 00143 } 00144 00145 long FeedbackMotor::readTargetPosition() 00146 { 00147 return target_position_; 00148 } 00149 00150 long FeedbackMotor::readTargetVelocity() 00151 { 00152 return target_velocity_; 00153 } 00154 00155 void FeedbackMotor::setDestination(long encoderPosition, long duration) 00156 { 00157 integral_error_ = 0; 00158 Motor::setDestination(encoderPosition, duration); 00159 }