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.
Revision 0:929eee0b13f2, committed 2018-08-14
- Comitter:
- electromotivated
- Date:
- Tue Aug 14 17:14:36 2018 +0000
- Commit message:
- Init;
Changed in this revision
diff -r 000000000000 -r 929eee0b13f2 PID.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PID.lib Tue Aug 14 17:14:36 2018 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/electromotivated/code/PID/#0cf2f6d13c71
diff -r 000000000000 -r 929eee0b13f2 QEI.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QEI.lib Tue Aug 14 17:14:36 2018 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/electromotivated/code/QEI/#50aae578cb89
diff -r 000000000000 -r 929eee0b13f2 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Aug 14 17:14:36 2018 +0000 @@ -0,0 +1,142 @@ +#include "mbed.h" +#include "PID.h" +#include "QEI.h" + +/* + Demo of setting motor speed using encoder in pid feedback. + + Parts used for this demo: + HN-GH12-1634T Gear Motor + LMD18200 H-Bridge Breakout Board + E4P-100-079 Quadrature Encoder + + TODO: Implement a "rolling"/"moving" average in callback + for speed feedback +*/ + +float clip(float value, float lower, float upper); + +static float setpoint, feedback, output; +const float output_lower_limit = -1.0; +const float output_upper_limit = 1.0; +const float FEEDBACK_SCALE = 1.0/3000.0; // Scale feedback to 1rev/3000cnts + +const float kp = 0.01; +const float ki = 0.01; +const float kd = 0.0; +const float Ts = 0.04; // 25Hz Sample Freq (40ms Sample Time); + // Used for PID Sample time and used + // to calculate callback() interrupt + // time + +PID pid(&setpoint, &feedback, &output, output_lower_limit, output_upper_limit, + kp, ki, kd, Ts); +QEI encoder(p15, p16); +PwmOut mtr_pwm(p25); +DigitalOut mtr_dir(p24); +void pid_callback(); // Updates encoder feedback and motor output +Ticker motor; + +int main() { + // Wait for me to plug in motor battery + wait(5); + + // Clear encoder count + encoder.reset(); + + // Init the motor + mtr_dir = 0; // CW + mtr_pwm = 0.0; // Quarter speed + + // Update sensors and feedback twice as fast as PID sample time; + // this makes pid react in real-time avoiding errors due to + // missing counts etc. + motor.attach(&pid_callback, Ts/2.0); + + // Init the pid + /*TODO: Implement PID Change Param Method in the PID class + and use it to init gains here*/ + setpoint = 0.0; + feedback = encoder.read(); + output = 0.0; + pid.start(); + + while(1){ + int flag; + float userInput; + do{ + printf("Enter Speed/RPM (-100.0 to 100.0)\r\n"); + flag = scanf("%f", &userInput); + }while(flag == EOF); + setpoint = userInput; + do{ + printf("Setpoint: %1.2f\t\tFeedback: %1.2f\t\tError: %1.2f\t\tOuput: %1.2f\r\n", + setpoint, feedback, pid.getError(), output); + wait(0.25); + }while(pid.getError() < -0.006 || 0.006 < pid.getError()); + printf("Speed Reached!\r\n"); + printf("Setpoint: %1.2f\t\tFeedback: %1.2f\t\tError: %1.2f\t\tOuput: %1.2f\r\n", + setpoint, feedback, pid.getError(), output); + } +} + +/* + Updates feedback and output, interrupt driven so that paramaters + are updated in real-time, i.e. avoids update lag due to main + code overhead and printfs which can be slow. +*/ +void pid_callback(){ + // Update motor + if(setpoint >= 0.0) mtr_dir = 1; // Set motor direction based on setpoint + else mtr_dir = 0; + if(-0.001 < setpoint && setpoint < 0.001){ + /* Setpoint = 0 is a special case, we allow output to control speed AND + direction to fight intertia and/or downhill roll. */ + if(output >= 0.0) mtr_dir = 1; + else mtr_dir = 0; + mtr_pwm = abs(output); + } + else{ + if(mtr_dir == 1){ // If CW then apply positive outputs + if(output >= 0.0) mtr_pwm = output; + else mtr_pwm = 0.0; + } + else{ // If CCW then apply negative outputs + if(output <= 0.0) mtr_pwm = abs(output); + else mtr_pwm = 0.0; + } + } +// if(mtr_dir == 1){ // If CW then apply positive outputs +// if(output >= 0.0) mtr_pwm = output; +// else mtr_pwm = mtr_pwm.read() - abs(output); // Take negative output value out of full range +// // helps avoid bumpiness in motor +// } +// else{ // If CCW then apply negative outputs +// if(output <= 0.0) mtr_pwm = abs(output); +// else mtr_pwm = mtr_pwm.read() - abs(output); +// } +// + // Running average + float k = Ts/2.0; // Discrete time, (Ts/2 because this callback is called + // at interval of Ts/2... or twice as fast as pid controller) + + /* TODO: Implement a "rolling"/"moving" average */ + static int last_count = 0; + int count = encoder.read(); + float raw_speed = ((count - last_count)*FEEDBACK_SCALE) / k; + float rpm_speed = raw_speed * 60.0; // Convert speed to RPM + + last_count = count; // Save last count + feedback = rpm_speed; +} + +/* + Clips value to lower/ uppper + @param value The value to clip + @param lower The mininum allowable value + @param upper The maximum allowable value + @return The resulting clipped value +*/ +float clip(float value, float lower, float upper){ + return std::max(lower, std::min(value, upper)); +} \ No newline at end of file
diff -r 000000000000 -r 929eee0b13f2 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Tue Aug 14 17:14:36 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/9296ab0bfc11 \ No newline at end of file