self-balancing-robot

Dependencies:   mbed mbed-rtos Motor

main.cpp

Committer:
pandirimukund
Date:
2020-04-27
Revision:
41:b9c8d527dd2b
Parent:
39:80b565a355f3

File content as of revision 41:b9c8d527dd2b:

#include "mbed.h"
#include "rtos.h"
#include "LSM9DS1.h"
#include "Motor.h"


///////////////////////////////////////////////////////////////////////////////
///////////////////////////// Variable Initialization//////////////////////////
///////////////////////////////////////////////////////////////////////////////
Serial pc(USBTX, USBRX);                          // serial setup for debug


// Setup mutexes for the parameters and the angle values
Mutex parametersmutex;
Mutex angleMutex;


Serial blue(p28, p27);                             // setup bluetooth device

LSM9DS1 imu(p9, p10, 0xD6, 0x3C);                  // setup IMU  


///////////////////////////////////////////////////////////////////////////////
///////////////////////////// Control System Variables/////////////////////////
///////////////////////////////////////////////////////////////////////////////

// parameters for control system 
float rp = 50;                              // proportion parameter           
float rd = 60;                              // derivative parameter
float ri = 20;                              // integral parameter
float desired_angle = 0;                    // the angle the bot should lean at

volatile float speed = 0;                   // speed of the robot
volatile float turnSpeed = 0;               // turn speed when turning

float pAngle = 0;                           // angle error
float dAngle = 0;                           // change in angle error
float iAngle = 0;                           // integral of angle error


float angleBias = 0;                        // the angle bias set during calibration

Motor leftWheel(p21, p24, p23);             // pwm, fwd, rev leftWheel(p21);
Motor rightWheel(p22, p25, p26);            // pwm, fwd, rev rightWheel(p22);

bool isTurning = false;



///////////////////////////////////////////////////////////////////////////////
///////////////////////////// Defining Function ///////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void get_current_angle();                   


///////////////////////////////////////////////////////////////////////////////
///////////////////////////// Bluetooth Section ///////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void bluetooth_update() {
    char bnum = 0;
    char bhit = 0;
    while (1) {
        if (blue.getc() == '!') {
            if (blue.getc() == 'B') { //button data packet
                bnum = blue.getc(); //button number
                bhit = blue.getc(); //1=hit, 0=release
                parametersmutex.lock();        // set mutex since parameters are being updated
                if (blue.getc() == char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
                    switch (bnum) {
                    case '1': //number button 1
                        if (bhit == '1') {
                            rd += 10;
                        } else {
                            //add release code here
                        }
                        break;
                    case '2': //number button 2
                        if (bhit == '1') {
                            ri += 10;
                        } else {
                            //add release code here
                        }
                        break;
                    case '3': //number button 3
                        if (bhit == '1') {
                            rd -= 10;
                        } else {
                            //add release code here
                        }
                        break;
                    case '4': //number button 4
                        if (bhit == '1') {
                            ri -= 10;
                        } else {
                            //add release code here
                        }
                        break;
                    case '5': //button 5 up arrow
                        if (bhit == '1') {
                            rp += 10;
                        } else {
                            //add release code here
                        }
                        break;
                    case '6': //button 6 down arrow
                        if (bhit == '1') {
                            rp -= 10;
                        } else {
                            //add release code here
                        }
                        break;
                    case '7': //button 7 left arrow
                        if (bhit == '1') {
//                            desired_angle -= 2;     //uncomment to change desired angle on press
                            turnSpeed = .3;           // comment to turn off turning
                            isTurning = !isTurning;
                        } else {
                            //add release code here
                        }
                        break;
                    case '8': //button 8 right arrow
                        if (bhit == '1') {
//                            desired_angle += 2;     //uncomment to change desired angle on press
                            turnSpeed = .3;           // comment to turn off turning
                            isTurning = !isTurning;
                        } else {
                            //add release code here
                        }
                        break;
                    default:
                        break;
                    }
                }
                parametersmutex.unlock();            // unlocking parameters mutex
            }
        }
        Thread::wait(100);                           // read bluetooth every tenth of a second
    }
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////// update motor speeds///////////////////////////
///////////////////////////////////////////////////////////////////////////////
void set_wheel_speed(float speed) {
    if (isTurning) {     // set bot to turning if enabled
        leftWheel.speed(turnSpeed*(1));
        rightWheel.speed(turnSpeed*(-1));
    } else {            // otherwise set the wheel speeds to the current speeds and max out at 1 (library requirements)
        if(speed > 1) speed = 1;
        if (speed < -1) speed = -1;
        leftWheel.speed(speed*(-1));
        rightWheel.speed(speed*(-1));
    }
}



///////////////////////////////////////////////////////////////////////////////
///////////////////////////// Control System Updates///////////////////////////
///////////////////////////////////////////////////////////////////////////////
//make the calls to IMU here and this should be another thread
void update_system() {
    while(1){
        get_current_angle();                       // get the current angle from function
        
        angleMutex.lock();                         // going to update angle values so lock mutex
        speed = -1*(rp*pAngle + ri*iAngle + rd*dAngle)/(70 * 150 * 3);     //set the speed based on angle error values
        set_wheel_speed(speed);                    // set the actual wheel speed
        angleMutex.unlock();                       // unlock the mutex
        
        Thread::wait(10);                          // update the sysetem every one hundreth of a second
    }
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////// IMU STUFF////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

//used to find the angle bias
void calibrate_imu() {
    for(int i = 0; i < 500; i++){
        imu.readGyro();
        angleBias += imu.gy;
    }
    angleBias /= 500;
}



void get_current_angle() {
    imu.readGyro();                                 // read the gyro to get velocity of angle
    int gyro = -(imu.gy-angleBias) * .01;           // multiply by time to get the change in angle from before
    //pc.printf("gyro:%f",gyro);
    angleMutex.lock();                              // lock angle mutex 
    dAngle = pAngle;                                // save the old angle to be used later
    
    pAngle += 1*gyro; //+ 0.02*acc;                 //update the proportion error based on gyro 
    pAngle -= desired_angle*70;                     // get error based on the desired angle - 70 just random constant that worked well
    
    dAngle = pAngle - dAngle;                       // get the change in angle error
    
    iAngle += pAngle * 0.01;                        // update the integral of the angle error
    
    angleMutex.unlock();                            // unlock the mutex
}




///////////////////////////////////////////////////////////////////////////////
///////////////////////////// Running Main Function////////////////////////////
///////////////////////////////////////////////////////////////////////////////

int main() {

    // create the threads    
    Thread bluetooth;
    Thread system_update;
    
    // start and calibrate imu
    imu.begin();
    calibrate_imu();
    
    // start the threads
    bluetooth.start(bluetooth_update);
    system_update.start(update_system);
    
    while (1) {
        
        // print out values to debug
        angleMutex.lock();
        pc.printf("pAngle: %f", pAngle/70);
        pc.printf("    speed: %f", speed);
        parametersmutex.lock();
        pc.printf("rp: %f, rd: %f, ri: %f, desired_angle: %f\n\r", rp, rd, ri, desired_angle);
        parametersmutex.unlock();
        angleMutex.unlock();
        
        
        
        Thread::wait(100);  //print out 10 times a second
    }
}