Control up to two motors using filtered EMG signals and a PID controller

Dependencies:   FastPWM HIDScope MODSERIAL QEI Matrix biquadFilter controller errorFetch mbed motorConfig refGen MatrixMath inverseKinematics

Fork of Minor_test_serial by First Last

Committer:
tvlogman
Date:
Fri Oct 06 05:29:52 2017 +0000
Revision:
19:f08b5cd2b7ce
Parent:
17:616ce7bc1f96
Child:
20:4ce3fb543a45
Added clarifying comments and (probably) fixed motor direction problems. Needs testing!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vsluiter 0:c8f15874531b 1 #include "mbed.h"
vsluiter 0:c8f15874531b 2 #include "MODSERIAL.h"
tvlogman 8:0067469c3389 3 #include "HIDScope.h"
tvlogman 9:5f0e796c9489 4 #include "QEI.h"
tvlogman 15:b76b8cff4d8f 5 #include "FastPWM.h"
tvlogman 15:b76b8cff4d8f 6
tvlogman 15:b76b8cff4d8f 7 enum robotStates {KILLED, ACTIVE};
tvlogman 15:b76b8cff4d8f 8 robotStates currentState = KILLED;
tvlogman 8:0067469c3389 9
tvlogman 12:0462757e1ed2 10 QEI Encoder(D12,D13,NC,64, QEI::X4_ENCODING);
tvlogman 10:e23cbcdde7e3 11 MODSERIAL pc(USBTX, USBRX);
tvlogman 8:0067469c3389 12
tvlogman 14:664870b5d153 13 // Defining outputs
tvlogman 13:83e3672b24ee 14 DigitalOut motor1_direction(D4);
tvlogman 13:83e3672b24ee 15 PwmOut motor1_pwm(D5);
tvlogman 14:664870b5d153 16
tvlogman 14:664870b5d153 17 // Defining inputs
tvlogman 14:664870b5d153 18 InterruptIn sw2(SW2);
tvlogman 15:b76b8cff4d8f 19 InterruptIn sw3(SW3);
tvlogman 16:27430afe663e 20 InterruptIn button1(D2);
tvlogman 15:b76b8cff4d8f 21 AnalogIn pot(A0);
tvlogman 15:b76b8cff4d8f 22
tvlogman 16:27430afe663e 23 // PWM settings
tvlogman 16:27430afe663e 24 float pwmPeriod = 1.0/5000.0;
tvlogman 16:27430afe663e 25 int frequency_pwm = 10000; //10kHz PWM
tvlogman 14:664870b5d153 26
tvlogman 16:27430afe663e 27 volatile float x;
tvlogman 16:27430afe663e 28 volatile float x_prev =0;
tvlogman 16:27430afe663e 29 volatile float y; // filtered 'output' of ReadAnalogInAndFilter
tvlogman 14:664870b5d153 30
tvlogman 17:616ce7bc1f96 31 // Initializing encoder
tvlogman 10:e23cbcdde7e3 32 Ticker encoderTicker;
tvlogman 19:f08b5cd2b7ce 33 Ticker controllerTicker;
tvlogman 10:e23cbcdde7e3 34 volatile int counts = 0;
tvlogman 12:0462757e1ed2 35 volatile float revs = 0.00;
tvlogman 7:1bffab95fc5f 36
tvlogman 19:f08b5cd2b7ce 37 // MOTOR CONTROL PART
tvlogman 19:f08b5cd2b7ce 38
tvlogman 19:f08b5cd2b7ce 39 // Function getReferenceVelocity returns reference r between -8.4 and 8.4 rad/s
tvlogman 19:f08b5cd2b7ce 40 float getReferenceVelocity(){
tvlogman 19:f08b5cd2b7ce 41 const float maxVelocity = 8.4; // max velocity in rad/s
tvlogman 19:f08b5cd2b7ce 42 double r;
tvlogman 19:f08b5cd2b7ce 43 if(motor1_direction = false){
tvlogman 19:f08b5cd2b7ce 44 // Clockwise rotation yields positive reference
tvlogman 19:f08b5cd2b7ce 45 r = maxVelocity*pot.read();
tvlogman 19:f08b5cd2b7ce 46 }
tvlogman 19:f08b5cd2b7ce 47 if(motor1_direction = true){
tvlogman 19:f08b5cd2b7ce 48 // Counterclockwise rotation yields negative reference
tvlogman 19:f08b5cd2b7ce 49 r = -1*maxVelocity*pot.read();
tvlogman 19:f08b5cd2b7ce 50 }
tvlogman 19:f08b5cd2b7ce 51 return r;
tvlogman 19:f08b5cd2b7ce 52 }
tvlogman 19:f08b5cd2b7ce 53
tvlogman 19:f08b5cd2b7ce 54 // motorController sets a motorValue based on the reference. Sign indicates direction and magnitude indicates speed. Right now this is a simple feedforward
tvlogman 19:f08b5cd2b7ce 55 float motorController(float reference){
tvlogman 19:f08b5cd2b7ce 56 const float motorGain = 8.4; // max power of the motor should normalize to a motorValue magnitude of 1
tvlogman 19:f08b5cd2b7ce 57 double motorValue = reference/motorGain; // motorValue is the normalized voltage applied to motor magnitude pin between -1 and 1
tvlogman 19:f08b5cd2b7ce 58 return motorValue;
tvlogman 10:e23cbcdde7e3 59 }
tvlogman 14:664870b5d153 60
tvlogman 19:f08b5cd2b7ce 61 // setMotor1 sets the direction and magnitude pins of motor1 depending on the given motorValue. Negative motorValue means clockwise rotation
tvlogman 19:f08b5cd2b7ce 62 void setMotor1(float motorValue){
tvlogman 19:f08b5cd2b7ce 63 switch(currentState){
tvlogman 19:f08b5cd2b7ce 64 case KILLED:
tvlogman 19:f08b5cd2b7ce 65 motor1_pwm.write(0.0);
tvlogman 19:f08b5cd2b7ce 66 break;
tvlogman 19:f08b5cd2b7ce 67 case ACTIVE:
tvlogman 19:f08b5cd2b7ce 68 // Set motor direction
tvlogman 19:f08b5cd2b7ce 69 if (motorValue >=0){
tvlogman 19:f08b5cd2b7ce 70 motor1_direction = 0;
tvlogman 19:f08b5cd2b7ce 71 }
tvlogman 19:f08b5cd2b7ce 72 else {
tvlogman 19:f08b5cd2b7ce 73 motor1_direction = 1;
tvlogman 19:f08b5cd2b7ce 74 }
tvlogman 19:f08b5cd2b7ce 75 // Set motor speed
tvlogman 19:f08b5cd2b7ce 76 if (fabs(motorValue)>1){
tvlogman 19:f08b5cd2b7ce 77 motor1_pwm = 1;
tvlogman 19:f08b5cd2b7ce 78 }
tvlogman 19:f08b5cd2b7ce 79 else {
tvlogman 19:f08b5cd2b7ce 80 motor1_pwm.write(fabs(motorValue));
tvlogman 19:f08b5cd2b7ce 81 }
tvlogman 19:f08b5cd2b7ce 82 break;
tvlogman 19:f08b5cd2b7ce 83 }
tvlogman 19:f08b5cd2b7ce 84 }
tvlogman 19:f08b5cd2b7ce 85
tvlogman 19:f08b5cd2b7ce 86 void measureAndControl(){
tvlogman 19:f08b5cd2b7ce 87 float referenceVelocity = getReferenceVelocity();
tvlogman 19:f08b5cd2b7ce 88 float motorValue = motorController(referenceVelocity);
tvlogman 19:f08b5cd2b7ce 89 pc.printf("Motorvalue is %.2f \r \n", motorValue);
tvlogman 19:f08b5cd2b7ce 90 pc.printf("Motor direction is %d \r \n", motor1_direction);
tvlogman 19:f08b5cd2b7ce 91 setMotor1(motorValue);
tvlogman 19:f08b5cd2b7ce 92 }
tvlogman 19:f08b5cd2b7ce 93
tvlogman 14:664870b5d153 94 void killSwitch(){
tvlogman 15:b76b8cff4d8f 95 pc.printf("Motors turned off");
tvlogman 15:b76b8cff4d8f 96 currentState = KILLED;
tvlogman 14:664870b5d153 97 }
tvlogman 14:664870b5d153 98
tvlogman 15:b76b8cff4d8f 99 void turnMotorsOn(){
tvlogman 15:b76b8cff4d8f 100 pc.printf("Motors turned on");
tvlogman 15:b76b8cff4d8f 101 currentState = ACTIVE;
tvlogman 15:b76b8cff4d8f 102 }
tvlogman 15:b76b8cff4d8f 103
tvlogman 15:b76b8cff4d8f 104
tvlogman 14:664870b5d153 105 void M1switchDirection(){
tvlogman 14:664870b5d153 106 motor1_direction = !motor1_direction;
tvlogman 14:664870b5d153 107 }
vsluiter 0:c8f15874531b 108
tvlogman 19:f08b5cd2b7ce 109 // readEncoder reads counts and revs and logs results to serial window
tvlogman 19:f08b5cd2b7ce 110 void readEncoder(){
tvlogman 19:f08b5cd2b7ce 111 counts = Encoder.getPulses();
tvlogman 19:f08b5cd2b7ce 112 revs = counts/(131*64.0f);
tvlogman 19:f08b5cd2b7ce 113 pc.printf("%0.2f revolutions \r\n", revs);
tvlogman 19:f08b5cd2b7ce 114 float reference = getReferenceVelocity();
tvlogman 19:f08b5cd2b7ce 115 pc.printf("Reference velocity %0.2f \r\n", reference);
tvlogman 19:f08b5cd2b7ce 116 }
tvlogman 19:f08b5cd2b7ce 117
vsluiter 0:c8f15874531b 118 int main()
tvlogman 10:e23cbcdde7e3 119 {
tvlogman 19:f08b5cd2b7ce 120 pc.printf("Main function");
tvlogman 19:f08b5cd2b7ce 121 motor1_direction = false; // False = clockwise rotation
tvlogman 13:83e3672b24ee 122 motor1_pwm.period(pwmPeriod);//T=1/f
tvlogman 14:664870b5d153 123 sw2.fall(&killSwitch);
tvlogman 15:b76b8cff4d8f 124 sw3.fall(&turnMotorsOn);
tvlogman 16:27430afe663e 125 button1.rise(&M1switchDirection);
vsluiter 0:c8f15874531b 126 pc.baud(115200);
tvlogman 19:f08b5cd2b7ce 127 encoderTicker.attach(readEncoder, 2);
tvlogman 19:f08b5cd2b7ce 128 controllerTicker.attach(measureAndControl, 0.1);
tvlogman 15:b76b8cff4d8f 129
tvlogman 19:f08b5cd2b7ce 130 pc.printf("Encoder ticker attached and baudrate set");
vsluiter 0:c8f15874531b 131 }
tvlogman 7:1bffab95fc5f 132