hoi

Dependencies:   mbed QEI biquadFilter MODSERIAL

main.cpp

Committer:
maaikelaagland
Date:
2017-11-07
Revision:
10:e328acbdf885
Parent:
9:5023f5a21eab

File content as of revision 10:e328acbdf885:

#include "QEI.h"
#include "math.h"
#include "mbed.h"
#include "MODSERIAL.h"
#include "BiQuad.h"

//left pot to set reference position.
//right pot to set Kp, right pot sets Ki when (right)button is pressed down


//--------------object creation------------------ 
Serial pc(USBTX, USBRX);
QEI enc1(D13, D12, NC, 32); //enable the encoder
QEI enc2(D15, D14, NC, 32); //enable the encoder
PwmOut M1_speed(D6);
PwmOut M2_speed(D5);
DigitalOut M1_direction(D7);
DigitalOut M2_direction(D4);
AnalogIn potmeter(A0);      //left pot
AnalogIn potmeter2(A1);     //right pot
InterruptIn button1(D2);       //hardware interrupt for stopping motors - right button
DigitalIn LimSW1(D9);
DigitalIn LimSW2(D8);
DigitalIn HomStart(D3); // - left button

BiQuad bqlowpass(0.4354, 0.8709, 0.4354, 0.5179, 0.2238);

Ticker motor_update1;
Ticker motor_update2;
Ticker error_update;


//-----------------variable decleration----------------
int pwm_freq = 500;
float set_speed;
float reference_pos;

double M1_home; 
double M1_error_pos = 0;
float M1_Kp = 2.2;
float M1_Ki = 3.8;
float M1_Kd = 0.19;
double M1_e_int=0;
double M1_e_prior=0;

double M2_home; 
double M2_error_pos = 0;
float M2_Kp = 2;
float M2_Ki = 2.5;
float M2_Kd = 0.1;
double M2_e_int=0;
double M2_e_prior=0;

double setpoint = 0;

double M1_rel_pos;
double M2_rel_pos;
double M1_reference_pos;
double M2_reference_pos;

double q1_step;
double q2_step;
double Arm1_home;
double Arm2_home;
double M1_actual_pos;
double M2_actual_pos;
double q1;
double q2;
double vdx;
double vdy;


float Ts = 0.01; //500hz sample freq

bool M1homflag;
bool M2homflag;
bool Homstartflag;
  


 
void kinematica(double q1, double q2, double vdx, double vdy, double &q1_new, double &q2_new){
  double q1_dot = (2.5*cos(q1+q2))/(sin(q2)) *vdx + (2.5*sin(q1+q2))/(sin(q2))*vdy;
  double q2_dot = -(0.3*cos(q1+q2)+0.4*cos(q1))/(0.12*sin(q2))*vdx -(0.3*sin(q1+q2)+0.4*sin(q1))/(0.12*sin(q2))*vdy;
  q1_new += q1_dot*Ts;
  q2_new += (q2_dot-q1_dot)*Ts;
 return;
}

float PID(double e, const double Kp, const double Ki, const double Kd, double Ts, double &e_int, double &e_prior){ //PID calculator
    e_int += Ts*e;
    double e_diff = (e-e_prior)/Ts;
    e_prior = e;
    double e_diff_filter = bqlowpass.step(e_diff);
    return(Kp*e+Ki*e_int+Kd*e_diff_filter);
    }

void M1_control(){
    
    //call PID func and set new motor speed
    set_speed = PID(M1_error_pos,M1_Kp,M1_Ki,M1_Kd,Ts,M1_e_int,M1_e_prior);
    if(set_speed > 0){
     M1_speed.write(abs(set_speed));
     M1_direction.write(0);
     }
    else if (set_speed < 0){
     M1_speed.write(abs(set_speed));
     M1_direction.write(1);
     }
    else{M1_speed.write(0);}
    
 }
 
 void M2_control(){
    set_speed = PID(M2_error_pos,M2_Kp,M2_Ki,M2_Kd,Ts,M2_e_int,M2_e_prior);
    if(set_speed > 0){
     M2_speed.write(abs(set_speed));
     M2_direction.write(0);
     }
    else if (set_speed < 0){
     M2_speed.write(abs(set_speed));
     M2_direction.write(1);
     }
    else{M2_speed.write(0);}       
  }
 
 void homing_system () {
    LimSW1.mode(PullDown);
    LimSW2.mode(PullDown);
    M1_speed.write(0);
    M2_speed.write(0);
    
    
       while(1){
            if (HomStart.read() == 0){
                  setpoint += 0.005; //move setpoint 0.2 radian per second (at 100hz)
                  //pc.printf("Homing... \n\r");
            }     
            
            double M1_rel_pos = enc1.getPulses()/32.0/131.25*2.0*3.1416; 
            double M2_rel_pos = enc2.getPulses()/32.0/131.25*2.0*3.1416;  
            if(LimSW1.read() == 0){
                  M1_error_pos = setpoint - M1_rel_pos;
                  M1_control();
            }
            if(LimSW2.read() == 0){
                M2_error_pos = - setpoint - M2_rel_pos;
                M2_control();
            }
            
            
            
        
        if(LimSW1.read() ==  1){
          M1_error_pos = 0;
          M1_speed.write(0);
          M1_home = enc1.getPulses()/32.0/131.25*2.0*3.1416; //in radians
        }    
        if (LimSW2.read() == 1) {
          M2_error_pos = 0;
          M2_speed.write(0);
          M2_home = enc2.getPulses()/32.0/131.25*2.0*3.1416; //in radians
        }
            
        if (LimSW1.read() == 1 && LimSW2.read() ==1) {
                pc.printf("Homing finished \n\r");
                M1_speed.write(0);
                M2_speed.write(0);
                wait(0.1);
                M1_home = enc1.getPulses()/32.0/131.25*2.0*3.1416; //in radians
                M2_home = enc2.getPulses()/32.0/131.25*2.0*3.1416; //in radians
                M1_e_int = 0;
                M2_e_int = 0;
                break;
                //while(1); //stop after homing.
        }
        pc.printf("M2 error = %f M2 reference = %f,M2_rel = %f\n\r", M2_error_pos,M2_reference_pos,M2_rel_pos);
        wait(0.01);
       }

}
 
 void scopesend(){
  
     
     
     }
 void StopMotors(){
     while(1){
         M1_speed.write(0);
         M2_speed.write(0);
         }
    }
 
void geterror(){ 
    M1_rel_pos = enc1.getPulses()/32.0/131.25*2.0*3.1416; //relative position in radians
    M2_rel_pos = enc2.getPulses()/32.0/131.25*2.0*3.1416; //relative position in radians   

    Arm1_home = 132.0/180.0*3.1416;//home position of large link attached to base in radians - 112 degrees
    Arm2_home = 5.0/180.0*3.1416;//home position of small link attached to base
    
    M1_actual_pos = Arm1_home + (M1_rel_pos - M1_home)*2; //!!!!!!!Gearing ratio of timing belt = 2!!!!!!!!!! - Also known as angle theta
    M2_actual_pos = Arm2_home + (M2_rel_pos - M2_home)*2; //!!!!!!!Gearing ratio of timing belt = 2!!!!!!!!!! - Also known as angle Alpha
    
    q1 = M1_actual_pos;
    q2 = -q1 - M2_actual_pos; //see drawing
    
    vdx = 0.1*potmeter.read();
    vdy = -0.1*potmeter2.read();
    
    kinematica(q1,q2,vdx,vdy,q1_step,q2_step);
    
    M1_reference_pos = q1_step; //should cover the right range - radians
    M2_reference_pos = -(q1_step+q2_step);
    
    
    
        
    
    pc.printf("VDX = %f, q1 = %f, q2 =  %f,q1_step = %f, q2_step =  %f,M1_rel = %f, M2_rel = %f, M2_reference = %f, M1_error_pos = %f, M2_error_pos = %f\n\r",vdx, q1, q2,q1_step,q2_step,M1_rel_pos,M2_rel_pos, M2_reference_pos,M1_error_pos,M2_error_pos);

    if(M1_reference_pos > Arm1_home){
        M1_reference_pos = Arm1_home;
    }
    else{
        M1_error_pos = M1_reference_pos - M1_actual_pos;
    }
    if(M2_reference_pos < Arm2_home){
        M2_reference_pos = Arm2_home;
    }
    else{
        M2_error_pos = M2_reference_pos - M2_actual_pos;
    }
    
    
    //---------PID motor control-------------
    
      set_speed = PID(M1_error_pos,M1_Kp,M1_Ki,M1_Kd,Ts,M1_e_int,M1_e_prior);
    if(set_speed > 0){
     M1_speed.write(abs(set_speed));
     M1_direction.write(0);
     }
    else if (set_speed < 0){
     M1_speed.write(abs(set_speed));
     M1_direction.write(1);
     }
    else{M1_speed.write(0);}
     set_speed = PID(M2_error_pos,M2_Kp,M2_Ki,M2_Kd,Ts,M2_e_int,M2_e_prior);
    if(set_speed > 0){
     M2_speed.write(abs(set_speed));
     M2_direction.write(0);
     }
    else if (set_speed < 0){
     M2_speed.write(abs(set_speed));
     M2_direction.write(1);
     }
    else{M2_speed.write(0);}   
}
 
int main() {
button1.fall(StopMotors);      
    //initialize serial comm and set motor PWM freq
M1_speed.period(1.0/pwm_freq);
M2_speed.period(1.0/pwm_freq);
pc.baud(115200);
pc.printf("starting homing function now. Push button to start procedure \n\r");
//commence homing procedure
homing_system();
pc.printf("Setting home position complete\n\r");
//attach all interrupt
pc.printf("attaching interrupt tickers now \n\r");
    M1_rel_pos = enc1.getPulses()/32.0/131.25*2.0*3.1416; //relative position in radians
    M2_rel_pos = enc2.getPulses()/32.0/131.25*2.0*3.1416; //relative position in radians   

    Arm1_home = 132.0/180.0*3.1416;//home position of large link attached to base in radians - 112 degrees
    Arm2_home = 5.0/180.0*3.1416;//home position of small link attached to base
    
    M1_actual_pos = Arm1_home + (M1_rel_pos - M1_home)*2; //!!!!!!!Gearing ratio of timing belt = 2!!!!!!!!!! - Also known as angle theta
    M2_actual_pos = Arm2_home + (M2_rel_pos - M2_home)*2; //!!!!!!!Gearing ratio of timing belt = 2!!!!!!!!!! - Also known as angle Alpha
    
    q1 = M1_actual_pos;
    q2 = -q1 - M2_actual_pos; //see drawing
    
    q1_step = q1;
    q2_step = q2;
error_update.attach(&geterror,0.02);

pc.printf("initialization complete - position control of motors now active\n\r");
    
    while(1){   
         
     
    }
 
}