Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed MODSERIAL FATFileSystem
Diff: LinearActuator/LinearActuator.cpp
- Revision:
- 9:d5fcdcb3c89d
- Child:
- 10:085ab7328054
diff -r 70412939a506 -r d5fcdcb3c89d LinearActuator/LinearActuator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LinearActuator/LinearActuator.cpp Fri Oct 20 11:41:22 2017 +0000 @@ -0,0 +1,343 @@ +#include "mbed.h" +#include "LinearActuator.hpp" +#include "StaticDefs.hpp" +#include "ConfigFile.h" + +LinearActuator::LinearActuator(float interval, PinName pwm, PinName dir, PinName reset, PinName limit, int adc_ch): + _motor(pwm, dir, reset), + _filter(), + _pid(), + //_time(), + _pulse(), + _limitSwitch(limit) +{ + _limitSwitch.fall(callback(this, &LinearActuator::_switchPressed)); + // this is where the variables that can be set are set when the object is created + _Pgain = 0.10; + _Igain = 0.0; + _Dgain = 0.0; + + _filterFrequency = 1.0; + + _adc_channel = adc_ch; + + _dt = interval; + + _init = true; + _paused = false; + _limit = false; + _slope = 498.729/4096; //this value should be correct for our current string pots using .625" diameter and 12 bit ADC + _deadband = 0.5; + +} + +void LinearActuator::init() +{ + // initialize and start all of the member objects. + // The pos-velocity filter for this item needs to be allowed to converge + // Before turning over control to the motor + // make sure that adc().init is called in mainline code before calling this function + + //load gains into pid controller this should eventually be in a config file + setFilterFrequency(_filterFrequency); + setControllerP(_Pgain); + setControllerI(_Igain); + setControllerD(_Dgain); + + //setup the controller object + //set deadband and limits + toggleDeadband(true); + setDeadband(_deadband); + +} + +void LinearActuator::update() +{ + + + //update the position velocity filter + if (_adc_channel == 0) { + _filter.update(_dt, adc().readCh0()); + } else if (_adc_channel == 1) { + _filter.update(_dt, adc().readCh1()); + } else { + error("\n\r This ADC channel does not exist"); + } + + //refresh the filter results and load into class variables + refreshPVState(); + + // update the PID controller with latest data + _pid.update(_position_mm, _velocity_mms, _filter.getDt()); + + if (_init) { + //The initialization phase is active + //dont run the motors until the velocity stabilizes + if (abs(_velocity_mms)<0.1) { + //we must be converged and can now release the motor controls + _init = false; + } + } else if (_limit) { + //if you end up here, an interrupt was triggered by an edge detection + //case on the limit switch. That function would have stopped the motor + //This logic should allow it to be re-enabled if the output being asked + //for by the controller is the correct direction. + + if (_pid.getOutput() < 0.0) { //a negative pid output results in motion toward the switch + //dont let the motor run + return; + } else { + //We are now trucking along in the correct direction, it is ok to + //reset the limit variable and allow the motor to run + _limit = false; + } + } else if (_paused) { + //if you get here, the pause function has stopped the motor + //the only way out is for a function call to unpause the motor + //this case also keeps the controller disconnected in the event that + //homing is happening + return; + } + + else { + //pipe controller data into the motor driver + //check that the limit switch is not pressed and if it is only let the + //motor run if the command is a negative number + //this catches the case where the piston is being moved off of the switch + //and the motor command reverses for some reason + + if ((_limitSwitch.read() == 0) && (_pid.getOutput()< 0)) { + //dont run + return; + } + _motor.run(_pid.getOutput()); + } +} + +void LinearActuator::start() +{ + _init = true; + _pulse.attach(this,&LinearActuator::update, _dt); + +} + +void LinearActuator::stop() +{ + _motor.stop(); + _pulse.detach(); +} + +void LinearActuator::pause() +{ + //this allows the controller to keep running while turning off the motor output + _motor.stop(); + //paused flag causes controller output not to be piped to the motor + _paused = true; +} + +void LinearActuator::unpause() +{ + //this resumes motor operation + _paused = false; +} + +void LinearActuator::refreshPVState() +{ + _position = _filter.getPosition(); + _velocity = _filter.getVelocity(); + + _position_mm = counts_to_dist(_position); + _velocity_mms = counts_to_velocity(_velocity); + +// _position_mL = _mm_to_mL(_position_mm); +// _velocity_mLs = _mm_to_mL(_velocity_mms); + +} + +// setting and getting variables +void LinearActuator::setPosition_mm(float dist) +{ + // convert mm representation to volume in mL +// _SetPoint_mL = _mm_to_mL(dist); + _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 + + _pid.writeSetPoint(_SetPoint_mm); + +} + +float LinearActuator::getPosition_mm() +{ + return _position_mm; +} + +float LinearActuator::getPosition_counts() +{ + return _position; // returns raw adc counts (useful for zeroing) +} + +float LinearActuator::getVelocity_mms() +{ + return _velocity_mms; +} + +void LinearActuator::setControllerP(float P) +{ + _Pgain = P; + _pid.setPgain(_Pgain); + return; +} + +float LinearActuator::getControllerP() +{ + return _Pgain; +} + +void LinearActuator::setControllerI(float I) +{ + _Igain = I; + _pid.setIgain(_Igain); + return; +} + +float LinearActuator::getControllerI() +{ + return _Igain; +} + +void LinearActuator::setControllerD(float D) +{ + _Dgain = D; + _pid.setDgain(_Dgain); + return; +} + +float LinearActuator::getControllerD() +{ + return _Dgain; +} + +float LinearActuator::getOutput() +{ + return _pid.getOutput(); +} + +void LinearActuator::setZeroCounts(int zero) +{ + _zeroCounts = clamp<int>(zero, 0, 4096); + return; +} + +int LinearActuator::getZeroCounts() +{ + return _zeroCounts; +} + +void LinearActuator::setTravelLimit(float limit) +{ + _extendLimit = limit; + return; +} + +float LinearActuator::getTravelLimit() +{ + return _extendLimit; +} + +void LinearActuator::setPotSlope(float slope) +{ + _slope = slope; + return; +} + +float LinearActuator::getPotSlope() +{ + return _slope; +} + +float LinearActuator::counts_to_dist(int count) +{ + float conv = _slope*(count-_zeroCounts); + return conv; +} + +void LinearActuator::setFilterFrequency(float frequency) +{ + _filterFrequency = frequency; + _filter.writeWn(frequency); +} + +int LinearActuator::dist_to_counts(float dist) +{ + float conv = (dist/_slope)+_zeroCounts; + return (int) conv; +} + +float LinearActuator::counts_to_velocity(int count) +{ + float conv = count*_slope; + return conv; +} + +void LinearActuator::_switchPressed() +{ + //first thing to do is stop the motor + _motor.stop(); + _limit = true; +} + +void LinearActuator::homePiston() +{ + //start calling the update for the Linear Actuator + //start the controller update and immediatley pause the motor output + start(); + pause(); + + //trap program execution here until the filter is converged + while(_init){ + //just wait here until the things calm down + } + + //Now that the readings are stabilized + // This sends the motor on a kamakaze mission toward the limit switch + // The interrupt should catch and stop it and the piston is now at home + //position + _motor.run(-1.0); + + while (1) { + //trap the program here while we wait for the limit switch to be triggered + //when it does, the limit interrupt will stop the motors + if (_limit) { + //the switch has been pressed + if (abs(_filter.getVelocity()) < 0.1) { + //this is here to make sure the adc filter is not jittering around + //we are probably stable enough to take a zero here + _zeroCounts = _filter.getPosition(); + + // This can be used for troubleshooting + //pc().printf("\n\rzero_counts: %4i \n\r" , _zeroCounts); + //stop the update loop + stop(); + return; + } + } + } +} + +bool LinearActuator::getSwitch() +{ + return _limit; +} + + void LinearActuator::setDeadband(float deadband) +{ + _deadband = deadband; + _pid.setDeadBand(_deadband); + return; +} + +bool LinearActuator::toggleDeadband(bool toggle) +{ + _pid.toggleDeadBand(toggle); + return toggle; +} + \ No newline at end of file