feedback_motor.cpp
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
00036 float base_term = (dt_ * desired_distance_) / (desired_move_duration_ * desired_move_duration_);
00037
00038 target_position_ = (desired_encoder_ - desired_distance_) +
00039 (3.0) * (dt_ * base_term) -
00040 (2.0) * (dt_ * dt_ * base_term) / (desired_move_duration_);
00041
00042 target_velocity_ = (6.0) * (base_term) -
00043 (6.0) * (dt_ * base_term) / (desired_move_duration_);
00044
00045
00046 position_error_ = target_position_ - encoder_;
00047
00048
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
00056 pwm_ = p_gain_*position_error_ + i_gain_*integral_error_ + d_gain_*target_velocity_;
00057
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
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
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
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
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
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
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
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 }