Werkt

Dependencies:   Encoder HIDScope MODSERIAL QEI mbed

Fork of Inverse_kinematics_PIDController by Casper Kroon

main.cpp

Committer:
Wimboo
Date:
2018-11-02
Revision:
15:6f5b97d006c2
Parent:
14:a98bc99ea004

File content as of revision 15:6f5b97d006c2:

#include "mbed.h"
#include "math.h"
#include "MODSERIAL.h"
#include "HIDScope.h"
#include "QEI.h"
#define PI 3.141592f //65358979323846  // pi 

PwmOut pwmpin1(D6);
PwmOut pwmpin2(D5);
DigitalOut directionpin2(D4);
DigitalOut directionpin1(D7);
QEI motor1(D13,D12,NC, 32);
QEI motor2(D11,D10,NC, 32);
DigitalOut ledred(LED_RED);

InterruptIn KillSwitch(SW2);
DigitalIn button(SW3);
MODSERIAL pc(USBTX, USBRX);
HIDScope scope(6);
DigitalIn buttonleft(D2);
DigitalIn buttonright(D3);

//values of inverse kinematics
volatile bool emg0Bool = false;
volatile bool emg1Bool = false;
volatile bool emg2Bool = false;
volatile bool x_direction = true;
volatile bool a;

const float C1 = 3.0; //motor 1 gear ratio
const float C2 = 0.013; //motor 2 gear ratio/radius of the circular gear in m
const float length = 0.300; //length in m (placeholder)
const float Timestep = 0.01;

volatile float x_position = length;
volatile float y_position = 0.0;
volatile float old_x_position;
volatile float old_y_position;
volatile float x_correction;
volatile float old_x_correction;
volatile float old_motor1_angle;
volatile float old_motor2_angle;
volatile float motor1_angle = 0.0; //sawtooth gear motor
volatile float motor2_angle = 0.0; //rotational gear motor
volatile float direction;
volatile char c;

//values of PID controller
const float Kp = 0.5;
const float Ki = 0.001;
const float Kd = 0.02;
volatile float Output1 = 0 ;      //Starting value
volatile float Output2 = 0 ;      //Starting value
volatile float P1 = 0;           //encoder value
volatile float P2 = 0;
volatile float e1 = 0 ;          //Starting value 
volatile float e2 = 0 ;          //Starting value
volatile float e3 = 0;  
volatile float f1 = 0 ;          //Starting value 
volatile float f2 = 0 ;          //Starting value
volatile float f3 = 0; 
volatile float df3 = 0;
volatile float if3 = 0;
volatile float de3 = 0;
volatile float ie3 = 0;
    
volatile float Output_Last1;      // Remember previous position
volatile float Output_Last2;      // Remember previous position
volatile float Y1 = 0;               // Value that is outputted to motor control
volatile float Y2 = 0;               // Value that is outputted to motor control
volatile float pwm_value1 = 0;
volatile float pwm_value2 = 0;
volatile float P_Last = 0;       // Starting position

Ticker pwm_ticker; 
Ticker mainticker;; 
    
void yDirection() {
    //direction of the motion
    if (emg0Bool && !emg1Bool) { //if a is pressed and not d, move to the left
        direction = -1;
    }
    else if (!emg0Bool && emg1Bool) { //if d is pressed and not a, move to the right
        direction = 1;
    }

    if (emg0Bool || emg1Bool){  
        //correction from motor 1 to keep x position the same
        
        
        //calculating the motion
        old_y_position = y_position;
        y_position = old_y_position + (0.0003f * direction);
        if (y_position > 0.29f){
            y_position = 0.29f;
        }
        else if (y_position < -0.29f){
            y_position = -0.29f;
        }
        
            
        old_motor1_angle = motor1_angle;
        motor1_angle = asin( y_position / length )* C1;     //saw tooth motor angle in rad
        //correction on x- axis
        old_x_correction = x_correction;
        x_correction = old_x_correction + (length * cos(old_motor1_angle / C1)- length * cos(motor1_angle/ C1)); // old x + correction
        //motor2_angle = ( x_position + x_correction - (length * cos(motor1_angle /C1 ))) / C2;
        
    }
    
    //reset the booleans, only for demo purposes
    emg0Bool = false;
    emg1Bool = false;
}

void xDirection () {      
    //if the button is pressed, reverse the y direction
    if (!button) {
        x_direction = !x_direction;
        //wait(0.5f);
        }     
        
    if (emg2Bool) { //if w is pressed, move up/down
        //direction of the motion
        if (x_direction) { 
            direction = 1.0f;
        }
        else if (!x_direction) {
            direction = -1.0f;
        }
        
        //calculating the motion
        old_x_position = x_position;
        x_position = old_x_position + (0.0003f * direction);
        if (x_position + x_correction > 0.35f ){
            x_position = 0.35f - x_correction;
        }
        else if (x_position < 0.0f){
            x_position = 0.0f;
        }
        //motor2_angle =( x_position + x_correction - (length * cos( motor1_angle / C1 ))) /C2 ; // sawtooth-gear motor angle in rad
        
        //reset the boolean, for demo purposes
        emg2Bool = false; 
    }
}

volatile float Plek1;
void PIDController1() { 
    //Plek1 = motor1.getPulses();  
    P1 = motor1.getPulses() / 8400.0f * 2.0f * PI;    //actual motor angle in rad  
    e1 = e2;
    e2 = e3;
    e3 = motor1_angle - P1;
    de3 = (e3-e2)/Timestep;
    ie3 = ie3 + e3*Timestep;
    Output1 = Kp * e3 + Ki * ie3 + Kd * de3;
    
//    Output_Last1 = Output1;
//    Output1 = Kp * (e3 - e2) + Output_Last1 +Ki * e3 + Kd * (e3 - 2*e2 + e1);
    Y1 = 0.5f * Output1;
    
    if (Y1 >= 1){
        Y1 = 1;
    }
    else if (Y1 <= -1){
        Y1 = -1;
    }    
    
}
volatile float Plek2;
void PIDController2() {   
    //Plek2 = motor2.getPulses();
    P2 = motor2.getPulses() / 8400.0f * 2.0f*PI; // actual motor angle in rad
    f2 = f3;
    f3 = motor2_angle - P2;
    df3 = (f3-f2)/Timestep;
    if3 = if3 + f3*Timestep;
    Output2 = Kp * f3 + Ki * if3 + Kd * df3;
  //  Output_Last2 = Output2;
  //  Output2 = Kp * (f3 - f2) + Output_Last2 +Ki * f3 + Kd * (f3 - 2*f2 + f1);
    Y2 = 0.5f * Output2;
     
    if (Y2 >= 1){
        Y2 = 1;
    }
    else if (Y2 <= -1){
        Y2 = -1;
    }   
    
}

void ControlMotor1() {
    if (Y1 > 0.0f) {
        Y1 = 0.4f * Y1 + 0.2f;
        directionpin1 = false;
    } 
    else if(Y1 < -0.0f){
        Y1 = -0.2f + 0.4f * Y1;
        directionpin1 = true;
    }    

    pwm_value1 = fabs(Y1);
}

void ControlMotor2() {
    if (Y2 > 0.0f) {
        Y2 = 0.8f * Y2 + 0.2f;
        directionpin2 = true;
    } 
    else if(Y2 < -0.0f){
        Y2 = -0.2f + 0.3f * Y2;
        directionpin2 = false;
    }

    pwm_value2 = fabs(Y2);
}

void motorPWM() {
    pwmpin1 = pwm_value1;
    pwmpin2 = pwm_value2;
} 

void tickermain() {
    if(!buttonleft){
        motor2_angle = 4.0f;
    }
    else if(!buttonright) {
        motor2_angle = 2.0f;
    }
    xDirection(); //call the function to move in the y direction
    yDirection(); //call the function to move in the x direction
    PIDController1();
    PIDController2();
    ControlMotor1();
    ControlMotor2();
    
    if (!KillSwitch) { //even in mekaar gebeund voor het hebben van een stop knop
        ledred = false;
        
        //for fun blink sos maybe???
        bool u = true;

        while(u) {
            pwm_value1 = 0;
            pwm_value2 = 0;
            if (!KillSwitch) {
                u = false;
                ledred = true;
                wait(2.0f);
            }
        }
    }
    scope.set(0, motor2_angle);
    scope.set(1, P2);
    scope.set(2, y_position);
    scope.set(3, P2);
    scope.set(4, motor1_angle);
    scope.set(5, motor2_angle);
    scope.send(); 
                  
    //pwm_value1 = 0;
    //pwm_value2 = 0;
    //Y1 = 0;
    //Y2 = 0;
    
    emg0Bool = false;
    emg1Bool = false;
    emg2Bool = false;
}

int main() {
    //pc.baud(115200);
    //pc.printf(" ** program reset **\n\r");
    mainticker.attach(&tickermain, Timestep);
    pwm_ticker.attach(&motorPWM, Timestep);
    ledred = true;
    
    while (true) {
    }
}