StateMachine PTR
Dependencies: MODSERIAL QEI MovingAverage biquadFilter mbed
StateMachinePTR.cpp
- Committer:
- rubenlucas
- Date:
- 2018-10-29
- Revision:
- 2:c2ae5044ec82
- Child:
- 3:97cac1d5ba8a
File content as of revision 2:c2ae5044ec82:
#include "mbed.h" #include "math.h" #include "MODSERIAL.h" #include "QEI.h" #include "BiQuad.h" //states enum States {Waiting, Homing, Emergency,EMGCal,MotorCal,Operation,Demo}; // Global variables States CurrentState; Ticker TickerLoop; Timer TimerLoop; //Communication MODSERIAL pc(USBTX,USBRX); QEI Encoder(D10,D11,NC,32); //Global pin variables Motor 1 PwmOut PwmPin(D5); DigitalOut DirectionPin(D4); AnalogIn Potmeter1(A1); AnalogIn Potmeter2(A0); //Output LED DigitalOut LedRed (LED_RED); DigitalOut LedGreen (LED_GREEN); DigitalOut LedBlue (LED_BLUE); // Buttons DigitalIn Button1(SW2); DigitalIn Button2(SW3); DigitalIn ButtonHome(D8); //Global variables for printing on screen volatile bool PrintFlag = false; volatile float PosRefPrint; // for printing value on screen volatile float PosMotorPrint; // for printing value on screen volatile float ErrorPrint; volatile int PrintCount = 0; volatile float MotorValuePrint; //------------------------------------------------------------------------------ //Functions void StateMachine () { switch (CurrentState) { case Waiting: LedRed = 0; LedGreen = 0; LedBlue = 1; //Yellow break; case Homing: LedRed = 0; LedGreen = 0; LedBlue = 0; //White if (TimerLoop.read() >= 5.0f) {CurrentState = Waiting;} break; case Emergency: LedRed = 0; LedGreen = 1; LedBlue = 1; //Red break; case EMGCal: LedRed = 0; LedGreen = 1; LedBlue = 0; //Pink break; case MotorCal: LedRed = 1; LedGreen = 0; LedBlue = 0; //Turqoise break; case Operation: LedRed = 1; LedGreen = 0; LedBlue = 1; //Green break; case Demo: LedRed = 1; LedGreen = 1; LedBlue = 0; //Blue break; } } //----------------------------------------------------------------------------- //The double-functions //Get reference position double GetReferencePosition() { // This function set the reference position to determine the position of the signal. // a positive position is defined as a counterclockwise (CCW) rotation double ValuePot = Potmeter1.read(); // Read value from potmeter (range from 0-1) double PositionRef = 3*6.2830*ValuePot - 3*3.1415; // position reference ranging from -1.5 rotations till 1.5 rotations return PositionRef; //rad } // actual position of the motor double GetActualPosition() { //This function determines the actual position of the motor //The count:radians relation is 8400:2pi double EncoderCounts = Encoder.getPulses(); //number of counts double PositionMotor = EncoderCounts/8400*(2*6.283); // in rad (6.283 = 2pi), 2* is for compensating X4 --> X2 encoding return PositionMotor; } ///The controller double PID_Controller(double Error) { double Ts = 0.005; //Sampling time 100 Hz double Kp = 5.34; // proportional gain double Ki = 2.0;//integral gain double Kd = 6.9; //derivative gain static double ErrorIntegral = 0; static double ErrorPrevious = Error; static BiQuad LowPassFilter(0.0640, 0.1279, 0.0640, -1.1683, 0.4241); //Proportional part: double u_k = Kp * Error; //Integral part: ErrorIntegral = ErrorIntegral + Error*Ts; double u_i = Ki * ErrorIntegral; //Derivative part: double ErrorDerivative = (Error - ErrorPrevious)/Ts; double FilteredErrorDerivative = LowPassFilter.step(ErrorDerivative); double u_d = Kd * FilteredErrorDerivative; ErrorPrevious = Error; return u_k + u_i + u_d; //This will become the MotorValue } //Ticker function set motorvalues void SetMotor(double MotorValue) { if (MotorValue >=0) { DirectionPin = 1; } else { DirectionPin = 0; } if (fabs(MotorValue)>3) // if error more than 1 radian, full duty cycle { PwmPin = 1; } else { PwmPin = 0; //fabs(MotorValue); } } void SetMotorOff() { PwmPin = 0; // Turn motor off } //----------------------------------------------------------------------------- void MeasureAndControl(void) { double PositionRef = GetReferencePosition(); double PositionMotor = GetActualPosition(); double MotorValue = PID_Controller(PositionRef - PositionMotor); // input is error SetMotor(MotorValue); //for printing on screen PosRefPrint = PositionRef; PosMotorPrint = PositionMotor; ErrorPrint = PositionRef - PositionMotor; MotorValuePrint = MotorValue; } void PrintToScreen() { PrintCount++; if (PrintCount == 100) // printing with 2 Hz {PrintFlag = true; PrintCount = 0;} } // Execution function void LoopFunction() { // buttons if (Button1.read() == false) // if pressed {CurrentState = Operation; TimerLoop.reset();} if (Button2.read() == false) // if pressed {CurrentState = Demo; TimerLoop.reset();} if (ButtonHome.read() == false) // if pressed {CurrentState = Homing; TimerLoop.reset();} //functions StateMachine(); //determine states if (CurrentState >= 4) {MeasureAndControl(); PrintToScreen();} else {SetMotorOff();} } int main() { pc.baud(115200); pc.printf("Hi I'm PTR, you can call me Peter!\r\n"); TimerLoop.start(); CurrentState = Waiting; // set initial state as Waiting TickerLoop.attach(&LoopFunction, 0.002f); //ticker for function calls 500 Hz while (true) { if(PrintFlag) // if-statement for printing every second four times to screen { pc.printf("Pos ref = %f, Pos motor = %f, Error = %f, motorvalue = %f\r",PosRefPrint,PosMotorPrint,ErrorPrint,MotorValuePrint); PrintFlag = false; } } }