speed code

Dependencies:   mbed

main.cpp

Committer:
benparkes
Date:
2015-10-18
Revision:
1:f4e3365155e1
Parent:
0:e79700919e2e

File content as of revision 1:f4e3365155e1:

#include "mbed.h"


#define wheelc 0.1759292
#define wheel_spacing 0.128 //add this in
#define pi 3.141592654
#define degreel 0.021988888
//Status LED
DigitalOut led(LED1);

//Motor PWM (speed)
PwmOut PWMA(PA_8);
PwmOut PWMB(PB_4);

//Motor Direction
DigitalOut DIRA(PA_9);
DigitalOut DIRB(PB_10);

//Hall-Effect Sensor Inputs
InterruptIn HEA1(PB_2);
InterruptIn HEA2(PB_1);
InterruptIn HEB1(PB_15);
InterruptIn HEB2(PB_14);

//On board switch
DigitalIn SW1(USER_BUTTON);

//Use the serial object so we can use higher speeds
Serial terminal(USBTX, USBRX);

//Timer used for measuring speeds
Timer timer;

//Enumerated types
enum DIRECTION   {FORWARD=0, REVERSE};
enum PULSE       {NOPULSE=0, PULSE};
enum SWITCHSTATE {PRESSED=0, RELEASED};

//Debug GPIO
DigitalOut probe(D10);

//Duty cycles
float dutyA = 0.000f; //100%
float dutyB = 0.000f; //100%

//distance measurement
float distanceA ;
float distanceB ;
float speedA ;
float speedB ;

//for interrupt speed and distance calcs
int tA1[2];
int tA2[2];
int tB1[2];
int tB2[2];
int pulse_orderA = 1;
int pulse_orderB = 1;

//interupt handler
int HEPulse(int let,int num, int order) //tell us which hall effect HEA1= hall effect, (let, A=1, B=2), (num, 1/2), order (index possition to be filled alternates)
{
    float fA1;
    float fA2;
    float fB1;
    float fB2;
    int time;
    time = timer.read_us(); //use to check for interrupt debounce

    if((tA1[0]-time<5)||(tA2[0]-time<5)||(tA1[1]-time<5)||(tA2[1]-time<5)) {
        return 1;
    } // if less than 5us from last interupt assume debouce and ignore
    //find right thing to do for current hall effect
    switch(order) { //check whether to fill index possition 0/1
        case(1) :
            switch(let) { //check hall effect A/B
                case(1):

                    switch(num) { //check hall effect 1/2
                        case (1):
                            tA1[0] = timer.read_us();
                            distanceA += (wheelc/6); //increment distance
                            pulse_orderA = 2; //toggle index to be filled
                            break;

                        case(2) :
                            tA2[0] = timer.read_us();
                            pulse_orderA = 2;
                            break;
                    }
                    break;


                case(2): //check hall effect A/B

                    switch(num) {
                        case (1):
                            tB1[0] = timer.read_us();
                            distanceB += (wheelc/6);
                            pulse_orderB = 2;
                            break;

                        case(2) :
                            tB2[0] = timer.read_us();
                            pulse_orderB = 2;
                            break;
                    }
                    break;

            }
        case(2) :
            switch(let) {
                case(1):

                    switch(num) {
                        case (1):
                            tA1[1] = timer.read_us();
                            distanceA += (wheelc/6);
                            fA1 = 1.0f/(( fabsf(tA1[1]-tA1[0]) ) * (float)3.0E-6);
                            pulse_orderA = 1;
                            break;

                        case(2) :
                            tA2[1] = timer.read_us();
                            fA2 = 1.0f/(( fabsf(tA2[1]-tA2[0]) ) * (float)3.0E-6);
                            pulse_orderA = 1;
                            break;
                    }
                    break;


                case(2):

                    switch(num) {
                        case (1):
                            tB1[1] = timer.read_us();
                            distanceB += (wheelc/6);
                            fB1 = 1.0f/(( fabsf(tB1[1]-tB1[0]) ) * (float)3.0E-6);
                            pulse_orderB = 1;
                            break;

                        case(2) :
                            tB2[1] = timer.read_us();
                            fB2 = 1.0f/((fabsf( tB2[1]-tB2[0]) ) * (float)3.0E-6);
                            pulse_orderB = 1;
                            break;
                    }
                    break;

            }

            float fA = (fA1 + fA2)*0.5f; //calculate average frequency of hall effect A
            float fB = (fB1 + fB2)*0.5f; //calculate average frequency of hall effect B
            speedA = fA/20.8f; //output speeds of motors by frequency/gear box ratio
            speedB = fB/20.8f;
    }
    return 1;
}

void ResetDistanceTimeSpeed() //reset vaviables for new straight or turn
{
    distanceA=0;
    distanceB=0;
    speedA=0;
    speedB=0;
    timer.reset();
    timer.start();
}

void stopmotors() //stop motors dead
{
    PWMA.write(0.0f);       //0% duty cycle
    PWMB.write(0.0f);       //0% duty cycle
}

void HuntSpeeds(float target_speedA, float target_speedB) //alter speeds to desired speed by hunting for corresponding duty (input desired speeds)
{

    float deltaA = target_speedA -speedA; //find difference between actual speed and desired speed
    dutyA = dutyA + deltaA*0.1f; //modify duty dependant upon size of error
    PWMA.write(dutyA); //write new duty to motor

    float deltaB = target_speedB -speedB; //repeat for B motor
    dutyB = dutyB + deltaB*0.1f;
    PWMB.write(dutyB);
}


int forward(float distance, float speed) //forward motion, input distance and speed (rev/s)
{
    // Set motor direction forward
    DIRA = FORWARD;
    DIRB = FORWARD;

    //reset distance
    ResetDistanceTimeSpeed();

    // Set initial motor to be altered by speed code
    PWMA.write(0.1f*speed);          //Set duty cycle (%)
    PWMB.write(0.1f*speed);          //Set duty cycle (%)


    //wait for run to complete byy checking if distance has been covered yet
    while (((distanceA+distanceB)/2) < distance) {
        //maintain desired speed
        HuntSpeeds(speed, speed);
    }
    return 1;
}

int turn(float degrees, float speed, int direction,float turn_radius) // (Degrees of Turn, Speed, (Anti/Clock)wise, turn radius (m))

{
    // Calculate Turn Distance
    float C1 = (pi * 2 * (float)turn_radius)*(degrees/360); // outside arc (piD)/fraction turn
    float C2 = (pi * 2 * ((float)turn_radius-(float)wheel_spacing))*(degrees/360); //inside arc (piD)/fraction turn
    //Set Initial Motor Direction
    DIRA = FORWARD;
    DIRB = FORWARD;

    // Test for direction to Enter Victory Spin
    if(direction==REVERSE) {
        DIRA = REVERSE;
        DIRB = FORWARD;//victory spin opposite wheels
    }
    // Reset Distance Travelled
    ResetDistanceTimeSpeed();

    // Wait for Turn to Complete by checking whether outer wheel completed spin yet
    while (distanceA < C1) {
        if(direction==FORWARD) {
            HuntSpeeds(speed, speed*(float(C2/C1))); //maitain speeds proportional to difference in turn length for each wheel
        }

        if(direction==REVERSE) {
            HuntSpeeds(speed,speed); //set speeds same for reverse spin
        }
    }
    return 1;
}
//interupt handlers
void HEA1I(void)
{
    HEPulse(1,1,pulse_orderA);
}
void HEA2I(void)
{
    HEPulse(1,2,pulse_orderA);
}
void HEB1I(void)
{
    HEPulse(2,1,pulse_orderB);
}
 void HEB2I(void)
{
    HEPulse(2,2,pulse_orderB);
}

int main()
{
    //Configure the terminal to high speed
    terminal.baud(115200);
    // initiate interupts to call interupt code
    HEA1.rise(&HEA1I);
    HEA2.rise(&HEA2I);
    HEB1.rise(&HEB1I);
    HEB2.rise(&HEB2I);
    //Set initial motor speed to stop
    stopmotors();
    //set motor frequency
    PWMA.period_ms(10);
    PWMB.period_ms(10);
    ResetDistanceTimeSpeed();
    while(1) {
    //wait for switch press
    while (SW1 == PRESSED) {
            wait(0.01);
            while(SW1 == RELEASED) {

                //navigate course
                for (int i = 0; i<2; i++) {
                    //forward 1m
                    forward(12,1); //distance, speed in rotations/s
                    //turn 90
                    turn(90,0.5,0,0.2);//degrees, speed (rev/s), direction (0 clockwise),radius of turn)
                    //forward 1/2m
                    forward(7,1);//distance, speed in rotations/s
                    //turn 90
                    turn(90,0.5,0,0.2);//degrees, speed (rev/s), direction (0 clockwise),radius of turn)
                }
                //repeat twice to end up back in starting possition

                //victory spin
                turn(365,0.5,1,0.001);//degrees, speed (rev/s), direction (0 clockwise),radius of turn)

                stopmotors();
                break;
            }
        }
    }

}