this code is for inverted pendulum balancer. it is based on two-loop PID controller. One controller is for Angle and another one is for velocity.

Dependencies:   HCSR04 L298HBridge mbed

communication/communication.cpp

Committer:
dudu941014
Date:
2017-08-25
Revision:
1:ce626b794a6c
Parent:
0:489498e8dae5

File content as of revision 1:ce626b794a6c:

//////////////////////////////////////////////////////////////////////////////////
// Company: edinburgh of university
// Engineer: ZEjun DU
// 
// Create Date: 2017/08/20 13:06:52
// Design Name: Inverted Pendulum Balancer
// Module Name: commnication with GUI
// Tool Versions: “Keil 5” or “Mbed Complie Online”
// Description: this funcition is to commucation with GUI through Bluetooth HC05
//              the system can invoke this function to send the packet and decode the result
//              Pin 28 --------> (TX) RX pin of the Bluetooth module 
//              Pin 27 --------> (RX) TX pin of the Bluetooth  module
//              GND ----------->  GND of the Bluetooth module
//              VOUT (3.3 V) -->  VCC of the Bluetooth module
// 
//////////////////////////////////////////////////////////////////////////////////

#include "communication.h"
#include "get_angle.h"
#include "controller.h"
#include "stabilizer.h"
#include "distance.h"

Serial bluetooth(p28,p27);    // p28: TX, p27: RX (LPC1768)

DigitalOut led1(LED1);//LED init
DigitalOut led2(LED2);//LED init
DigitalOut led3(LED3);//LED init
DigitalOut led4(LED4);//LED init

int j = 500;//the defualt PWM(50% PWM)
int i = 0; //the Bytes' numbers
float AY, EP, ER;//redundant variables

uint8_t usart_rx_buf[64];//this variable is to load the packet from GUI

uint8_t Tx_Buf[24] = //this is the buff which should be sent to GUI 
{
    'A','T',
    '0','0','0','0',
    '0','0','0','0',
    '0','0','0','0',
    '0','0','0','0',
    '0','0','0','0',
    '0','0'
};


////////////////////////////////////////////////////////////
//this funcition is to load the data (distance and angle) and send the whole packet
////////////////////////////////////////////////////////////
void Send_Messge(void)
{
    int X;//the number of current Byte

    Tx_Buf[2] = (int32_t)angle>>24;//send 8 bits each time
    Tx_Buf[3] = (int32_t)angle>>16;//angle
    Tx_Buf[4] = (int32_t)angle>>8;
    Tx_Buf[5] = (int32_t)angle;
    
    Tx_Buf[6] = (int32_t)distance>>24;//send 8 bits each time
    Tx_Buf[7] = (int32_t)distance>>16;//distance
    Tx_Buf[8] = (int32_t)distance>>8;
    Tx_Buf[9] = (int32_t)distance;
    
    Tx_Buf[10] = (int32_t)AY>>24;//send 8 bits each time
    Tx_Buf[11] = (int32_t)AY>>16;
    Tx_Buf[12] = (int32_t)AY>>8;
    Tx_Buf[13] = (int32_t)AY;
    
    Tx_Buf[14] = (int32_t)EP>>24;//send 8 bits each time
    Tx_Buf[15] = (int32_t)EP>>16;
    Tx_Buf[16] = (int32_t)EP>>8;
    Tx_Buf[17] = (int32_t)EP;
    
    Tx_Buf[18] = (int32_t)ER>>24;//send 8 bits each time
    Tx_Buf[19] = (int32_t)ER>>16;
    Tx_Buf[20] = (int32_t)ER>>8;
    Tx_Buf[21] = (int32_t)ER;
    
    Tx_Buf[22] = 0;
    Tx_Buf[23] = 0;
//    bluetooth.printf("this sentence is used to test");
    
    for(X=0; X<24; X++)
    { 
        bluetooth.printf("%c", Tx_Buf[X]);//send the packet         
    }    
}


////////////////////////////////////////////////////////////
//this funcition is to deocode the data from GUI
////////////////////////////////////////////////////////////
void commander(void)
{
    usart_rx_buf[i] = bluetooth.getc();
    i++;
    if(i==6){
        i=0;  
        if( (usart_rx_buf[0]=='G') && (usart_rx_buf[1]=='O'))//"GO"
        {
            PID_ctrl = 1;//enable PID mode
            Velocity_ctrl = 1;//enable velocity PID
                       
            led1 = 1;
            led2 = 0;
            led3 = 0;
            led4 = 0;
        }//unlock the inverted pendulum, its means that we start the pid control 
        
        if( (usart_rx_buf[0]=='S') && (usart_rx_buf[1]=='T'))//"STOP"
        {
            PID_ctrl = 0;//disable PID mode
            Velocity_ctrl = 0;//disable velocity PID
            
            led1 = 0;            
            led2 = 1;
            led3 = 0;
            led4 = 0;
            MOTOR_Update(0);
        }//shut down all controlling 
        
        if( (usart_rx_buf[0]=='A') && (usart_rx_buf[1]=='U'))//keyboard control
        {
            if(usart_rx_buf[2]=='1'){//go forward manually
                Motor_PWM.Stop();//to avoid turnning on all switches of L298n. turnning on all switches will damage the L298n
                wait_us(50);
                Motor_PWM.Fwd();
                Motor_PWM.Speed(j);
                led1 = 0;            
                led2 = 0;
                led3 = 1;
                led4 = 0;
                
                }
            else if(usart_rx_buf[2]=='2'){//go reverse manually
                Motor_PWM.Stop();
                wait_us(50);
                Motor_PWM.Rev();
                Motor_PWM.Speed(j);
                led1 = 0;            
                led2 = 0;
                led3 = 0;
                led4 = 1;
                }  
            else if(usart_rx_buf[2]=='3'){//change the force to motor manually
                j=j+100;
                if(j>=1000)
                j=1000;
                Motor_PWM.Speed(j);
                led1 = 0;            
                led2 = 0;
                led3 = 1;
                led4 = 0;
                }
            else if(usart_rx_buf[2]=='4'){//change the force to motor manually
                j=j-100;
                if(j<=0)
                j=0;
                Motor_PWM.Speed(j);
                led1 = 0;            
                led2 = 0;
                led3 = 0;
                led4 = 1;
                }
            else if(usart_rx_buf[2]=='5'){
                PID_ctrl = 0;
            
                led1 = 1;            
                led2 = 1;
                led3 = 0;
                led4 = 0;
                MOTOR_Update(0);
                }
                
            else if(usart_rx_buf[2]=='6'){//set the original of angle and distance
                angle_offset = angle_voltage.read();
                usensor.start();
                home = usensor.get_dist_cm();
            
                led1 = 1;            
                led2 = 1;
                led3 = 1;
                led4 = 1;
                
                }
            else if(usart_rx_buf[2]=='7'){//set the original of distance
                usensor.start();
                home = usensor.get_dist_cm();
                Velocity_ctrl = 1;
            
                led1 = 1;            
                led2 = 0;
                led3 = 1;
                led4 = 0;
                
                }
        }// change the direction of car by keyboard
        

        

        //change the volecity of car   
        if(usart_rx_buf[0] == 'P' && usart_rx_buf[1] == 'W')
        {
            M_Thr = (usart_rx_buf[2] << 8) | usart_rx_buf[3];
            MOTOR_Update(M_Thr);
        }
        
        //Launch Control 
        if(usart_rx_buf[0] == 'L' && usart_rx_buf[1] == 'C')
        {
            PID_ctrl = 0;
            Velocity_ctrl = 0;
            if(angle <=0)
            {
            Motor_PWM.Rev();
            Motor_PWM.Speed(900);
            wait(0.7);
            Motor_PWM.Fwd();
            Motor_PWM.Speed(700);
            wait(0.3);
            }
            else
            {
            Motor_PWM.Fwd();
            Motor_PWM.Speed(900);
            wait(0.7);
            Motor_PWM.Rev();
            Motor_PWM.Speed(700);
            wait(0.3);
            }
            PID_ctrl = 1;
            Velocity_ctrl = 1;
            
        }
        
        
        
        //this is function for distance
        //to set the 'home' point
        if( (usart_rx_buf[0]=='H') && (usart_rx_buf[1]=='O'))
        {
            usensor.start();
            home = usensor.get_dist_cm();
        }        
        
        if(usart_rx_buf[0] == 'S' && usart_rx_buf[1] == 'H')
        {
            Velocity_ctrl = 0;
            M_Alt = 0;
        } 
        
        if(usart_rx_buf[0] == 'H' && usart_rx_buf[1] == 'P')
        {
            pidVelocity.kp = -(usart_rx_buf[2]<<8)|(usart_rx_buf[3]);
            
            pidVelocity.kp /= 1000;
        }
        if(usart_rx_buf[0] == 'H' && usart_rx_buf[1] == 'I')
        {
            pidVelocity.ki = -(usart_rx_buf[2]<<8)|(usart_rx_buf[3]);
            
            pidVelocity.ki /= 1000;
        }
        if(usart_rx_buf[0] == 'H' && usart_rx_buf[1] == 'D')
        {
            pidVelocity.kd = -(usart_rx_buf[2]<<8)|(usart_rx_buf[3]);
            
            pidVelocity.kd /= 1000;
        }
                         
        //change the distance
        if(usart_rx_buf[0] == 'E' && usart_rx_buf[1] == 'H')
        {
            pidVelocity.desired  = (usart_rx_buf[2] << 8) | usart_rx_buf[3];
            if(usart_rx_buf[4]=='-')           
            pidVelocity.desired  = -(pidVelocity.desired /1000);
            if(usart_rx_buf[4]=='+')           
            pidVelocity.desired  = pidVelocity.desired /1000;
        }    
                
        //the following part is to set PID of angle                 
        if(usart_rx_buf[0] == 'S' && usart_rx_buf[1] == 'P')
        {
            pidAngle.kp = (usart_rx_buf[2]<<8)|(usart_rx_buf[3]);
    
            pidAngle.kp /= 1000;   
        }
                                    
        if(usart_rx_buf[0] == 'S' && usart_rx_buf[1] == 'I')
        {
            pidAngle.ki = (usart_rx_buf[2]<<8)|(usart_rx_buf[3]);
            
            pidAngle.ki /= 1000;
        }
                                    
        if(usart_rx_buf[0] == 'S' && usart_rx_buf[1] == 'D')
        {
            pidAngle.kd = ( usart_rx_buf[2]<<8)|(usart_rx_buf[3]);
                        
            pidAngle.kd /= 1000;
        }
        
        if(usart_rx_buf[0] == 'E' && usart_rx_buf[1] == 'P')
        {
            pidAngle.desired =( usart_rx_buf[2]<<8)|(usart_rx_buf[3]);
            if(usart_rx_buf[4]=='-')                           
                pidAngle.desired = -(pidAngle.desired /1000);
            if(usart_rx_buf[4]=='+')                            
                pidAngle.desired /= 1000;
        }
    }
}