Developers_of_anti_slip_compensator / Mbed 2 deprecated WIPV

Dependencies:   CURRENT_CONTROL IIR LSM9DS0 MEDIAN_FILTER PID QEI RF24 SENSOR_FUSION mbed

main.cpp

Committer:
adam_z
Date:
2016-07-28
Revision:
9:a91135551be1
Parent:
8:9f4c10787775
Child:
10:2dc43cd59ff0

File content as of revision 9:a91135551be1:

#include "mbed.h"
#include "PID.h"
#include "LSM9DS0.h"
#include "QEI.h"
#include "CURRENT_CONTROL.h"
#include "SENSOR_FUSION.h"
#include "MEDIAN_FILTER.h"
#include <algorithm>

#define Ts 0.001
#define pi 3.14159

LSM9DS0 sensor(SPI_MODE, D9, D6);
Serial pc(SERIAL_TX, SERIAL_RX);
Serial blueTooth(D10, D2);
Serial LeftSerial(PC_12, PD_2);
Serial RightSerial(PC_10, PC_11);

DigitalOut debugLed_l(A4);
DigitalOut debugLed_r(A5);

InterruptIn SCEnable(USER_BUTTON);


Ticker WIPVTimer;
void WIPVTimerInterrupt();
float saturation(float input, float limit_H, float limit_L);
//void SensorAcquisition(float * data, float samplingTime);

void bluetoothRx();
void RXIrqLeft();
void RXIrqRight();

void SCEnableFunc();
bool SCEnalbeIndicator;

//MOTOR L == MOTOR 1;  MOTOR R = MOTOR 2
CURRENT_CONTROL motorCur_L(PC_3, D8,  A3,CURRENT_CONTROL::PWM2,400, 900.0,0.0,Ts);
CURRENT_CONTROL motorCur_R(PC_2, D7, D11,CURRENT_CONTROL::PWM1,400, 900.0,0.0,Ts);

QEI wheel_L(D13, D12, NC, 280, 250, Ts, QEI::X4_ENCODING);
QEI wheel_R(A1,  A2,  NC, 280, 250, Ts, QEI::X4_ENCODING);


PID balancingPD(20,0.00,0.0,Ts);
LPF sensorFilter1(Ts);
LPF sensorFilter2(Ts);
LPF sensorFilter3(Ts);
LPF sensorFilter4(Ts);

MedianFilter slipA_L_MF(9);
MedianFilter slipA_R_MF(9);





int tim_counter = 0;
float tim = 0.0;
float amp = 0.3;
float omega = 6.0;
float curCmd_L =0.0, curCmd_R =0.0;


//*************real plant states and matrices*****************************
float state[4] = {0.0, 0.0, 0.0, 0.0};
float ref[4] = {0.0, 0.0, 0.0, 0.0};

float torque_L = 0.0, torque_R = 0.0;
float KL[4] = {-1.9483 ,  -0.1317 ,   0.0006*2  , -0.0112*2};//{-0.7057 ,  -0.0733 ,  -0.0085 ,  -0.0300};
float KR[4] = {-1.9483,   -0.1317 ,  -0.0112*2 ,   0.0006*2};//{-0.7057 ,  -0.0733 ,  -0.0300 ,  -0.0085};

//********simulated states and multiplying matrices***********************
float z1_prime[4] = {0.0, 0.0, 0.0, 0.0};
float z1_prime_dot[4] = {0.0, 0.0, 0.0, 0.0};
float v1[2] = {0.0,0.0};
float A1_prime0[4] = {0,1,0,0},A1_prime1[4] = {176.4899,0,0,0},A1_prime2[4] = {-83.1468,0, 0, 0},A1_prime3[4] = {-83.1468, 0, 0,0};
float B11_prime0[2] = {0,0}, B11_prime1[2] = {-537.6123, -537.6123}, B11_prime2[2] = { 679.2587,  104.3936}, B11_prime3[2] = { 104.3936,  679.2587};
float B31_0[2] = {0,0},B31_1[2] = {0.7840,0.7840},B31_2[2] = {12.1836, 0.3086},B31_3[2] = {0.3086, 12.1836};

float Ks0[4] = {-1.9483,   -0.1317,    0.0006,   -0.0112}, Ks1[4] = {-1.9483,   -0.1317,   -0.0112,    0.0006};
float yc[2] = {0.0,0.0};



float Km_L = 1.050*0.163;
float Km_R = 1.187*0.137;

float yawRate = 0.0;

float velocityCmd[2] = {0.0, 0.0};
unsigned int accelerateFlag = 0, decelerationFlag = 0;


//uint8_t cLast_l = 0x00, cLast_r = 0x00;
float cLast_l, cLast_r;
bool headerCaptured_l = 0, headerCaptured_r = 0;
uint8_t fromPhoton_l[2] = {0,0}, fromPhoton_r[2] = {0,0};
float slipAcceleration_L = 0.0, slipAcceleration_R = 0.0, slipAcceleration_L_f, slipAcceleration_R_f, slipAcceleration_L_m, slipAcceleration_R_m;
float slipAcceleration_L_f_d, slipAcceleration_R_f_d;
int i_l, i_r;


float a_vehicle;
float a_slip_L,a_slip_R;

int send_i = 0, send_counter = 0;
bool sent_flag = 1;
uint8_t data_sent[18];

int delay_num = 37;
float fifo_array[37];
float a_vehicle_fifo;
int fifo_i = 0;


int main()
{

    pc.baud(230400);
    blueTooth.baud(230400);
    LeftSerial.baud(230400); //uart commu with photon left
    RightSerial.baud(230400); //uart commu with photon right

    if( sensor.begin() != 0 ) {
        pc.printf("Problem starting the sensor with CS @ Pin D6.\r\n");
    } else {
        pc.printf("Sensor with CS @ Pin D9&D6 started.\r\n");
    }
    sensor.setGyroOffset(38,-20,-95);
    sensor.setAccelOffset(-680,-460,300);

    motorCur_L.SetParams(3.3*8/0.6, Km_L, 0.04348);
    motorCur_R.SetParams(3.3*8/0.6, Km_R, 0.04348);

    WIPVTimer.attach_us(WIPVTimerInterrupt, Ts*1000.0*1000.0);
    blueTooth.attach(&bluetoothRx, Serial::RxIrq);
    LeftSerial.attach(&RXIrqLeft, Serial::RxIrq);
    RightSerial.attach(&RXIrqRight, Serial::RxIrq);

    SCEnable.rise(&SCEnableFunc);
    SCEnalbeIndicator = 0;

    while(true) {
        //pc.printf("%5.4f\t", 10*pitch_angle);
//        pc.printf("%5.3f\n", 10*sensor.pitch*3.14159/180);
//        pc.printf("%5.3f\r\n", 10*curCmd_L);


        //if(sent_flag == 0) {///
//            pc.putc(data_sent[send_i]);
//            send_i++;
//            if(send_i >= 18) {
//                send_i = 0;
//                sent_flag = 1;
//            }
//        }///
    pc.printf("%5.4f\t",a_vehicle);
        pc.printf("%5.4f\t",a_vehicle_fifo);
//        pc.printf("%5.4f\t", slipAcceleration_L);
        pc.printf("%5.4f\r\n",slipAcceleration_L);
//    pc.printf("%5.4f\t",yc[0]);
//    pc.printf("%5.4f\r\n",yc[1]);

    }
}


void WIPVTimerInterrupt()
{
    if(tim_counter <100)tim_counter++;
    else if (tim_counter >= 100 && tim_counter <=109) {
        motorCur_L.currentOffset += motorCur_L.currentAnalogIn.read();
        motorCur_R.currentOffset += motorCur_R.currentAnalogIn.read();
        tim_counter++;
        if(tim_counter == 110) {
            motorCur_L.currentOffset = motorCur_L.currentOffset/10;
            motorCur_R.currentOffset = motorCur_R.currentOffset/10;
        }

    } else {


        //int16_t data_array[6];
//
//        data_array[0]  = sensor.readRawAccelX();
//        data_array[1]  = sensor.readRawAccelY();
////        data_array[2]  = sensor.readRawAccelZ();
////        data_array[3]  = sensor.readRawGyroX();
//        data_array[4]  = sensor.readRawGyroY();
//        data_array[5]  = sensor.readRawGyroZ();
//
//        pc.printf("%d, ", data_array[0]);
//        pc.printf("%d, ", data_array[1]);
////        pc.printf("%d, ", data_array[2]);
////        pc.printf("%d, ", data_array[3]);
//        pc.printf("%d, ", data_array[4]);
//        pc.printf("%d;\r\n ", data_array[5]);



        float data_array[6];//Gs and deg/s
        data_array[0]  = sensor.readFloatAccelX();
        data_array[1]  = sensor.readFloatAccelY();
//        data_array[2]  = sensor.readFloatAccelZ();
//        data_array[3]  = sensor.readFloatGyroX();
        data_array[4]  = sensor.readFloatGyroY();
        data_array[5]  = sensor.readFloatGyroZ();

        sensor.complementaryFilter(data_array,Ts);


        //===============wheel speed calculation============//
        wheel_L.Calculate();
        wheel_R.Calculate();


        /////////////Balancing Control/////////////////////////
        //SI dimension
        state[0] = sensor.pitch*3.14159/180.0;
        state[1] = sensorFilter1.filter(data_array[5]*3.14159/180.0, 6.0);
        state[2] = sensorFilter2.filter(wheel_L.getAngularSpeed(),80.0);
        state[3] = -sensorFilter3.filter(wheel_R.getAngularSpeed(),80.0);

        if(accelerateFlag == 1) {
            if(velocityCmd[0]>=20 || velocityCmd[1]>=20) {
                accelerateFlag = 0;
                decelerationFlag = 1;
            } else {
                velocityCmd[0] += 0.010;
                velocityCmd[1] += 0.010;
            }
        }

        if(decelerationFlag == 1 & velocityCmd[0] > 0.0) {
            velocityCmd[0] -= 0.015;
            velocityCmd[1] -= 0.015;
            if(velocityCmd[0] <= 0.0)decelerationFlag = 0;
        }

        ref[2] = velocityCmd[0];
        ref[3] = velocityCmd[1];

        yawRate = sensorFilter4.filter(data_array[4],9);


        //===============integration of z1_prime=========================
        z1_prime[0] += z1_prime_dot[0]*Ts;
        z1_prime[1] += z1_prime_dot[1]*Ts;
        z1_prime[2] += z1_prime_dot[2]*Ts;
        z1_prime[3] += z1_prime_dot[3]*Ts;


        yc[0] = (KL[0]*(ref[0] - (state[0] - z1_prime[0])) + KL[1]*(ref[1] - (state[1] - z1_prime[1]))\
                 + KL[2]*(ref[2] - (state[2] - z1_prime[2])) + KL[3]*(ref[3] - (state[3] - z1_prime[3])));

        yc[1] = (KR[0]*(ref[0] - (state[0] - z1_prime[0])) + KR[1]*(ref[1] - (state[1] - z1_prime[1]))\
                 + KR[2]*(ref[2] - (state[2] - z1_prime[2])) + KR[3]*(ref[3] - (state[3] - z1_prime[3])));


        //=========================Anti slip control=============================//
        //***********filtering the slip acceleration of two wheels********************
        a_vehicle = (data_array[0]*cos(state[0]) - data_array[1]*sin(state[0]))*9.791;//compute acceleration of vehicle using lsm9ds0
        //fifo delay
        a_vehicle_fifo = fifo_array[fifo_i];
//        delay_num = sizeof(fifo_array);
        fifo_array[fifo_i] = a_vehicle;
        fifo_i++;
        if(fifo_i >= delay_num)fifo_i = 0;




        //pc.printf("%5.2f\t", a_vehicle);
////        pc.printf("%5.2f\t",slipAcceleration_L_f);
//        pc.printf("%5.2f\r\n",slipAcceleration_R_f);

        a_slip_L = slipAcceleration_L - a_vehicle_fifo;
        a_slip_R = slipAcceleration_R - a_vehicle_fifo;

        float alpha = 40.0;//HZ
        slipAcceleration_L_f = (1 - alpha*2*3.141593*Ts)*slipAcceleration_L_f + alpha*2*3.141593*Ts*a_slip_L;
        slipAcceleration_R_f = (1 - alpha*2*3.141593*Ts)*slipAcceleration_R_f + alpha*2*3.141593*Ts*a_slip_R;

        if(SCEnalbeIndicator == 0) {
            slipAcceleration_L_f_d = 0;
            slipAcceleration_R_f_d = 0;

        } else {
            //***********dead zone************************//
            float deadzone = 0.0;
            if(slipAcceleration_L_f < deadzone & slipAcceleration_L_f > -deadzone)slipAcceleration_L_f_d = 0;
            else slipAcceleration_L_f_d = slipAcceleration_L_f;

            if(slipAcceleration_R_f < deadzone & slipAcceleration_R_f > -deadzone)slipAcceleration_R_f_d = 0;
            else slipAcceleration_R_f_d = slipAcceleration_R_f;

        }


        //***************simulated plant feedback**************
        v1[0] = -(Ks0[0]*z1_prime[0] + Ks0[1]*z1_prime[1] + Ks0[2]*z1_prime[2] + Ks0[3]*z1_prime[3]);
        v1[1] = -(Ks1[0]*z1_prime[0] + Ks1[1]*z1_prime[1] + Ks1[2]*z1_prime[2] + Ks1[3]*z1_prime[3]);

        //**********simulated dynamics*****************
        z1_prime_dot[0] =  A1_prime0[0]*z1_prime[0] + A1_prime0[1]*z1_prime[1]+A1_prime0[2]*z1_prime[2]+A1_prime0[3]*z1_prime[3]\
                           + B11_prime0[0]*v1[0]+ B11_prime0[1]*v1[1]\
                           + B31_0[0]*slipAcceleration_L_f_d+ B31_0[1]*slipAcceleration_R_f_d;

        z1_prime_dot[1] =  A1_prime1[0]*z1_prime[0] + A1_prime1[1]*z1_prime[1]+A1_prime1[2]*z1_prime[2]+A1_prime1[3]*z1_prime[3]\
                           + B11_prime1[0]*v1[0]+ B11_prime1[1]*v1[1]\
                           + B31_1[0]*slipAcceleration_L_f_d+ B31_1[1]*slipAcceleration_R_f_d;

        z1_prime_dot[2] =  A1_prime2[0]*z1_prime[0] + A1_prime2[1]*z1_prime[1]+A1_prime2[2]*z1_prime[2]+A1_prime2[3]*z1_prime[3]\
                           + B11_prime2[0]*v1[0]+ B11_prime2[1]*v1[1]\
                           + B31_2[0]*slipAcceleration_L_f_d+ B31_2[1]*slipAcceleration_R_f_d;

        z1_prime_dot[3] =  A1_prime3[0]*z1_prime[0] + A1_prime3[1]*z1_prime[1]+A1_prime3[2]*z1_prime[2]+A1_prime3[3]*z1_prime[3]\
                           + B11_prime3[0]*v1[0]+ B11_prime3[1]*v1[1]\
                           + B31_3[0]*slipAcceleration_L_f_d+ B31_3[1]*slipAcceleration_R_f_d;

        torque_L = -((yc[0] + v1[0])/Km_L) + 0.015*yawRate;
        torque_R =  ((yc[1] + v1[1])/Km_R) + 0.015*yawRate;

        //************motor torque control*****************
//        motorCur_L.Control(saturation(torque_L,1.3,-1.3), state[2]);
//        motorCur_R.Control(saturation(torque_R,1.3,-1.3), -state[3]);

        //**************sending data to PC******************
        if(send_counter < 40)send_counter++;

        else if( sent_flag == 1 & send_counter >= 40) {
            send_counter = 0;
            int multiplier = 500;
            data_sent[0] = 0xAA;
            data_sent[1] = 0x55;

            data_sent[2] = ((int16_t)((state[0])*multiplier)) >>8;
            data_sent[3] = ((int16_t)((state[0])*multiplier)) & 0x00FF;
            data_sent[4] = ((int16_t)(state[1]*multiplier)) >>8;
            data_sent[5] = ((int16_t)(state[1]*multiplier)) & 0x00FF;

            data_sent[6] = ((int16_t)((v1[0])*multiplier)) >>8;
            data_sent[7] = ((int16_t)((v1[0])*multiplier)) & 0x00FF;
            data_sent[8] = ((int16_t)((v1[1])*multiplier)) >>8;
            data_sent[9] = ((int16_t)((v1[1])*multiplier)) & 0x00FF;

            data_sent[10] = ((int16_t)((yc[0])*multiplier)) >>8;
            data_sent[11] = ((int16_t)((yc[0])*multiplier)) & 0x00FF;
            data_sent[12] = ((int16_t)((yc[1])*multiplier)) >>8;
            data_sent[13] = ((int16_t)((yc[1])*multiplier)) & 0x00FF;
            //data_sent[10] = ((int16_t)((-a_vehicle)*multiplier)) >>8;
//            data_sent[11] = ((int16_t)((-a_vehicle)*multiplier)) & 0x00FF;
//            data_sent[12] = ((int16_t)((slipAcceleration_R_m)*multiplier)) >>8;
//            data_sent[13] = ((int16_t)((slipAcceleration_R_m)*multiplier)) & 0x00FF;
            data_sent[14] = ((int16_t)((slipAcceleration_L)*multiplier)) >>8;
            data_sent[15] = ((int16_t)((slipAcceleration_L)*multiplier)) & 0x00FF;
            data_sent[16] = ((int16_t)((slipAcceleration_R)*multiplier)) >>8;
            data_sent[17] = ((int16_t)((slipAcceleration_R)*multiplier)) & 0x00FF;


            sent_flag = 0;

        }





        /*  //PD Balancing Control
                balancingPD.Compute(0.0, sensor.pitch*3.14159/180);
                curCmd_R = sensorFilter.filter(saturation(0.5*( -balancingPD.output + 0.002*data_array[5]),1.0, -1.0),10);
                //======================current control=========================//
                tim += Ts;
                if(tim >= 4*pi/omega)tim = 0.0;
                //curCmd_R = amp*sin(omega*tim); //current command
                //curCmd_L = 0.8;

                motorCur_R.SetPWMDuty(0.75);

                motorCur_L.Control(-curCmd_R + 0.002*data_array[4], wheel_L.getAngularSpeed());
                motorCur_R.Control(curCmd_R  + 0.002*data_array[4], wheel_R.getAngularSpeed());
        */

    }


}


void  bluetoothRx()
{
    while(pc.readable()) {
        char charRx = pc.getc();
        switch(charRx) {
            case 'w'://forward
                velocityCmd[0] = 2.5;
                velocityCmd[1] = 2.5;
                accelerateFlag = 0;
                break;
            case 's'://backward
                velocityCmd[0] = -3.0;
                velocityCmd[1] = -3.0;
                accelerateFlag = 0;
                break;
            case 'a'://turn left
                velocityCmd[0] = -4.0;
                velocityCmd[1] = 4.0;
                accelerateFlag = 0;
                break;
            case 'd'://turn right
                velocityCmd[0] = 4.0;
                velocityCmd[1] = -4.0;
                accelerateFlag = 0;
                break;
            case 'x'://stop
                velocityCmd[0] = 0.0;
                velocityCmd[1] = 0.0;
                accelerateFlag = 0;
                break;

            case 'q'://accelerate
//                debugLed_l = !debugLed_l;
                accelerateFlag = 1;
                break;
        }
    }
}

void RXIrqLeft()
{


    if(LeftSerial.readable()) {
        debugLed_l = !debugLed_l;
        uint8_t c = LeftSerial.getc();
        cLast_l = c;

        if( c == 0xAA) {
            i_l = 0;
            headerCaptured_l = 1;


        } else if(headerCaptured_l)  {
            fromPhoton_l[i_l] = c;
            i_l++;
            if(i_l == 2) {
                headerCaptured_l = 0;
                slipAcceleration_L = (float)((int16_t)(fromPhoton_l[0]*256+fromPhoton_l[1])*0.92)/1000.0;

//                pc.printf("%5.4f\t",(float)slipAcceleration_L_f);
//                pc.printf("%5.4f\r\n",(float)slipAcceleration_R_f);
            }

        }
    }


}




void RXIrqRight()
{

    //  slipAcceleration_L += 0.1;
    if(RightSerial.readable()) {
        debugLed_r = !debugLed_r;
        uint8_t c = RightSerial.getc();
        cLast_r = c;
//        pc.printf("%5.4f\r\n",(float)cLast_r);

        if( c == 0xAA) {
            headerCaptured_r = 1;
            i_r = 0;

        } else if(headerCaptured_r) {

            fromPhoton_r[i_r] = c;
            i_r++;
            if(i_r == 2) {
                headerCaptured_r = 0;
                slipAcceleration_R = -(float)((int16_t)(fromPhoton_r[0]*256+fromPhoton_r[1])*1.18)/1000.0;

            }
        }
    }
}



float saturation(float input, float limit_H, float limit_L)
{
    float output;
    if(input >= limit_H)output = limit_H;
    else if (input <= limit_L)output = limit_L;
    else output = input;
    return output;
}


//void SensorAcquisition(float * data, float samplingTime)
//{
//
//    axm =  data[0]*(-1)*9.81;//accelerometer dimension from g to m/s^2
//    aym =  data[1]*(-1)*9.81;
//    azm =  data[2]*(-1)*9.81;
//    u1  = data[0]*3.14159/180;      //gyroscope :deg/s to rad/s
//    u2  = data[1]*3.14159/180;
//    u3  = data[2]*3.14159/180;
//
//
//    if(conv_init <= 3) {
//        axm_f_old = axm;
//        aym_f_old = aym;
//        azm_f_old = azm;
//
//        conv_init++;
//    } else {
//        pitch_fusion(axm,  aym,azm,u3,u2,20, samplingTime);
//        roll_fusion(axm,   aym,azm,u3,u1,20, samplingTime);
//        x3_hat_estimat(axm,aym,azm,u2,u1,20, samplingTime);
//    }
//
//}


void SCEnableFunc()
{
//    debugLed_l = !debugLed_l;
    accelerateFlag = 1;
    SCEnalbeIndicator = !SCEnalbeIndicator;
}