First trial

Dependencies:   MPU6050 Motor ledControl2 mbed

Fork of BalancingRobotPS3 by Kristian Lauszus

BalancingRobot.cpp

Committer:
lakshmananag
Date:
2016-08-25
Revision:
9:67f2110fce8e
Parent:
7:f1d24c6119ac

File content as of revision 9:67f2110fce8e:

/*
 * The code is released under the GNU General Public License.
 * This is the algorithm for my balancing robot/segway.
 * It is controlled by Bluetooth
 */

#include "mbed.h"
#include "BalancingRobot.h"
#include "MPU6050.h"
#include "ledControl.h"
#include "HALLFX_ENCODER.h"

/* Setup serial communication */
Serial blue(p28,p27); // For remote control ps3
Serial pc(USBTX, USBRX); // USB

/* IMU */
MPU6050 mpu6050;  

/* Encoders*/
HALLFX_ENCODER leftEncoder(p13);
HALLFX_ENCODER rightEncoder(p14);

/* Setup timer instance */
Timer t;

/* Ticker for led toggling */
Ticker toggler1;               

int main() {
    /* Set baudrate */
    blue.baud(9600);
    pc.baud(9600);
    
    /* Set PWM frequency */
    leftPWM.period(0.00005); // The motor driver can handle a pwm frequency up to 20kHz (1/20000=0.00005)
    rightPWM.period(0.00005);
    
    /* Calibrate the gyro and accelerometer relative to ground */
    mpu6050.whoAmI();                            // Communication test: WHO_AM_I register reading 
    wait(0.5);
    mpu6050.calibrate(accelBias,gyroBias);       // Calibrate MPU6050 and load biases into bias registers
    pc.printf("Calibration is completed. \r\n"); 
    mpu6050.init();                              // Initialize the sensor
    pc.printf("MPU6050 is initialized for operation.. \r\n\r\n");
    
    /* Setup timing */
    t.start();
    loopStartTime = t.read_us();
    timer = loopStartTime;
    
    while (1) {
        /* Calculate pitch angle using a Complementary filter */
        mpu6050.complementaryFilter(&pitchAngle, &rollAngle);
        wait_us(5);
        timer = t.read_us();
        
        /* Drive motors */
        if (abs(pitchAngle)> 20) // Stop if falling or laying down
            stopAndReset();
        else
            PID(targetAngle,targetOffset);
        
        /* Update wheel velocity every 100ms */
        loopCounter++;
        if (loopCounter%10 == 0) 
        { // If remainder is equal 0, it must be 10,20,30 etc.
            LeftWheelPosition = leftEncoder.read();
            RightWheelPosition = rightEncoder.read();
            wheelPosition = LeftWheelPosition + RightWheelPosition;
            wheelVelocity = wheelPosition - lastWheelPosition;
            lastWheelPosition = wheelPosition;
            
            if (abs(wheelVelocity) <= 20 && !stopped) 
            { // Set new targetPosition if braking
                targetPosition = wheelPosition;
                stopped = true;
            }
        }
        
        pc.printf("Pitch: %f, error: %f, PIDValue: %f \n",pitchAngle,error,PIDValue);
        pc.printf("Left Wheel Encoder: %f, Right Wheel Encoder: %f \n", LeftWheelPosition, RightWheelPosition);
        pc.printf("Wheel Position: %f, Last wheel position:%f, Velocity: %f \n\n", wheelPosition, lastWheelPosition, wheelVelocity);
                
        /* Check for incoming serial data */
        if (blue.readable()) // Check if there's any incoming data
            receiveBluetooth();
          
        /* Use a time fixed loop */
        lastLoopUsefulTime = t.read_us() - loopStartTime;
        if (lastLoopUsefulTime < STD_LOOP_TIME)
            wait_us(STD_LOOP_TIME - lastLoopUsefulTime);
        lastLoopTime = t.read_us() - loopStartTime; // only used for debugging
        loopStartTime = t.read_us();
    }
}

void compFilter() {mpu6050.complementaryFilter(&pitchAngle, &rollAngle);}

void toggle_led1() {ledToggle(1);}
void toggle_led2() {ledToggle(2);}

void PID(double restAngle, double offset) 
{
    /* Steer robot */
    if (steerForward) 
    {
        offset += (double)wheelVelocity/velocityScaleMove; // Scale down offset at high speed and scale up when reversing
        restAngle -= offset;
    } 
    else if (steerBackward) 
    {
        offset -= (double)wheelVelocity/velocityScaleMove; // Scale down offset at high speed and scale up when reversing
        restAngle += offset;
    }
    /* Brake */
    else if (steerStop) 
    {
        //long positionError = wheelPosition - targetPosition;
        
    /*  if (abs(positionError) > zoneA) // Inside zone A
            restAngle -= (double)positionError/positionScaleA;
        else if (abs(positionError) > zoneB) // Inside zone B
            restAngle -= (double)positionError/positionScaleB;
        else // Inside zone C
            restAngle -= (double)positionError/positionScaleC; */
        
        restAngle -= (double)wheelVelocity/velocityScaleStop;
        
        if (restAngle < -5.00) // Limit rest Angle
            restAngle = -5.00;
        else if (restAngle > 5.00)
            restAngle = 5.00;
    }
    
    /* Update PID values */
    error = restAngle - pitchAngle;
    double pTerm = Kp * error;
    iTerm += Ki * error;
    double dTerm = Kd * (error - lastError);
    lastError = error;
    
    PIDValue = pTerm + iTerm + dTerm;
    
    //pc.printf("Pitch: %5.2f\tPIDValue: %5.2f\tKp: %5.2f\tKi: %5.2f\tKd: %5.2f\n",pitch,PIDValue,Kp,Ki,Kd);
    
    /* Steer robot sideways */
    double PIDLeft;
    double PIDRight;
    if (steerLeft) {
        PIDLeft = PIDValue-turnSpeed;
        PIDRight = PIDValue+turnSpeed;
    } else if (steerRotateLeft) {
        PIDLeft = PIDValue-rotateSpeed;
        PIDRight = PIDValue+rotateSpeed;
    } else if (steerRight) {
        PIDLeft = PIDValue+turnSpeed;
        PIDRight = PIDValue-turnSpeed;
    } else if (steerRotateRight) {
        PIDLeft = PIDValue+rotateSpeed;
        PIDRight = PIDValue-rotateSpeed;
    } else {
        PIDLeft = PIDValue;
        PIDRight = PIDValue;
    }
    //PIDLeft *= 0.95; // compensate for difference in the motors
    
    /* Set PWM Values */
    if (PIDLeft >= 0)
        move(left, forward, PIDLeft);
    else
        move(left, backward, PIDLeft * -1);
    if (PIDRight >= 0)
        move(right, forward, PIDRight);
    else
        move(right, backward, PIDRight * -1);
}
void receiveBluetooth() {
    //char input[16]; // The serial buffer is only 16 characters
    char phone_char;
    //int i = 0;
    //while (1) {
        //input[i] = blue.getc();
        //if (input[i] == ';' || i == 15) // keep reading until it reads a semicolon or it exceeds the serial buffer
            //break;
        //i++;
        
        //pc.printf("Im here..");
    //}
    phone_char = blue.getc();
    pc.putc(phone_char);
    //pc.printf("Input: %c\n",i);
    
    // Set all false
    steerForward = false;
    steerBackward = false;
    steerStop = false;
    steerLeft = false;
    steerRotateLeft = false;
    steerRight = false;
    steerRotateRight = false;
    
    /* For remote control */
    if (/*input[0]*/phone_char == 'F') { // Forward
        //strtok(/*input*/phone_char, ","); // Ignore 'F'
        //targetOffset = atof((strtok(NULL, ";")); // read until the end and then convert from string to double
        //pc.printf("%f\n",targetOffset); // Print targetOffset for debugging
        steerForward = true;
    } else if (/*input[0]*/phone_char == 'B') { // Backward
        //strtok(/*input*/phone_char, ","); // Ignore 'B'
        targetOffset = atof(strtok(NULL, ";")); // read until the end and then convert from string to double
        //pc.printf("%f\n",targetOffset); // Print targetOffset for debugging
        steerBackward = true;
    } else if (/*input[0]*/phone_char == 'L') { // Left
        if (/*input[0]*/phone_char == 'L') // Left Rotate
            steerRotateLeft = true;
        else
            steerLeft = true;
    } else if (/*input[0]*/phone_char == 'R') { // Right
        if (/*input[0]*/phone_char == 'R') // Right Rotate
            steerRotateRight = true;
        else
            steerRight = true;
    } else if (/*input[0]*/phone_char == 'S') { // Stop
        steerStop = true;
        stopped = false;
        targetPosition = wheelPosition;
    } else if (/*input[0]*/phone_char == 'A') { // Abort
        stopAndReset();
        while (blue.getc() != 'C'); // Wait until continue is send
    }
}

void stopAndReset() {
    stop(both);
    lastError = 0;
    iTerm = 0;
    targetPosition = wheelPosition;
}

void move(Motor motor, Direction direction, float speed) { // speed is a value in percentage (0.0f to 1.0f)
    if (motor == left) {
        leftPWM = speed;
        if (direction == forward) {
            leftA = 0;
            leftB = 1;
        } else if (direction == backward) {
            leftA = 1;
            leftB = 0;
        }
    } else if (motor == right) {
        rightPWM = speed;
        if (direction == forward) {
            rightA = 0;
            rightB = 1;
        } else if (direction == backward) {
            rightA = 1;
            rightB = 0;
        }
    } else if (motor == both) {
        leftPWM = speed;
        rightPWM = speed;
        if (direction == forward) {
            leftA = 0;
            leftB = 1;
            
            rightA = 0;
            rightB = 1;
        } else if (direction == backward) {
            leftA = 1;
            leftB = 0;
            
            rightA = 1;
            rightB = 0;
        }
    }
}
void stop(Motor motor) {
    if (motor == left) {
        leftPWM = 1;
        leftA = 1;
        leftB = 1;
    } else if (motor == right) {
        rightPWM = 1;
        rightA = 1;
        rightB = 1;
    } else if (motor == both) {
        leftPWM = 1;
        leftA = 1;
        leftB = 1;
        
        rightPWM = 1;
        rightA = 1;
        rightB = 1;
    }
}