Framework for doing the figure 8 track.

Dependencies:   mbed

main.cpp

Committer:
mawk2311
Date:
2015-03-20
Revision:
2:a04e2757d372
Parent:
1:55e0aaf71bda
Child:
3:e867c4e984df

File content as of revision 2:a04e2757d372:

#include "mbed.h"
#include "stdlib.h"

//Outputs
DigitalOut led1(LED1);
DigitalOut clk(PTD5);
DigitalOut si(PTD4);
PwmOut motor1(PTA4);
PwmOut motor2(PTA12);
DigitalOut break1(PTC12);
DigitalOut break2(PTC13);
PwmOut servo(PTA5);

//Inputs
AnalogIn camData(PTC2);

//Encoder setup and variables
InterruptIn interrupt(PTA13);

//Line Tracking Variables --------------------------------
float ADCdata [128];
float minAccum;
float minCount;
float approxPos;
float minVal;
int minLoc;

//Servo turning parameters
float straight = 0.00155f;
float hardLeft = 0.0013f;
float slightLeft = 0.00145f;
float hardRight = 0.0018f;
float slightRight = 0.00165f;

//End of Line Tracking Variables -------------------------

//Encoder and Motor Driver Variables ---------------------

//Intervals used during encoder data collection to measure velocity
int interval1=0;
int interval2=0;
int interval3=0;
int avg_interval=0;
int lastchange1 = 0;
int lastchange2 = 0;
int lastchange3 = 0;
int lastchange4 = 0;

//Variables used to for velocity control
float avg_speed = 0;
float stall_check = 0;
float tuning_val = 1;

Timer t;
Timer servoTimer;

//Observed average speeds for each duty cycle
const float DESIRED_SPEED = 0.5;
const float TUNING_CONSTANT_10 = 1.10;
const float TUNING_CONSTANT_20 = 3.00;
const float TUNING_CONSTANT_30 = 4.30;
const float TUNING_CONSTANT_50 = 6.880;
const float PI = 3.14159;
const float WHEEL_CIRCUMFERENCE = .05*PI;

//Velocity Control Tuning Constants
const float TUNE_THRESH = 0.5f;
const float TUNE_AMT = 0.1f;

//Parameters specifying sample sizes and delays for small and large average speed samples
float num_samples_small = 3.0f;
float delay_small = 0.05f;
float num_samples_large = 100.0f;
float delay_large = 0.1f;

//Large and small arrays used to get average velocity values
float large_avg_speed_list [100];
float small_avg_speed_list [10];

//End of Encoder and Motor Driver Variables ----------------------

//Line Tracker Functions~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

int find_track(float line[]){
    int track_location = -1;
    float slope_threshold = .05;
    bool downslope_indices [128] = {false};
    bool upslope_indices [128] = {false};
    for(int i=10; i<118; i++){
        if(line[i+1] - line[i] < -slope_threshold && line[i+2] - line[i+1] < -slope_threshold){
            downslope_indices[i] = true;
        }
        if(line[i+1] - line[i] > slope_threshold && line[i+2] - line[i+1] > slope_threshold){
            upslope_indices[i] = true;
        }
    }
    int numDownslopes = 0;
    int numUpslopes = 0;
    for(int i=0; i<128; i++){
        if(downslope_indices[i] == true){
            numDownslopes ++;
        }
        if(upslope_indices[i] == true){
            numUpslopes ++;
        }
    }
    int downslope_locs [numDownslopes];
    int upslope_locs [numUpslopes];
    int dsctr = 0;
    int usctr = 0;
    
    for (int i=0; i<128; i++){
        if(downslope_indices[i] == true){
            downslope_locs[dsctr] = i;
            dsctr++;
        }
        if(upslope_indices[i] == true){
            upslope_locs[usctr] = i;
            usctr++;
        }
    }
    
    for(int i=0; i<numDownslopes; i++){
        for(int j=0; j<numUpslopes; j++){
            if(upslope_locs[j] - downslope_locs[i] >=4 && upslope_locs[j] - downslope_locs[i] <=5){
                track_location = downslope_locs[i] + 2 ;
            }
        }
    }

    return track_location;
}


// Encoder and Motor Driver Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

float get_speed(){
    float revPerSec = (1.0f/((float)avg_interval*.000001))*.25f;
    float linearSpeed = revPerSec * WHEEL_CIRCUMFERENCE;
    return linearSpeed;
}

float get_avg_speed(float num_samples, float delay) {
    
    float avg_avg_speed = 0;
    
    for (int c = 0; c < num_samples; c++) {
        if (num_samples == num_samples_small){
            small_avg_speed_list[c] = get_speed();
        } else if (num_samples == num_samples_large){
            large_avg_speed_list[c] = get_speed();
        }
        //wait(delay);
        }
                
        for (int c = 1; c < num_samples; c++) {
            if (num_samples == num_samples_small){
                avg_avg_speed += small_avg_speed_list[c];
            } else if (num_samples == num_samples_large){
                avg_avg_speed += large_avg_speed_list[c];
            }
        }
    return avg_avg_speed/num_samples;
}

void velocity_control(float duty_cyc, float tuning_const) {
    
    avg_speed = get_speed();//get_avg_speed(num_samples_small, delay_small);
    
    if (avg_speed == stall_check) {
        avg_speed = 0;
        tuning_val += TUNE_AMT;
    } else if((avg_speed - tuning_const) > TUNE_THRESH){
        tuning_val -= TUNE_AMT;
        stall_check = avg_speed;
    } else if (tuning_const - avg_speed > TUNE_THRESH){
        //tuning_val += TUNE_AMT;
        stall_check = avg_speed;
    } else {
        //tuning_val = 1;
        stall_check = avg_speed;
    }
    motor1.pulsewidth(.0025 * duty_cyc * tuning_val);
    motor2.pulsewidth(.0025 * duty_cyc * tuning_val);
    
}

void fallInterrupt(){
    
    int time = t.read_us();
    interval1 = time - lastchange2;
    interval2 = lastchange1-lastchange3;
    interval3 = lastchange2 - lastchange4;
    avg_interval = (interval1 + interval2 + interval3)/3;
    
    lastchange4 = lastchange3;
    lastchange3 = lastchange2;
    lastchange2 = lastchange1;
    lastchange1 = time;
}

void riseInterrupt(){
    int time = t.read_us();
    interval1 = time - lastchange2;
    interval2 = lastchange1-lastchange3;
    interval3 = lastchange2 - lastchange4;
    avg_interval = (interval1 + interval2 + interval3)/3;
    
    lastchange4 = lastchange3;
    lastchange3 = lastchange2;
    lastchange2 = lastchange1;
    lastchange1 = time;
}


//End of Encoder and Motor Driver Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

int main() {
    //Line Tracker Initializations
    int integrationCounter = 0;
    
    // Motor Driver Initializations
    motor1.period(.0025);
    motor2.period(.0025);
    //interrupt.fall(&fallInterrupt);
    //interrupt.rise(&riseInterrupt);

    wait(5);

    motor1.pulsewidth(.0025*.105);
    motor2.pulsewidth(.0025*.105);
    break1 = 0;
    break2 = 0;
    
    //t.start();
    
    //wait(5);
    
    while(1) {
            
        if(integrationCounter % 151== 0){
            //Disable interrupts
            //__disable_irq();
            //interrupt.fall(NULL);
            //interrupt.rise(NULL);
            
            //Send start of integration signal
            si = 1;
            clk = 1;

            si = 0;
            clk = 0;
            
            //Reset timing counter for integration
            integrationCounter = 0;
            
            //Reset line tracking variables
            minAccum = 0;
            minCount = 0;
            approxPos = 0;
            
            //Reset Encoder and Motor Driver Variables
            interval1=0;
            interval2=0;
            interval3=0;
            avg_interval=0;
            lastchange1 = 0;
            lastchange2 = 0;
            lastchange3 = 0;
            lastchange4 = 0;
            
            t.reset();
                
        }
        else if (integrationCounter > 129){
            //Enable interrupts
            //__enable_irq();
            //interrupt.fall(&fallInterrupt);
            //interrupt.rise(&riseInterrupt);
            
            minVal = ADCdata[15];
            for (int c = 10; c < 118; c++) {
                if (ADCdata[c] < minVal){
                    minVal = ADCdata[c];
                    minLoc = c;
                }
            }
            
            for (int c = 10; c < 118; c++) {
                if (ADCdata[c] >= minVal && ADCdata[c] - minVal < 0.08f && ADCdata[c] > 0.1f){
                    minAccum += c;
                    minCount++;
                }
            }
            
            approxPos = (float)minAccum/(float)minCount;
            
            
            //approxPos = find_track(ADCdata);
            
            if(approxPos > 0 && approxPos <= 25){
                    servo.pulsewidth(hardLeft);
                    motor1.pulsewidth(.0025*.1);
                    motor2.pulsewidth(.0025*.1);
            } else if (approxPos > 25 && approxPos <= 40){
                    servo.pulsewidth(slightLeft);
                    motor1.pulsewidth(.0025*.105);
                    motor2.pulsewidth(.0025*.105);
            } else if (approxPos > 40 && approxPos <= 90){
                servo.pulsewidth(straight);
                    motor1.pulsewidth(.0025*.1125);
                    motor2.pulsewidth(.0025*.1125);
            } else if (approxPos > 90 && approxPos <= 105){
                    servo.pulsewidth(slightRight);
                    motor1.pulsewidth(.0025*.105);
                    motor2.pulsewidth(.0025*.105);
            } else if (approxPos > 105 && approxPos <= 128){
                    servo.pulsewidth(hardRight);
                    motor1.pulsewidth(.0025*.1);
                    motor2.pulsewidth(.0025*.1);
            }
            /*
            if(approxPos > 0 && approxPos <= 45){
                    servo.pulsewidth(hardLeft);
            } else if (approxPos > 45 && approxPos <= 95){
                    servo.pulsewidth(straight);
            } else {
                servo.pulsewidth(hardRight);
            }*/
            //velocity_control(0.05f, DESIRED_SPEED);
            
            integrationCounter = 150;
        }
        else{
            clk = 1;
            wait_us(220);
            ADCdata[integrationCounter - 1] = 1 - camData;
            clk = 0;
        }

        //clk = 0;
        integrationCounter++;
        //camData.
        
    }
}