most functionality to splashdwon, find neutral and start mission. short timeouts still in code for testing, will adjust to go directly to sit_idle after splashdown

Dependencies:   mbed MODSERIAL FATFileSystem

Committer:
joel_ssc
Date:
Mon May 13 19:25:26 2019 +0000
Revision:
92:52a91656458a
Parent:
75:92e79d23d29a
version for first flight test, timeouts not yet set correctly

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tnhnrl 62:d502889e74f1 1 #include "mbed.h"
tnhnrl 62:d502889e74f1 2 #include "LinearActuator.hpp"
tnhnrl 62:d502889e74f1 3 #include "StaticDefs.hpp"
tnhnrl 62:d502889e74f1 4 #include "ConfigFile.h"
tnhnrl 62:d502889e74f1 5
tnhnrl 62:d502889e74f1 6 // this is where the variables that can be set are set when the object is created
tnhnrl 62:d502889e74f1 7 LinearActuator::LinearActuator(float interval, PinName pwm, PinName dir, PinName reset, PinName limit, int adc_ch):
tnhnrl 62:d502889e74f1 8 _motor(pwm, dir, reset),
tnhnrl 62:d502889e74f1 9 _filter(),
tnhnrl 62:d502889e74f1 10 _pid(),
tnhnrl 62:d502889e74f1 11 _pulse(),
tnhnrl 62:d502889e74f1 12 _limitSwitch(limit)
tnhnrl 62:d502889e74f1 13 {
tnhnrl 62:d502889e74f1 14 _limitSwitch.fall(callback(this, &LinearActuator::_switchPressed));
tnhnrl 62:d502889e74f1 15
tnhnrl 62:d502889e74f1 16 _Pgain = 0.10;
tnhnrl 62:d502889e74f1 17 _Igain = 0.0;
tnhnrl 62:d502889e74f1 18 _Dgain = 0.0;
tnhnrl 62:d502889e74f1 19
tnhnrl 62:d502889e74f1 20 _filterFrequency = 1.0;
tnhnrl 62:d502889e74f1 21
tnhnrl 62:d502889e74f1 22 _adc_channel = adc_ch;
tnhnrl 62:d502889e74f1 23
tnhnrl 62:d502889e74f1 24 _dt = interval;
tnhnrl 62:d502889e74f1 25
tnhnrl 62:d502889e74f1 26 _init = true;
tnhnrl 62:d502889e74f1 27 _paused = false;
tnhnrl 62:d502889e74f1 28 _limit = false;
tnhnrl 74:d281aaef9766 29 _slope = 498.729/4096; //this value should be correct for our current string pots using .625" diameter and 12 bit ADC (hardcoded in config as 0.12176)
tnhnrl 62:d502889e74f1 30 _deadband = 0.5;
tnhnrl 62:d502889e74f1 31
tnhnrl 62:d502889e74f1 32 _pid_high_limit = 0.0;
tnhnrl 62:d502889e74f1 33 _pid_low_limit = 0.0;
tnhnrl 62:d502889e74f1 34 }
tnhnrl 62:d502889e74f1 35
tnhnrl 62:d502889e74f1 36 void LinearActuator::init() {
tnhnrl 62:d502889e74f1 37 // initialize and start all of the member objects.
tnhnrl 62:d502889e74f1 38 // The pos-velocity filter for this item needs to be allowed to converge
tnhnrl 62:d502889e74f1 39 // Before turning over control to the motor
tnhnrl 62:d502889e74f1 40 // make sure that adc().init is called in mainline code before calling this function
tnhnrl 62:d502889e74f1 41
tnhnrl 62:d502889e74f1 42 //load gains into pid controller this should eventually be in a config file
tnhnrl 62:d502889e74f1 43 setFilterFrequency(_filterFrequency);
tnhnrl 62:d502889e74f1 44 setControllerP(_Pgain);
tnhnrl 62:d502889e74f1 45 setControllerI(_Igain);
tnhnrl 62:d502889e74f1 46 setControllerD(_Dgain);
tnhnrl 62:d502889e74f1 47
tnhnrl 62:d502889e74f1 48 //setup the controller object
tnhnrl 62:d502889e74f1 49 //set deadband and limits
tnhnrl 62:d502889e74f1 50 toggleDeadband(true);
tnhnrl 62:d502889e74f1 51 setDeadband(_deadband);
tnhnrl 62:d502889e74f1 52 }
tnhnrl 62:d502889e74f1 53
tnhnrl 62:d502889e74f1 54 void LinearActuator::update() {
tnhnrl 62:d502889e74f1 55 // update the position velocity filter
tnhnrl 62:d502889e74f1 56 if (_adc_channel == 0) {
tnhnrl 62:d502889e74f1 57 _filter.update(_dt, adc().readCh0());
tnhnrl 62:d502889e74f1 58 } else if (_adc_channel == 1) {
tnhnrl 62:d502889e74f1 59 _filter.update(_dt, adc().readCh1());
tnhnrl 62:d502889e74f1 60 } else {
tnhnrl 62:d502889e74f1 61 error("\n\r This ADC channel does not exist");
tnhnrl 62:d502889e74f1 62 }
tnhnrl 62:d502889e74f1 63
tnhnrl 62:d502889e74f1 64 // refresh the filter results and load into class variables
tnhnrl 62:d502889e74f1 65 refreshPVState();
tnhnrl 62:d502889e74f1 66
tnhnrl 62:d502889e74f1 67 // update the PID controller with latest data
tnhnrl 62:d502889e74f1 68 _pid.update(_position_mm, _velocity_mms, _filter.getDt());
tnhnrl 62:d502889e74f1 69
tnhnrl 62:d502889e74f1 70 if (_init) {
tnhnrl 62:d502889e74f1 71 //The initialization phase is active
tnhnrl 62:d502889e74f1 72 //dont run the motors until the velocity stabilizes
tnhnrl 62:d502889e74f1 73 if (abs(_velocity_mms)<0.1) {
tnhnrl 62:d502889e74f1 74 //we must be converged and can now release the motor controls
tnhnrl 62:d502889e74f1 75 _init = false;
tnhnrl 62:d502889e74f1 76 }
tnhnrl 62:d502889e74f1 77 } else if (_limit) {
tnhnrl 62:d502889e74f1 78 //if you end up here, an interrupt was triggered by an edge detection
tnhnrl 62:d502889e74f1 79 //case on the limit switch. That function would have stopped the motor
tnhnrl 62:d502889e74f1 80 //This logic should allow it to be re-enabled if the output being asked
tnhnrl 62:d502889e74f1 81 //for by the controller is the correct direction.
tnhnrl 62:d502889e74f1 82
tnhnrl 62:d502889e74f1 83 if (_pid.getOutput() < 0.0) { //a negative pid output results in motion toward the switch
tnhnrl 62:d502889e74f1 84 //dont let the motor run
tnhnrl 62:d502889e74f1 85 return;
tnhnrl 62:d502889e74f1 86 } else {
tnhnrl 62:d502889e74f1 87 //We are now trucking along in the correct direction, it is ok to
tnhnrl 62:d502889e74f1 88 //reset the limit variable and allow the motor to run
tnhnrl 62:d502889e74f1 89 _limit = false;
tnhnrl 62:d502889e74f1 90 }
tnhnrl 62:d502889e74f1 91 } else if (_paused) {
tnhnrl 62:d502889e74f1 92 //if you get here, the pause function has stopped the motor
tnhnrl 62:d502889e74f1 93 //the only way out is for a function call to unpause the motor
tnhnrl 62:d502889e74f1 94 //this case also keeps the controller disconnected in the event that
tnhnrl 62:d502889e74f1 95 //homing is happening
tnhnrl 62:d502889e74f1 96 return;
tnhnrl 62:d502889e74f1 97 }
tnhnrl 62:d502889e74f1 98
tnhnrl 62:d502889e74f1 99 else {
tnhnrl 62:d502889e74f1 100 //pipe controller data into the motor driver
tnhnrl 62:d502889e74f1 101 //check that the limit switch is not pressed and if it is only let the
tnhnrl 62:d502889e74f1 102 //motor run if the command is a negative number
tnhnrl 62:d502889e74f1 103 //this catches the case where the piston is being moved off of the switch
tnhnrl 62:d502889e74f1 104 //and the motor command reverses for some reason
tnhnrl 62:d502889e74f1 105
tnhnrl 62:d502889e74f1 106 if ((_limitSwitch.read() == 0) && (_pid.getOutput()< 0)) {
tnhnrl 62:d502889e74f1 107 //dont run
tnhnrl 62:d502889e74f1 108 return;
tnhnrl 62:d502889e74f1 109 }
tnhnrl 62:d502889e74f1 110
tnhnrl 62:d502889e74f1 111 // clamp the output to the motor to -1.0 to 1.0
tnhnrl 62:d502889e74f1 112 if (_pid.getOutput() > 1.0)
tnhnrl 62:d502889e74f1 113 _motor.run(1.0);
tnhnrl 62:d502889e74f1 114 else if (_pid.getOutput() < -1.0)
tnhnrl 62:d502889e74f1 115 _motor.run(-1.0);
tnhnrl 62:d502889e74f1 116 else
tnhnrl 62:d502889e74f1 117 _motor.run(_pid.getOutput());
tnhnrl 62:d502889e74f1 118 }
tnhnrl 62:d502889e74f1 119 }
tnhnrl 62:d502889e74f1 120
tnhnrl 62:d502889e74f1 121 // using main loop ticker (attached at 0.01 intervals)
tnhnrl 62:d502889e74f1 122 void LinearActuator::runLinearActuator() {
tnhnrl 62:d502889e74f1 123 _init = true;
tnhnrl 62:d502889e74f1 124 }
tnhnrl 62:d502889e74f1 125
tnhnrl 62:d502889e74f1 126 void LinearActuator::pause() {
tnhnrl 62:d502889e74f1 127 //this allows the controller to keep running while turning off the motor output
tnhnrl 62:d502889e74f1 128 _motor.stop();
tnhnrl 62:d502889e74f1 129 //paused flag causes controller output not to be piped to the motor
tnhnrl 62:d502889e74f1 130 _paused = true;
tnhnrl 62:d502889e74f1 131 }
tnhnrl 62:d502889e74f1 132
tnhnrl 62:d502889e74f1 133 void LinearActuator::unpause() {
tnhnrl 62:d502889e74f1 134 //this resumes motor operation
tnhnrl 62:d502889e74f1 135 _paused = false;
tnhnrl 62:d502889e74f1 136 }
tnhnrl 62:d502889e74f1 137
tnhnrl 62:d502889e74f1 138 void LinearActuator::refreshPVState() {
tnhnrl 62:d502889e74f1 139 _position = _filter.getPosition();
tnhnrl 62:d502889e74f1 140 _velocity = _filter.getVelocity();
tnhnrl 62:d502889e74f1 141
tnhnrl 62:d502889e74f1 142 _position_mm = counts_to_dist(_position);
tnhnrl 62:d502889e74f1 143 _velocity_mms = counts_to_velocity(_velocity);
tnhnrl 62:d502889e74f1 144 }
tnhnrl 62:d502889e74f1 145
tnhnrl 62:d502889e74f1 146 // setting and getting variables
tnhnrl 62:d502889e74f1 147 void LinearActuator::setPosition_mm(float dist) {
tnhnrl 62:d502889e74f1 148 _SetPoint_mm = clamp<float>(dist, 0.0, _extendLimit); //this is another spot that prevents the requested set point from going out of range, this template function is defined in the controller header file fyi
tnhnrl 62:d502889e74f1 149
tnhnrl 62:d502889e74f1 150 _pid.writeSetPoint(_SetPoint_mm);
tnhnrl 62:d502889e74f1 151 }
tnhnrl 62:d502889e74f1 152
tnhnrl 62:d502889e74f1 153 float LinearActuator::getSetPosition_mm() {
tnhnrl 62:d502889e74f1 154 return _SetPoint_mm;
tnhnrl 62:d502889e74f1 155 }
tnhnrl 62:d502889e74f1 156
tnhnrl 62:d502889e74f1 157 float LinearActuator::getPosition_mm() {
tnhnrl 62:d502889e74f1 158 return _position_mm;
tnhnrl 62:d502889e74f1 159 }
tnhnrl 62:d502889e74f1 160
tnhnrl 62:d502889e74f1 161 float LinearActuator::getPosition_counts() {
tnhnrl 62:d502889e74f1 162 return _position;
tnhnrl 62:d502889e74f1 163 }
tnhnrl 62:d502889e74f1 164
tnhnrl 62:d502889e74f1 165 float LinearActuator::getVelocity_mms() {
tnhnrl 62:d502889e74f1 166 return _velocity_mms;
tnhnrl 62:d502889e74f1 167 }
tnhnrl 62:d502889e74f1 168
tnhnrl 62:d502889e74f1 169 void LinearActuator::setControllerP(float P) {
tnhnrl 62:d502889e74f1 170 _Pgain = P;
tnhnrl 62:d502889e74f1 171 _pid.setPgain(_Pgain);
tnhnrl 62:d502889e74f1 172 return;
tnhnrl 62:d502889e74f1 173 }
tnhnrl 62:d502889e74f1 174
tnhnrl 62:d502889e74f1 175 float LinearActuator::getControllerP() {
tnhnrl 62:d502889e74f1 176 return _Pgain;
tnhnrl 62:d502889e74f1 177 }
tnhnrl 62:d502889e74f1 178
tnhnrl 62:d502889e74f1 179 void LinearActuator::setControllerI(float I) {
tnhnrl 62:d502889e74f1 180 _Igain = I;
tnhnrl 62:d502889e74f1 181 _pid.setIgain(_Igain);
tnhnrl 62:d502889e74f1 182 return;
tnhnrl 62:d502889e74f1 183 }
tnhnrl 62:d502889e74f1 184
tnhnrl 62:d502889e74f1 185 float LinearActuator::getControllerI() {
tnhnrl 62:d502889e74f1 186 return _Igain;
tnhnrl 62:d502889e74f1 187 }
tnhnrl 62:d502889e74f1 188
tnhnrl 62:d502889e74f1 189 void LinearActuator::setControllerD(float D) {
tnhnrl 62:d502889e74f1 190 _Dgain = D;
tnhnrl 62:d502889e74f1 191 _pid.setDgain(_Dgain);
tnhnrl 62:d502889e74f1 192 return;
tnhnrl 62:d502889e74f1 193 }
tnhnrl 62:d502889e74f1 194
tnhnrl 62:d502889e74f1 195 float LinearActuator::getControllerD() {
tnhnrl 62:d502889e74f1 196 return _Dgain;
tnhnrl 62:d502889e74f1 197 }
tnhnrl 62:d502889e74f1 198
tnhnrl 62:d502889e74f1 199 float LinearActuator::getOutput() {
tnhnrl 62:d502889e74f1 200 return _pid.getOutput();
tnhnrl 62:d502889e74f1 201 }
tnhnrl 62:d502889e74f1 202
tnhnrl 62:d502889e74f1 203 void LinearActuator::setZeroCounts(int zero) {
tnhnrl 62:d502889e74f1 204 _zeroCounts = clamp<int>(zero, 0, 4096);
tnhnrl 62:d502889e74f1 205 return;
tnhnrl 62:d502889e74f1 206 }
tnhnrl 62:d502889e74f1 207
tnhnrl 62:d502889e74f1 208 int LinearActuator::getZeroCounts() {
tnhnrl 62:d502889e74f1 209 return _zeroCounts;
tnhnrl 62:d502889e74f1 210 }
tnhnrl 62:d502889e74f1 211
tnhnrl 62:d502889e74f1 212 void LinearActuator::setTravelLimit(float limit) {
tnhnrl 62:d502889e74f1 213 _extendLimit = limit;
tnhnrl 62:d502889e74f1 214 return;
tnhnrl 62:d502889e74f1 215 }
tnhnrl 62:d502889e74f1 216
tnhnrl 62:d502889e74f1 217 float LinearActuator::getTravelLimit() {
tnhnrl 62:d502889e74f1 218 return _extendLimit;
tnhnrl 62:d502889e74f1 219 }
tnhnrl 62:d502889e74f1 220
tnhnrl 62:d502889e74f1 221 void LinearActuator::setPotSlope(float slope) {
tnhnrl 62:d502889e74f1 222 _slope = slope;
tnhnrl 62:d502889e74f1 223 return;
tnhnrl 62:d502889e74f1 224 }
tnhnrl 62:d502889e74f1 225
tnhnrl 62:d502889e74f1 226 float LinearActuator::getPotSlope() {
tnhnrl 62:d502889e74f1 227 return _slope;
tnhnrl 62:d502889e74f1 228 }
tnhnrl 62:d502889e74f1 229
tnhnrl 62:d502889e74f1 230 float LinearActuator::counts_to_dist(int count) {
tnhnrl 62:d502889e74f1 231 float conv = _slope*(count-_zeroCounts);
tnhnrl 62:d502889e74f1 232 return conv;
tnhnrl 62:d502889e74f1 233 }
tnhnrl 62:d502889e74f1 234
tnhnrl 62:d502889e74f1 235 void LinearActuator::setFilterFrequency(float frequency) {
tnhnrl 62:d502889e74f1 236 _filterFrequency = frequency;
tnhnrl 62:d502889e74f1 237 _filter.writeWn(frequency);
tnhnrl 62:d502889e74f1 238 }
tnhnrl 73:f6f378311c8d 239
tnhnrl 73:f6f378311c8d 240 float LinearActuator::getFilterFrequency() {
tnhnrl 73:f6f378311c8d 241 return _filterFrequency; //new 7/11/18
tnhnrl 73:f6f378311c8d 242 }
tnhnrl 62:d502889e74f1 243
tnhnrl 62:d502889e74f1 244 int LinearActuator::dist_to_counts(float dist) {
tnhnrl 62:d502889e74f1 245 float conv = (dist/_slope)+_zeroCounts;
tnhnrl 62:d502889e74f1 246 return (int) conv;
tnhnrl 62:d502889e74f1 247 }
tnhnrl 62:d502889e74f1 248
tnhnrl 62:d502889e74f1 249 float LinearActuator::counts_to_velocity(int count) {
tnhnrl 62:d502889e74f1 250 float conv = count*_slope;
tnhnrl 62:d502889e74f1 251 return conv;
tnhnrl 62:d502889e74f1 252 }
tnhnrl 62:d502889e74f1 253
tnhnrl 62:d502889e74f1 254 void LinearActuator::_switchPressed() {
tnhnrl 62:d502889e74f1 255 //first thing to do is stop the motor
tnhnrl 62:d502889e74f1 256 _motor.stop();
tnhnrl 62:d502889e74f1 257 _limit = true;
tnhnrl 62:d502889e74f1 258 }
tnhnrl 62:d502889e74f1 259
tnhnrl 62:d502889e74f1 260 void LinearActuator::homePiston() {
tnhnrl 74:d281aaef9766 261 //system is already active, input readings should be valid
tnhnrl 62:d502889e74f1 262
tnhnrl 62:d502889e74f1 263 // This sends the motor on a kamakaze mission toward the limit switch
tnhnrl 62:d502889e74f1 264 // The interrupt should catch and stop it, and the piston is now at home
tnhnrl 62:d502889e74f1 265 // position
tnhnrl 74:d281aaef9766 266
tnhnrl 74:d281aaef9766 267 //unpause the motor (activate it)
tnhnrl 74:d281aaef9766 268 unpause();
tnhnrl 74:d281aaef9766 269
tnhnrl 75:92e79d23d29a 270 _motor.run(-0.5);
tnhnrl 74:d281aaef9766 271
tnhnrl 74:d281aaef9766 272 xbee().printf("HOMING SEQUENCE ENGAGED. Press \"X\" to exit!\n\r");
tnhnrl 62:d502889e74f1 273
tnhnrl 62:d502889e74f1 274 while (1) {
tnhnrl 62:d502889e74f1 275 //trap the program here while we wait for the limit switch to be triggered
tnhnrl 62:d502889e74f1 276 //when it does, the limit interrupt will stop the motors
tnhnrl 62:d502889e74f1 277 if (_limit) {
tnhnrl 74:d281aaef9766 278 xbee().printf("\r\nHit limit switch\r\n");
tnhnrl 62:d502889e74f1 279 //the switch has been pressed
tnhnrl 62:d502889e74f1 280 if (abs(_filter.getVelocity()) < 0.1) {
tnhnrl 62:d502889e74f1 281 //this is here to make sure the adc filter is not jittering around
tnhnrl 62:d502889e74f1 282 //we are probably stable enough to take a zero here
tnhnrl 74:d281aaef9766 283
tnhnrl 74:d281aaef9766 284 _zeroCounts = _filter.getPosition() + 50; //get position of motors
tnhnrl 74:d281aaef9766 285
tnhnrl 74:d281aaef9766 286 //Added 50 counts for some margin of error
tnhnrl 62:d502889e74f1 287
tnhnrl 62:d502889e74f1 288 // This can be used for troubleshooting
tnhnrl 74:d281aaef9766 289 xbee().printf("\n\rzero_counts: %4i \n\r" , _zeroCounts);
tnhnrl 74:d281aaef9766 290
tnhnrl 74:d281aaef9766 291 //pause the motor (deactivate it)
tnhnrl 74:d281aaef9766 292 pause();
tnhnrl 74:d281aaef9766 293
tnhnrl 74:d281aaef9766 294 break; //end while loop
tnhnrl 74:d281aaef9766 295 }
tnhnrl 74:d281aaef9766 296 } //end of limit switch if statement
tnhnrl 74:d281aaef9766 297
tnhnrl 74:d281aaef9766 298 if (xbee().readable()) {
tnhnrl 74:d281aaef9766 299 char user_input = xbee().getc();
tnhnrl 74:d281aaef9766 300
tnhnrl 74:d281aaef9766 301 if (user_input == 'x' or user_input == 'X') {
tnhnrl 74:d281aaef9766 302 xbee().printf("EXIT! HOMING NOT COMPLETE!\n\r");
tnhnrl 74:d281aaef9766 303 break; //end while loop
tnhnrl 74:d281aaef9766 304 }
tnhnrl 74:d281aaef9766 305
tnhnrl 74:d281aaef9766 306 else if (user_input == 'c' or user_input == 'C') {
tnhnrl 74:d281aaef9766 307 xbee().printf("Current counts: %d\n\r", _filter.getPosition());
tnhnrl 62:d502889e74f1 308 }
tnhnrl 62:d502889e74f1 309 }
tnhnrl 62:d502889e74f1 310 }
tnhnrl 62:d502889e74f1 311 }
tnhnrl 62:d502889e74f1 312
tnhnrl 62:d502889e74f1 313 bool LinearActuator::getSwitch() {
tnhnrl 62:d502889e74f1 314 return _limit;
tnhnrl 62:d502889e74f1 315 }
tnhnrl 65:2ac186553959 316
tnhnrl 65:2ac186553959 317 bool LinearActuator::getHardwareSwitchStatus() {
tnhnrl 65:2ac186553959 318 return _limitSwitch.read();
tnhnrl 65:2ac186553959 319 }
tnhnrl 62:d502889e74f1 320
tnhnrl 62:d502889e74f1 321 void LinearActuator::setDeadband(float deadband) {
tnhnrl 62:d502889e74f1 322 _deadband = deadband;
tnhnrl 62:d502889e74f1 323 _pid.setDeadBand(_deadband);
tnhnrl 62:d502889e74f1 324 return;
tnhnrl 62:d502889e74f1 325 }
tnhnrl 62:d502889e74f1 326
tnhnrl 62:d502889e74f1 327 float LinearActuator::getDeadband() {
tnhnrl 62:d502889e74f1 328 return _deadband;
tnhnrl 62:d502889e74f1 329 }
tnhnrl 62:d502889e74f1 330
tnhnrl 62:d502889e74f1 331 bool LinearActuator::toggleDeadband(bool toggle) {
tnhnrl 62:d502889e74f1 332 _pid.toggleDeadBand(toggle);
tnhnrl 62:d502889e74f1 333 return toggle;
tnhnrl 62:d502889e74f1 334 }
tnhnrl 62:d502889e74f1 335
tnhnrl 62:d502889e74f1 336 void LinearActuator::setPIDHighLimit(float high_limit) {
tnhnrl 62:d502889e74f1 337 _pid_high_limit = high_limit;
tnhnrl 62:d502889e74f1 338 _pid.setHiLimit(_pid_high_limit);
tnhnrl 62:d502889e74f1 339 }
tnhnrl 62:d502889e74f1 340
tnhnrl 62:d502889e74f1 341 void LinearActuator::setPIDLowLimit(float low_limit) {
tnhnrl 62:d502889e74f1 342 _pid_low_limit = low_limit;
tnhnrl 62:d502889e74f1 343 _pid.setLoLimit(_pid_low_limit); //default at zero, or the switch retracted
tnhnrl 62:d502889e74f1 344 }