Project BioRobotics Group 19
Dependencies: FastPWM HIDScope MODSERIAL QEI biquadFilter mbed
main.cpp
- Committer:
- jordiluong
- Date:
- 2017-10-23
- Revision:
- 8:78d8ccf84a38
- Parent:
- 7:757e95b4dc46
- Child:
- 10:a9e344e440b8
File content as of revision 8:78d8ccf84a38:
#include "BiQuad.h" #include "FastPWM.h" #include "HIDScope.h" #include <math.h> #include "mbed.h" #include "MODSERIAL.h" #include "QEI.h" const double pi = 3.1415926535897; // Definition of pi // SERIAL COMMUNICATION WITH PC //////////////////////////////////////////////// MODSERIAL pc(USBTX, USBRX); // STATES ////////////////////////////////////////////////////////////////////// enum states{MOTORS_OFF, MOVING, HITTING}; states currentState = MOTORS_OFF; // Start with motors off bool stateChanged = true; // Make sure the initialization of first state is executed // ENCODER ///////////////////////////////////////////////////////////////////// QEI Encoder1(D10,D11,NC,32); // CONNECT ENC1A TO D10, ENC1B TO D11 QEI Encoder2(D12,D13,NC,32); // CONNECT ENC2A TO D12, ENC2B TO D13 // PINS //////////////////////////////////////////////////////////////////////// DigitalOut motor1DirectionPin(D4); // Value 0: CCW; 1: CW PwmOut motor1MagnitudePin(D5); DigitalOut motor2DirectionPin(D7); // Value 0: CW or CCW?; 1: CW or CCW? PwmOut motor2MagnitudePin(D6); InterruptIn button1(D2); // CONNECT BUT1 TO D2 InterruptIn button2(D3); // CONNECT BUT2 TO D3 AnalogIn emg(A0); // MOTOR CONTROL /////////////////////////////////////////////////////////////// Ticker controllerTicker; const double controller_Ts = 1/5000; // Time step for controllerTicker; Should be between 5kHz and 10kHz [s] const double motorRatio = 131.25; // Ratio of the gearbox in the motors [] const double radPerPulse = 2*pi/(32*motorRatio); // Amount of radians the motor rotates per encoder pulse [rad/pulse] // MOTOR 1 double reference1 = 0.0; // Desired rotation of motor 1 [rad] // Controller gains const double motor1_KP = 2.5; // Position gain [] const double motor1_KI = 1.0; // Integral gain [] const double motor1_KD = 0.5; // Derivative gain [] double motor1_err_int = 0, motor1_prev_err = 0; // Derivative filter coefficients const double motor1_f_a1 = 1.0, motor1_f_a2 = 2.0; // Derivative filter coefficients [] const double motor1_f_b0 = 1.0, motor1_f_b1 = 3.0, motor1_f_b2 = 4.0; // Derivative filter coefficients [] // Filter variables double motor1_f_v1 = 0, motor1_f_v2 = 0; // MOTOR 2 // Controller gains // Derivative filter coefficients // Filter variables // EMG FILTER ////////////////////////////////////////////////////////////////// BiQuadChain bqc; BiQuad bq1(0, 0, 0, 0, 0); // EMG filter coefficients [] BiQuad bq2(0, 0, 0, 0, 0); // EMG filter coefficients [] Ticker emgSampleTicker; double emg_Ts = 0.01; // Time step for EMG sampling // FUNCTIONS /////////////////////////////////////////////////////////////////// // EMG ///////////////////////////////////////////////////////////////////////// void EmgSample() { double emgFiltered = bqc.step(emg.read()); // Filter the EMG signal } // BIQUAD FILTER FOR DERIVATIVE OF ERROR /////////////////////////////////////// double biquad(double u, double &v1, double &v2, const double a1, const double a2, const double b0, const double b1, const double b2) { double v = u - a1*v1 - a2*v2; double y = b0*v + b1*v1 + b2*v2; v2 = v1; v1 = v; return y; } // P-CONTROLLER //////////////////////////////////////////////////////////////// double P_Controller(double error, const double Kp) { return Kp * error; } // PID-CONTROLLER WITH FILTER ////////////////////////////////////////////////// double PID_Controller(double e, const double Kp, const double Ki, const double Kd, double Ts, double &e_int, double &e_prev, double &f_v1, double &f_v2, const double f_a1, const double f_a2, const double f_b0, const double f_b1, const double f_b2) { // Derivative double e_der = (e - e_prev)/Ts; // Calculate the derivative of error e_der = biquad(e_der, f_v1, f_v2, f_a1, f_a2, f_b0, f_b1, f_b2); // Filter the derivative of error e_prev = e; // Integral e_int = e_int + Ts*e; // Calculate the integral of error // PID return Kp*e + Ki*e_int + Kd*e_der; } // MOTOR 1 ///////////////////////////////////////////////////////////////////// void RotateMotor1(double motor1Value) { if(currentState == MOVING) // Check if state is MOVING { if(motor1Value >= 0) motor1DirectionPin = 1; // Rotate motor 1 CW else motor1DirectionPin = 0; // Rotate motor 1 CCW if(fabs(motor1Value) > 1) motor1MagnitudePin = 1; else motor1MagnitudePin = fabs(motor1Value); } else motor1MagnitudePin = 0; } // MOTOR 1 P-CONTROLLER //////////////////////////////////////////////////////// void Motor1PController() { double position1 = radPerPulse * Encoder1.getPulses(); // Calculate the rotation of motor 1 double motor1Value = P_Controller(reference1 - position1, motor1_KP); RotateMotor1(motor1Value); } // MOTOR 1 PID-CONTROLLER ////////////////////////////////////////////////////// void Motor1Controller() { double position1 = radPerPulse * Encoder1.getPulses(); double motor1Value = PID_Controller(reference1 - position1, motor1_KP, motor1_KI, motor1_KD, controller_Ts, motor1_err_int, motor1_prev_err, motor1_f_v1, motor1_f_v2, motor1_f_a1, motor1_f_a2, motor1_f_b0, motor1_f_b1, motor1_f_b2); RotateMotor1(motor1Value); } // TURN OFF MOTORS ///////////////////////////////////////////////////////////// void TurnMotorsOff() { motor1MagnitudePin = 0; motor2MagnitudePin = 0; } // STATES ////////////////////////////////////////////////////////////////////// void ProcessStateMachine() { switch(currentState) { case MOTORS_OFF: { // State initialization if(stateChanged) { pc.printf("Entering MOTORS_OFF \r\n Press button 1 to enter MOVING \r\n"); TurnMotorsOff(); // Turn motors off stateChanged = false; } // Home command if(!button1) { currentState = MOVING; stateChanged = true; break; } break; } case MOVING: { // State initialization if(stateChanged) { pc.printf("Entering MOVING \r\n Press button 2 to enter HITTING \r\n"); stateChanged = false; } // Hit command if(!button2) { currentState = HITTING; stateChanged = true; break; } break; } case HITTING: { // State initialization if(stateChanged) { pc.printf("Entering HITTING \r\n"); stateChanged = false; //HitBall(); // Hit the ball currentState = MOVING; stateChanged = true; break; } break; } default: { TurnMotorsOff(); // Turn motors off for safety break; } } } // MAIN FUNCTION /////////////////////////////////////////////////////////////// int main() { // Serial communication pc.baud(115200); pc.printf("START \r\n"); bqc.add(&bq1).add(&bq2); // Make BiQuad Chain controllerTicker.attach(&Motor1PController, controller_Ts); // Ticker to control motor 1 //controllerTicker.attach(&Motor1Controller, controller_Ts); emgSampleTicker.attach(&EmgSample, emg_Ts); // Ticker to sample EMG while(true) { ProcessStateMachine(); // Execute states function } }