motor controller with P velocity control

Dependencies:   HIDScope PID QEI mbed EMG

Fork of PID_VelocityExample by Aaron Berk

main.cpp

Committer:
ewoud
Date:
2015-10-12
Revision:
19:3ca10fe26131
Parent:
18:4ee32b922251

File content as of revision 19:3ca10fe26131:

//****************************************************************************/
// Includes
#include "PID.h"
#include "QEI.h"
#include "HIDScope.h"
#include <math.h>
#include "inits.h" // all globals, pin and variable initialization 

void setGoFlag(){
    if (goFlag==true && systemOn==true && calcFlag==false){
        pc.printf("ERROR: INCORRECT TIMINGS, look at the setGoFlag \n\r");
        // flag is already set true: code too slow or frequency too high    
    }
    goFlag=true;
}
void setCalcFlag(){
    if (calcFlag==true && systemOn==true){
        pc.printf("ERROR: INCORRECT TIMINGS, look at the setCalcFlag \n\r");   
    }
    calcFlag=true;     
}
void systemStart(){
    systemOn=true;
}
void systemStop(){
    systemOn=false;
    leftMotor=0;
    rightMotor=0;
}
int main() {
    velocityTimer.start();
    // initialize (defined in inits.h)
    initMotors();
    initPIDs();
    
    speedcalcTicker.attach(&setCalcFlag, calcRATE);
    motorControlTicker.attach(&setGoFlag, RATE);
    
    startButton.rise(&systemStart);
    stopButton.rise(&systemStop);
    
    while (true){
        if (systemOn==true && calcFlag==true){
            // get 'emg' signal
            request_pos = pot1.read();
            request_neg = pot2.read();
            
            // determine if forward or backward signal is stronger
            if (request_pos > request_neg){
                request = request_pos; 
            } 
            else {
                request = -request_neg;
            }
            
            request=request*maxspeed; // turn [-1, 1] into [-max cm/s, max cm/s]
                       
            // calculate required rotational velocity from the requested horizontal velocity
            // first get the current position from the motor encoders
            // make them start at 45 degree.
            leftAngle=(leftQei.getPulses()/round)*360+45;
            rightAngle=(rightQei.getPulses()/round)*360+45;
            
            if (leftAngle < 0 or leftAngle > 90 or rightAngle < 0 or rightAngle > 90 ){
                pc.printf("out of bounds \n\r");
                leftRequest=0;
                rightRequest=0;
                //if (leftAngle < -45){leftRequest=0.1;}
                //if (leftAngle > 45){leftRequest=-0.1;}
                //if (rightAngle < -45){rightRequest=0.1;}
                //if (rightAngle > 45){rightRequest=-0.1;}
            }
            else {
                currentX = (tan(rightAngle*M_PI/180)*l)/(tan(leftAngle*M_PI/180)+tan(rightAngle*M_PI/180));
                currentY = tan(leftAngle*M_PI/180)*currentX;
                
                //if (sqrt(pow(currentX,2)+pow(currentY,2)) > armlength){ // too far from left arm
                    //return 0;
                //}
                //if (sqrt(pow(l-currentX,2)+pow(currentY,2)) > armlength){ // too far from right arm
                    //return 0;
                //}
                // calculate the position to go to according the the current position + the distance that should be covered in this timestep
                toX=currentX+request/200*calcRATE; // should be request*RATE, 200 is a magical number to make request work in cm/s
                //toY=currentY+0*calcRATE;
                toY=currentY+0*calcRATE;
                
                toLeftAngle = atan(toY/toX)*180/M_PI;
                toRightAngle = atan(toY/(l-toX))*180/M_PI;
                
                // calculate how much the angles should change in this timestep
                leftDeltaAngle=(toLeftAngle-leftAngle);
                rightDeltaAngle=(toRightAngle-rightAngle);
                
                // calculate the neccesairy velocities to make these angles happen.
                leftRequest=(leftDeltaAngle/calcRATE);
                rightRequest=(rightDeltaAngle/calcRATE);
            }
            //pc.printf("leftRequest: %f, rightRequest %f, curX: %f, curY: %f \n\r",leftRequest,rightRequest,currentX,currentY);
            calcFlag=false;
        }
        else if (systemOn == true && goFlag == true){
            
            // set the PID controller to go with that speed.
            leftController.setSetPoint(leftRequest);
            rightController.setSetPoint(rightRequest);
            
            //pc.printf("leftAngle: %f, rightAngle: %f, leftDeltaAngle: %f, rightDeltaAngle: %f \n\r", leftAngle, rightAngle, leftDeltaAngle, rightDeltaAngle);
            
            // *******************
            // Velocity calculation
            // left
            thistime=velocityTimer.read();
            looptime=thistime-lasttime;
            lasttime=thistime;
            //pc.printf("looptime: %f",looptime);
            
            leftPulses = leftQei.getPulses();
            leftVelocity = ((float)(leftPulses - leftPrevPulses))/ looptime;
            leftVelocity = leftVelocity/30000; // scale to 0 - 1, max velocity = 30000
            leftPrevPulses = leftPulses;
            
            // right
            rightPulses = rightQei.getPulses();
            rightVelocity = ((float)(rightPulses - rightPrevPulses))/ looptime;
            rightVelocity = rightVelocity/30000; // scale to 0 - 1, max velocity = 30000
            rightPrevPulses = rightPulses;
            
            // ***********
            // PID control
            // left
            leftController.setProcessValue(leftVelocity);
            leftPwmDuty = leftController.compute();
            if (leftPwmDuty < 0){
                leftDirection = 0;
                leftMotor = -leftPwmDuty;
            }
            else {
                leftDirection = 1;
                leftMotor = leftPwmDuty;
            }
            
            // right
            rightController.setProcessValue(rightVelocity);
            rightPwmDuty = rightController.compute();
            if (rightPwmDuty < 0){
                rightDirection = 1;
                rightMotor = -rightPwmDuty;
            }
            else {
                rightDirection = 0;
                rightMotor = rightPwmDuty;
            }
            
            // User feedback
            scope.set(0, rightRequest*10);
            scope.set(1, rightPwmDuty);
            scope.set(2, rightVelocity*10);
            scope.set(3, leftAngle);
            scope.set(4, rightAngle);
            scope.send();
            //pc.printf("pot2: %f, request: %f, lefVelocity: %f, output: %f \n\r",pot2.read(),request,leftVelocity,leftPwmDuty);
        
            goFlag=false;
        }
    }

    //Stop motors.
    leftMotor  = 0;
    rightMotor = 0;
    
}