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:
74:d281aaef9766
version for first flight test, timeouts not yet set correctly

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tnhnrl 52:f207567d3ea4 1 // modifications by Dan 2018-02-28
tnhnrl 52:f207567d3ea4 2 // - mostly formatting consistency for readability
tnhnrl 52:f207567d3ea4 3 // - changed ServoDriver initial _valid_servo_position to the _center_pwm value
tnhnrl 52:f207567d3ea4 4 // - fixed problems with servo mapping function.
tnhnrl 52:f207567d3ea4 5 // -- made min_pwm match to min_deg, even if min_pwm is greater than max_pwm
tnhnrl 52:f207567d3ea4 6 // -- made max_pwm match to max_deg, even if max_pwm is less than min_pwm
tnhnrl 52:f207567d3ea4 7 // -- now linear mapping between min pwm/deg, center_pwm/0deg, max pwm/deg.
tnhnrl 52:f207567d3ea4 8
tnhnrl 52:f207567d3ea4 9 #include "ServoDriver.hpp"
tnhnrl 52:f207567d3ea4 10
tnhnrl 52:f207567d3ea4 11 // INNER LOOP ServoDriver has settings, endpoints, direction, neutral point
tnhnrl 52:f207567d3ea4 12
tnhnrl 52:f207567d3ea4 13 //this driver does not use pwmOut because of the period timer conflict with the H-bridge motor controllers
tnhnrl 52:f207567d3ea4 14
tnhnrl 52:f207567d3ea4 15 // initialize default calibration/parameter values
tnhnrl 52:f207567d3ea4 16 // note: (min_deg < max_deg) must be true!
tnhnrl 52:f207567d3ea4 17 ServoDriver::ServoDriver(PinName digital_pin) : _pwm_out(digital_pin) {
tnhnrl 52:f207567d3ea4 18 _period_cnt = 0;
tnhnrl 74:d281aaef9766 19 _center_pwm = 1640.0; // mechanical center trimmed to be 1.5ms (1500us)
tnhnrl 52:f207567d3ea4 20 _min_deg = -45.0; // lower deflection against end stop
tnhnrl 52:f207567d3ea4 21 _max_deg = 45.0; // upper deflection against end stop
tnhnrl 52:f207567d3ea4 22 _min_pwm = 2240.0; // pwm corresponding to _min_deg
tnhnrl 52:f207567d3ea4 23 _max_pwm = 1040.0; // pwm corresponding to _max_deg
tnhnrl 52:f207567d3ea4 24
tnhnrl 52:f207567d3ea4 25 _valid_servo_position_pwm = (unsigned int)_center_pwm; // servo position on boot-up
tnhnrl 74:d281aaef9766 26
tnhnrl 74:d281aaef9766 27 _paused = false;
tnhnrl 52:f207567d3ea4 28 }
tnhnrl 52:f207567d3ea4 29
tnhnrl 52:f207567d3ea4 30 /////////////////////////////////////////////////////////////////////////////
tnhnrl 52:f207567d3ea4 31 // PWM TIMING SETUP AND SUPPORT FUNCTIONS
tnhnrl 52:f207567d3ea4 32
tnhnrl 52:f207567d3ea4 33 // initialize the ticker that will pulse on, start an off ticker, off-ticker pulses off and detaches, rinse and repeat
tnhnrl 52:f207567d3ea4 34 void ServoDriver::init() {
tnhnrl 52:f207567d3ea4 35 }
tnhnrl 52:f207567d3ea4 36
tnhnrl 52:f207567d3ea4 37 void ServoDriver::runServo() {
tnhnrl 52:f207567d3ea4 38 pwm_pulse_on();
tnhnrl 52:f207567d3ea4 39 }
tnhnrl 52:f207567d3ea4 40
tnhnrl 52:f207567d3ea4 41 void ServoDriver::pwm_pulse_off() {
tnhnrl 52:f207567d3ea4 42 _pwm_out = 0; //changed the pulse on and off to TIMEOUT so you don't have to detach anything
tnhnrl 52:f207567d3ea4 43 }
tnhnrl 52:f207567d3ea4 44
tnhnrl 52:f207567d3ea4 45 void ServoDriver::pwm_pulse_on() {
tnhnrl 74:d281aaef9766 46 if (_paused) {
tnhnrl 74:d281aaef9766 47 pwm_pulse_off_timeout.detach();
tnhnrl 74:d281aaef9766 48 }
tnhnrl 74:d281aaef9766 49 else {
tnhnrl 74:d281aaef9766 50 pwm_pulse_off_timeout.attach_us(callback(this, &ServoDriver::pwm_pulse_off), _valid_servo_position_pwm); // _valid_servo_position_pwm is the signal in microseconds, e.g. 1500
tnhnrl 74:d281aaef9766 51 }
tnhnrl 52:f207567d3ea4 52 _pwm_out = 1;
tnhnrl 52:f207567d3ea4 53 }
tnhnrl 52:f207567d3ea4 54
tnhnrl 52:f207567d3ea4 55 void ServoDriver::pause() {
tnhnrl 74:d281aaef9766 56 //pwm_pulse_on_ticker.detach(); //run a pwm pulse on a digital out pin that has a period of 20 ms
tnhnrl 52:f207567d3ea4 57 }
tnhnrl 52:f207567d3ea4 58
tnhnrl 52:f207567d3ea4 59 void ServoDriver::unpause() {
tnhnrl 74:d281aaef9766 60 //init();
tnhnrl 52:f207567d3ea4 61 }
tnhnrl 52:f207567d3ea4 62
tnhnrl 52:f207567d3ea4 63 // SERVO OUTPUT MAPPING
tnhnrl 52:f207567d3ea4 64
tnhnrl 52:f207567d3ea4 65 // this function converts a desired degree location into a PWM command
tnhnrl 52:f207567d3ea4 66 void ServoDriver::setPosition_deg(float input_deg) {
tnhnrl 52:f207567d3ea4 67 // make sure desired angle is within the min and max deflection angles
tnhnrl 52:f207567d3ea4 68 _degrees_set_position = servoClamp<float>(input_deg, _min_deg, _max_deg);
tnhnrl 52:f207567d3ea4 69
tnhnrl 52:f207567d3ea4 70 // servo calibration
tnhnrl 52:f207567d3ea4 71 // slope is pwm signal over degrees (y = mx + b) using linear fit
tnhnrl 52:f207567d3ea4 72 // different slopes for above or below center!
tnhnrl 52:f207567d3ea4 73 float slope;
tnhnrl 52:f207567d3ea4 74 if (_degrees_set_position > 0)
tnhnrl 52:f207567d3ea4 75 slope = (_center_pwm - _min_pwm) / (-_min_deg);
tnhnrl 52:f207567d3ea4 76
tnhnrl 52:f207567d3ea4 77 else if (_degrees_set_position < 0)
tnhnrl 52:f207567d3ea4 78 slope = (_max_pwm - _center_pwm) / (_max_deg);
tnhnrl 52:f207567d3ea4 79
tnhnrl 52:f207567d3ea4 80 else
tnhnrl 52:f207567d3ea4 81 slope = 0.0;
tnhnrl 52:f207567d3ea4 82
tnhnrl 52:f207567d3ea4 83 // calculate linear servo response (output = slope*input + offset)
tnhnrl 52:f207567d3ea4 84 // negative slope needed for correct direction response
tnhnrl 52:f207567d3ea4 85 float initial_output = (slope * _degrees_set_position) + _center_pwm;
tnhnrl 52:f207567d3ea4 86
tnhnrl 52:f207567d3ea4 87 // saturate the pwm output to the min/max pwm limits
tnhnrl 52:f207567d3ea4 88 // remember the min/max pwm values may not be (min < max)
tnhnrl 74:d281aaef9766 89 // Basically handles the direction of movement
tnhnrl 52:f207567d3ea4 90 if (_max_pwm > _min_pwm)
tnhnrl 52:f207567d3ea4 91 _valid_servo_position_pwm = servoClamp<float>(initial_output, _min_pwm, _max_pwm);
tnhnrl 52:f207567d3ea4 92
tnhnrl 52:f207567d3ea4 93 else if (_max_pwm < _min_pwm)
tnhnrl 52:f207567d3ea4 94 _valid_servo_position_pwm = servoClamp<float>(initial_output, _max_pwm, _min_pwm);
tnhnrl 74:d281aaef9766 95 }
tnhnrl 74:d281aaef9766 96
tnhnrl 74:d281aaef9766 97 //the comparison below is used to swap the rotation of the servo
tnhnrl 74:d281aaef9766 98
tnhnrl 74:d281aaef9766 99 void ServoDriver::setPWM(float input_pwm) {
tnhnrl 74:d281aaef9766 100 if (_max_pwm > _min_pwm)
tnhnrl 74:d281aaef9766 101 _valid_servo_position_pwm = (unsigned int) servoClamp<float>(input_pwm, _min_pwm, _max_pwm); //volatile unsigned int
tnhnrl 52:f207567d3ea4 102
tnhnrl 74:d281aaef9766 103 else if (_min_pwm > _max_pwm)
tnhnrl 74:d281aaef9766 104 _valid_servo_position_pwm = (unsigned int) servoClamp<float>(input_pwm, _max_pwm, _min_pwm); //volatile unsigned int
tnhnrl 52:f207567d3ea4 105 }
tnhnrl 52:f207567d3ea4 106
tnhnrl 52:f207567d3ea4 107 ///////////////////////////////////////////////////////////////////////////
tnhnrl 52:f207567d3ea4 108 // SETTING PARAMETERS
tnhnrl 52:f207567d3ea4 109 void ServoDriver::setMinPWM(float pwm_input) {
tnhnrl 52:f207567d3ea4 110 _min_pwm = pwm_input;
tnhnrl 52:f207567d3ea4 111 }
tnhnrl 52:f207567d3ea4 112
tnhnrl 52:f207567d3ea4 113 void ServoDriver::setMaxPWM(float pwm_input) {
tnhnrl 52:f207567d3ea4 114 _max_pwm = pwm_input;
tnhnrl 52:f207567d3ea4 115 }
tnhnrl 52:f207567d3ea4 116
tnhnrl 52:f207567d3ea4 117 void ServoDriver::setCenterPWM(float pwm_input) {
tnhnrl 52:f207567d3ea4 118 _center_pwm = pwm_input;
tnhnrl 52:f207567d3ea4 119 }
tnhnrl 52:f207567d3ea4 120
tnhnrl 52:f207567d3ea4 121 void ServoDriver::setMinDeg(float deg) {
tnhnrl 52:f207567d3ea4 122 _min_deg = deg;
tnhnrl 52:f207567d3ea4 123 }
tnhnrl 52:f207567d3ea4 124
tnhnrl 52:f207567d3ea4 125 void ServoDriver::setMaxDeg(float deg) {
tnhnrl 52:f207567d3ea4 126 _max_deg = deg;
tnhnrl 52:f207567d3ea4 127 }
tnhnrl 52:f207567d3ea4 128
tnhnrl 52:f207567d3ea4 129 ///////////////////////////////////////////////////////////////////////////
tnhnrl 52:f207567d3ea4 130 // READING PARAMETERS
tnhnrl 74:d281aaef9766 131 float ServoDriver::getSetPosition_deg() { //rename to getSetPosition later for consistency
tnhnrl 52:f207567d3ea4 132 return _degrees_set_position;
tnhnrl 52:f207567d3ea4 133 }
tnhnrl 52:f207567d3ea4 134
tnhnrl 52:f207567d3ea4 135 // returns pwm signal in microseconds, for example: 1580 microseconds
tnhnrl 74:d281aaef9766 136 float ServoDriver::getSetPosition_pwm() {
tnhnrl 52:f207567d3ea4 137 return (float)_valid_servo_position_pwm; //servo is unsigned int
tnhnrl 52:f207567d3ea4 138 }
tnhnrl 52:f207567d3ea4 139
tnhnrl 52:f207567d3ea4 140 float ServoDriver::getMinPWM() {
tnhnrl 52:f207567d3ea4 141 return _min_pwm;
tnhnrl 52:f207567d3ea4 142 }
tnhnrl 52:f207567d3ea4 143
tnhnrl 52:f207567d3ea4 144 float ServoDriver::getMaxPWM() {
tnhnrl 52:f207567d3ea4 145 return _max_pwm;
tnhnrl 52:f207567d3ea4 146 }
tnhnrl 52:f207567d3ea4 147
tnhnrl 52:f207567d3ea4 148 float ServoDriver::getCenterPWM() {
tnhnrl 52:f207567d3ea4 149 return _center_pwm;
tnhnrl 52:f207567d3ea4 150 }
tnhnrl 52:f207567d3ea4 151
tnhnrl 52:f207567d3ea4 152 float ServoDriver::getMinDeg() {
tnhnrl 52:f207567d3ea4 153 return _min_deg;
tnhnrl 52:f207567d3ea4 154 }
tnhnrl 52:f207567d3ea4 155
tnhnrl 52:f207567d3ea4 156 float ServoDriver::getMaxDeg() {
tnhnrl 52:f207567d3ea4 157 return _max_deg;
tnhnrl 52:f207567d3ea4 158 }