Our version of TFC code.

Dependencies:   FRDM-TFC mbed

Fork of FRDM-TFC by Eli Hughes

main.cpp

Committer:
kdsch
Date:
2015-05-01
Revision:
8:4e9ce846f7c3

File content as of revision 8:4e9ce846f7c3:

/* log
2/7/2015 2:18pm, Karl
 - Pasted in http://developer.mbed.org/users/redxeth/code/TFC-TEST/file/6432166d0781/main.cpp
   as directed in the video at https://community.freescale.com/videos/1591.
 - Cleaned up code style for compactness and regularity.
2/15/2015 4:00pm, Karl
 - Researched serial terminal connection. This was helpful: http://developer.mbed.org/handbook/SerialPC
2/17/2015 9:08am, Karl
 - Played with different baud rates to improve frame rate. http://developer.mbed.org/forum/mbed/topic/893/
2/17/2015 3:14pm. Corbin
 - Added function test_garage back in to view labview graphing of the camera data.
2/19/2015 6:34pm, Karl
 - Moved the functions from control.cpp to main.cpp and deleted control.cpp and control.h.
   This resolved errors of multiple definition. See http://suckless.org/style
endlog */

/* headers */
#include "mbed.h"
#include "TFC.h"
#include <stdlib.h>

/* macros */
#define NUM_TFC_TICKERS 4
#define IS 128

/* types */
enum State {STOP, GO, DONE, BRAKE};

typedef struct {
    uint32_t x;
    int y;
} Point;

/* global variables */
Serial PC(USBTX, USBRX);
Ticker TFC_TickerObj;
volatile uint32_t TFC_Ticker[NUM_TFC_TICKERS];
void TFC_TickerUpdate()
{
    for (int i = 0; i < NUM_TFC_TICKERS; i++)
        if (TFC_Ticker[i]<0xFFFFFFFF) 
            TFC_Ticker[i]++;
}

/* function declarations */
void drive();
void stop();
void sortdesc(uint32_t x[], Point sx[]);
int comPoint(void *a, void *b);
void deriv2(volatile uint16_t x[], int ddx[]);
int min(int a, int b);
int max(int a, int b);

/* function definitions */

void drive(float s, float throt)
{
    float l, r;
    TFC_HBRIDGE_ENABLE;
    
    // determine motor drive as a function of steering angle
    /*
    *     ____
    *    /
    *   /
    *  /
    */
    l = (1 - 0*s*s) * throt * (1 - 1.6*s*(s>0));
    r = (1 - 0*s*s) * throt * (1 + 1.6*s*(s<0));

    TFC_SetMotorPWM(r, -l);
    if (TFC_Ticker[2] >= 20) {
        TFC_Ticker[2] = 0;
        TFC_SetServo(0, s);
    }   
}


/* Stop the car. */
void stop()
{
    TFC_SetMotorPWM(0, 0);
    TFC_HBRIDGE_DISABLE;
}

/* compare the height of two points */
int comPoint(const void *a, const void *b)
{
    Point *A = (Point *)a;
    Point *B = (Point *)b;
    if (A->y < B->y)
        return 1;
    else if (A->y > B->y)
        return -1;
    else
        return 0;
}

/* sort an array of ints into an array of points in decreasing order */
void sortdesc(int x[], Point sx[])
{
    for (uint32_t i = 0; i < IS; i++) {
        sx[i].y = x[i];
        sx[i].x = i;
    }
    qsort(sx, IS, sizeof(sx[0]), comPoint);
}

int maxarray(int x[])
{
    int mem = 0; /* Typically this value would be zero */
    for (int i = 0; i<IS; i++)
        mem = max(x[i], mem);
    return mem;
}

/* take a second derivative */
void deriv2(volatile uint16_t x[], int sx[])
{
    int thres;
    //PC.printf("clear\n");
    for (int i = 2; i + 2 < IS; i++) {
        sx[i] = x[i + 2] - 2 * x[i] + x[i - 2];
        //PC.printf("%d %d\n", i, sx[i]);
    }
    thres = 1 * maxarray(sx) / 2; /* play with the coefficient to tune noise robustness */
    for (int i = 1; i + 1 < IS; i++)
        sx[i] = (sx[i] > thres && sx[i] > 700) ? 1 : 0;
    //PC.printf("replot\n");
}

int min(int a, int b)
{
    return (a < b) ? a : b;
}

int max(int a, int b)
{
    return (a > b) ? a : b;
}

float sat(float x, float lim)
{
    if (x > lim)
        return lim;
    else if (x < -lim)
        return -lim;
    else
        return x;
}

int main()
{
    float steer = 0;
    int ddx[IS] = {0};
    int edge[5];
    float err = 0;
    int nedges = 0;
    PC.baud(115200);
    TFC_TickerObj.attach_us(&TFC_TickerUpdate, 1000);
    TFC_Init();
    State s = STOP;
    for (;;) {
        switch (s) {

        case STOP:
            stop();
            if (TFC_GetDIP_Switch() == 0)
                s = GO;
            TFC_SetBatteryLED(15);
            break;
        case GO:
            if (TFC_Ticker[0] > 20 && TFC_LineScanImageReady > 0) {
                TFC_Ticker[0] = 0;
                TFC_LineScanImageReady = 0;
                nedges = 0;
                deriv2(TFC_LineScanImage0, ddx);
                
                for (int i = 21; i+20<IS && nedges < 4; i++) {
                    //PC.printf("%c", ddx[i] == 0 ? ' ' : '|');
                    if (ddx[i - 1] < ddx[i])
                        edge[nedges++] = i;
                }
                
                //PC.printf("\n");
                TFC_SetBatteryLED(nedges);
                if (nedges == 0) {
                    err = 2;
                } else if (nedges == 1 && edge[0] > 64) {
                    err = edge[0] - 90;
                    if(err > 0)
                        err = 0;
                } else if (nedges == 1 && edge[0] <= 64) {
                    err = edge[0] - 37; 
                    if(err < 0)
                        err = 0;
                } else if (nedges == 2) {
                    err = (edge[0] + edge[1]) / 2.0 - 64;
                } else if (nedges == 3 && edge[1] < 64) {
                    err = (edge[1] + edge[2]) / 2.0 - 64;
                } else if (nedges == 3 && edge[1] >= 64) {
                    err = (edge[0] + edge[1]) / 2.0 - 64;
                } else if (nedges == 4) {
                    s = BRAKE;
                }
                steer = sat(0.50 * steer + err * 0.01 * (TFC_ReadPot(1) + 1), 0.44);
                
                drive(steer, 0.5 * (TFC_ReadPot(0) + 1));
            }
            if (TFC_GetDIP_Switch() != 0)
                s = STOP;
            break;
        case BRAKE:
            drive(0, -0.5);
            wait_ms(400);
            s = DONE;
            break;
        case DONE:
            stop();
            if (TFC_GetDIP_Switch() != 0)
                s = STOP;
            break;
        default:
            s = STOP;
            break;
        }
    }
}