Thomas Burgers / Mbed 2 deprecated ZZ-TheChenneRobot

Dependencies:   Encoder HIDScope MODSERIAL QEI biquadFilter mbed

main.cpp

Committer:
ThomasBNL
Date:
2015-10-14
Revision:
37:23660d12d772
Parent:
36:da07b5c2984d

File content as of revision 37:23660d12d772:

#include "mbed.h"
#include "HIDScope.h"
#include "QEI.h"
#include "MODSERIAL.h"
#include "biquadFilter.h"
#include "encoder.h"

//                    ___________________________
//                  //                           \\
//                 ||          [Inputs]           ||
//                  \\___________________________//
//


MODSERIAL   pc(USBTX,USBRX);

DigitalOut  debug_led_red(LED_RED);                 // Debug LED
DigitalOut  debug_led_green(LED_GREEN);             // Debug LED 
DigitalOut  debug_led_blue(LED_BLUE);               // Debug LED   

DigitalIn buttonL1(PTC6);                // Button 1 (low on k64f) for testing at the lower board
DigitalIn buttonL2(PTA4);                // Button 2 (low on k64f) for testing at the lower board
DigitalIn buttonH1(D2);                  // Button 3 (high on k64f) for testing at the top board
DigitalIn buttonH2(D6);                  // Button 4 (high on k64f) for testing at the top board   

AnalogIn potmeter(A0);                  // Potmeter that can read a reference value (DEBUG TOOL)

//                    ___________________________
//                  //                           \\
//                 ||        [MOTOR TURN]         ||
//                  \\___________________________//
//
QEI motor_turn(D12,D13,NC,32);          // Encoder for motor Turn
PwmOut pwm_motor_turn(D5);              // Pwm for motor Turn
DigitalOut motordirection_turn(D4);     // Direction of the motor Turn

//                    ___________________________
//                  //                           \\
//                 ||          [HIDSCOPE]         ||
//                  \\___________________________//
//
//HIDScope    scope(3); // HIDSCOPE declared
//                    ___________________________
//                  //                           \\
//                 ||         [CONSTANTS]         ||
//                  \\___________________________//
//
    const double off=1;                     //Led off
    const double on=0;                      //Led on
    const int Fs = 512;                     // sampling frequency (512 Hz)
    
//                    ___________________________
//                  //                           \\
//                 ||       [FUNCTIONS USED]      ||
//                  \\___________________________//
//

void keep_in_range(double * in, double min, double max);
void setlooptimerflag(void);



                                                     ///////////////////////////////
                                                     //                           //
///////////////////////////////////////////////////////      [MAIN FUNCTION]      ////////////////////////////////////////////////////////////////////////////
                                                     //                           //                                                                        //
                                                     ///////////////////////////////                                                                        //
int main() {
    debug_led_red=off;
    debug_led_blue=off;
    debug_led_green=off;
    
    
    //START OF CODE 
    pc.printf("Start of code \n\r");
    
    pc.baud(115200);                          // Set the baudrate
    
    // Tickers 
    Ticker looptimer;                                          // Ticker called looptimer to set a looptimerflag
    looptimer.attach(&setlooptimerflag,(float)1/Fs);            // calls the looptimer flag every 0.01s
    
    pc.printf("Start infinite loop \n\r");
    wait (3);                                                  // Wait before starting system
    
    
    //INFINITE LOOP
    while(1) 
        {                                                                                                   // Start while loop
        

//                                         ___________________________
//                                       //                           \\
//                                      ||    [Wait for go signal]     ||
//                                       \\___________________________//
//                     // Wait until looptimer flag is true then execute PID controller loop.                
             
        
                //reference = (potmeter.read()-0.5)*2000;  // Potmeter bepaald reference (uitgeschakeld) 
        

    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                    //                                //  
                                                    //      [Functions Described]     //
                                                    //                                //
                                                    ////////////////////////////////////

// Keep in range function
void keep_in_range(double * in, double min, double max)
{
    *in > min ? *in < max? : *in = max: *in = min;
}

    double reference_turn=20;                  // Set constant to store reference value of the Turn motor
    volatile bool looptimerflag;
    const double  cw=0;                     // zero is clockwise (front view)
    const double  ccw=1;                    // one is counterclockwise (front view)
    const double sample_time = 0.001953125;                     // sampling frequency (512 Hz)

// PID motor constants
double integrate_error_turn=0;          // integration error turn motor
double previous_error_turn=0;           // previous error turn motor

const double Gain_P_turn=10; //0.0067; 
                    // stel setpoint tussen (0 en 360) en position tussen (0 en 360)
                    // max verschil: 360 -> dan pwm_to_motor 1 tot aan een verschil van 15 graden-> bij 15 moet pwm_to_motor ong 0.1 zijn 
                    // dus     0.1=15*gain      gain=0.0067
                    // Als 3 graden verschil 0.1 dan 0.1/3=gain=0.33
                                                        
double Gain_I_turn=0.1; //0.025;  //(1/2000) //0.00000134
        // pwm_motor_I=(integrate_error_turn + sample_time*error)*gain;  pwm = (4*0.01 + 4)* Gain => 0.1 pwm gewenst (na 1 seconde een verschil van 4 graden)  
                        // 0.1 / (4.01) = Gain = 0.025
        
double Gain_D_turn=50; //0.01;                    
        // error_derivative_turn=(error - previous_error_turn)/sample_time
        // 
        
double conversion_counts_to_degrees=0.085877862594198;
                    // gear ratio motor = 131
                    // ticks per magnet rotation = 32 (X2 Encoder)
                    // One revolution = 360 degrees
                    // degrees_per_encoder_tick = 360/(gear_ratio*ticks_per_magnet_rotation)=360/131*32=0.085877862594198 

// Looptimerflag function
void setlooptimerflag(void)
{
    debug_led_green=on;


//                                         ___________________________
//                                       //                           \\
//                                      ||       [DEBUG BUTTONS]       ||
//                                       \\___________________________//
//                             interrupt button Disbalances the current motor position 

                                //if button L2 pressed => disbalance motor                                                  
         if (buttonL2.read() < 0.5){      
             motordirection_turn = cw;                       
             pwm_motor_turn = 0.5f;         
             pc.printf("positie = %d \r\n", motor_turn.getPulses()); }

             
                                // if button L1 pressed => shut down motor for 1000 seconds  
         if (buttonL1.read() < 0.5){      
             motordirection_turn = cw;                       
             pwm_motor_turn = 0;
             wait(1000);        
             pc.printf("positie = %d \r\n", motor_turn.getPulses()); }   
             
            else
            {
    
    //                                         ___________________________
//                                       //                           \\
//                                      ||     [Calibrate position]    ||
//                                       \\___________________________//
//                             //   Keep motor position between -4200 and 4200 counts        
        debug_led_green=on;
        if ((motor_turn.getPulses()>4200) || (motor_turn.getPulses()<-4200)) // If value is outside -4200 and 4200 (number of counts equal to one revolution) reset to zero
        {
            motor_turn.reset();
            pc.printf("RESET \n\r");
        }   
        
                              //    Convert position to degrees    \\
                              
        double position_turn = conversion_counts_to_degrees * motor_turn.getPulses();
        
        pc.printf("calibrated setpoint: %f, calibrated position motor %i, position %f \n\r", reference_turn, motor_turn.getPulses(), position_turn);
        
        
//                                         ___________________________
//                                       //                           \\
//                                      ||     [PID CONTROLLER]        ||
//                                       \\___________________________//
//            // Calculate error then multiply it with the (P, I and D) gains, and store in pwm_to_motor \\

        double error_turn=(reference_turn - position_turn);                                     // Current error (input controller)
        
        integrate_error_turn=integrate_error_turn + sample_time*error_turn;              // integral error output
//                                                                                          // overwrite previous integrate error by adding the current error 
                                                                                            // multiplied by the sample time.
//        
        double error_derivative_turn=(error_turn - previous_error_turn)/sample_time;     // derivative error output
    
            // FILTER error_derivative_turn (lowpassfilter)             (EMG LOWPASS FILTER MOMENTEEL!!!!!)
        
const double low_b1 = 1.480219865318266e-04; //filter coefficients
const double low_b2 = 2.960439730636533e-04;
const double low_b3 = 1.480219865318266e-04;
const double low_a2 = -1.965293372622690e+00; // a1 is normalized to 1
const double low_a3 = 9.658854605688177e-01;                
biquadFilter lowpassfilter_1(low_a2, low_a3, low_b1, low_b2, low_b3);

            error_derivative_turn=lowpassfilter_1.step(error_derivative_turn);
        
        previous_error_turn=error_turn;                                // current error is saved to memory constant to be used in 
                                                                  // the next loop for calculating the derivative error 

        double pwm_to_motor_turn = error_turn*Gain_P_turn;                     // output P controller to pwm   

        double pwm_motor_turn_P = error_turn*Gain_P_turn;                     // output P controller to pwm        
        double pwm_motor_turn_I = integrate_error_turn*Gain_I_turn;      // output I controller to pwm
        double pwm_motor_turn_D = error_derivative_turn*Gain_D_turn;     // output D controller to pwm

        pwm_to_motor_turn = pwm_motor_turn_P + pwm_motor_turn_I + pwm_motor_turn_D;
     
//                                         ___________________________
//                                       //                           \\
//                                      ||   [PID error -> pwm motor]  ||
//                                       \\___________________________//
//          // Keep Pwm between -1 and 1 -> and decide the direction of the motor to compensate the error       

        keep_in_range(&pwm_to_motor_turn, -1,1);                     // Pass to motor controller but keep it in range!
        pc.printf("pwm %f \n\r", pwm_to_motor_turn);

        // Check error and decide direction to turn
        if(pwm_to_motor_turn > 0)
            {
            motordirection_turn=ccw;
            pc.printf("if loop pwm > 0 \n\r");
            }
        else
            {
            motordirection_turn=cw;
            pc.printf("else loop pwm < 0 \n\r");
            }
        
//                                         ___________________________
//                                       //                           \\
//                                      ||       [pwm -> Plant]        ||
//                                       \\___________________________//
//                                          // Put pwm to the motor \\

        pwm_motor_turn=(abs(pwm_to_motor_turn));
        
//                                         ___________________________
//                                       //                           \\
//                                      ||         [HIDSCOPE]          ||
//                                       \\___________________________//
//                                      // Check signals inside HIDSCOPE \\
        
//            scope.set(0,error_turn);             // HIDSCOPE channel 0 : Current Reference
//            scope.set(1,position_turn);     // HIDSCOPE channel 1 : Position_turn
//            scope.set(2,pwm_to_motor_turn); // HIDSCOPE channel 2 : Pwm_to_motor_turn
//            scope.send();                   // Send channel info to HIDSCOPE
}
}

// Get setpoint -> potmeter (MOMENTEEL UITGESCHAKELD)
double get_reference(double input)
{
const float offset = 0.5;
const float gain = 4.0;
return (input-offset)*gain;
}