Generation 3 of the Harp project

Dependencies:   Servo TMP36 GZ buffered-serial1 chan_fatfs_sd nmea_parser watchdog mbed-rtos mbed

Fork of HARP2 by Tyler Weaver

main.cpp

Committer:
tylerjw
Date:
2012-12-13
Revision:
22:becb67846755
Parent:
21:8799ee63c2cd
Child:
23:5a7b5db55be5

File content as of revision 22:becb67846755:

#include "mbed.h"
#include "rtos.h"
#include "buffered_serial.h"
#include "ff.h"
#include "BMP085.h"
#include "GPS_parser.h"
#include "config.h"

I2C i2c(p9, p10); // sda, scl
BMP085 alt_sensor(i2c);

Serial pc(USBTX, USBRX);
BufferedSerial gps(NC, p14);
AnalogIn gps_battery(p20);
AnalogIn mbed_battery(p19);

GPS_Parser nmea;

Semaphore parachute_sem(0);

typedef struct {
    char    line[80];
} gps_line;
MemoryPool<gps_line, 16> mpool_gps_line;
Queue<gps_line, 16> queue_gps_line;

typedef struct {
    char line[80];
} sensor_line;
MemoryPool<sensor_line, 16> mpool_sensor_line;
Queue<sensor_line, 16> queue_sensor_line;

void gps_thread(void const *args)
{
    char buffer[80];
    float alt, alt_prev;
    alt = alt_prev = 0;

    //DigitalOut gps_led(LED4);

    gps.baud(4800);

    while(true) {
        //gps_led = !gps_led;
        gps.read_line(buffer);
        int line_type = nmea.parse(buffer);
        //pc.puts(buffer);
        // send to log...
        gps_line *message = mpool_gps_line.alloc();
        strcpy(message->line, buffer);
        queue_gps_line.put(message);

        // debugging
        //pc.printf("%d, %f, %f, %f\r\n", nmea.get_date(), nmea.get_time(), nmea.get_msl_altitude(), nmea.get_altitude_ft());
        //pc.printf("%f, %f\r\n", nmea.get_dec_longitude(), nmea.get_dec_latitude());
        //pc.printf("%f, %f, %f\r\n", nmea.calc_dist_to_mi(lat,lon), nmea.calc_dist_to_km(lat,lon), nmea.calc_course_to(lat,lon));

        // test altitude direction - release parachute thread to run
        if(line_type == RMC && nmea.get_lock()) {
            if(UNLOCK_ON_FALL) {
                if(alt != 0) { // first time
                    alt = nmea.get_msl_altitude();
                } else {
                    alt_prev = alt;
                    alt = nmea.get_msl_altitude();
                    if(alt < alt_prev) // going down
                        parachute_sem.release(); // let the parachute code execute
                }
            } else {
                parachute_sem.release();
            }
        }
    }
}

void log_thread(const void *args)
{
    FATFS fs;
    FIL fp_gps, fp_sensor;

    DigitalOut log_led(LED3);

    f_mount(0, &fs);
    f_open(&fp_gps, "0:gps.txt", FA_CREATE_ALWAYS | FA_WRITE);
    f_open(&fp_sensor, "0:sensors.csv", FA_CREATE_ALWAYS | FA_WRITE);

    while(1) {
        log_led = !log_led;
        osEvent evt1 = queue_gps_line.get(1);
        if (evt1.status == osEventMessage) {
            gps_line *message = (gps_line*)evt1.value.p;

            f_puts(message->line, &fp_gps);
            f_sync(&fp_gps);

            mpool_gps_line.free(message);
        }

        osEvent evt2 = queue_sensor_line.get(1);
        if(evt2.status == osEventMessage) {
            sensor_line *message = (sensor_line*)evt2.value.p;

            f_puts(message->line, &fp_sensor);
            f_sync(&fp_sensor);

            mpool_sensor_line.free(message);
        }
    }
}

void sensor_thread(const void* args)
{
    DigitalOut sensor_led(LED2);
    Timer t;
    float time;
    float gps_battery_voltage, mbed_battery_voltage;
    float bmp_temperature, bmp_altitude;
    int bmp_pressure;

    if(WAIT_FOR_LOCK) {
        while(!nmea.get_date())  Thread::wait(100); // wait for lock
    }

    t.start(); // start timer after lock

    sensor_line *message = mpool_sensor_line.alloc();
    sprintf(message->line, "Date: %d, Time: %f\r\nGPS Time (UTC),GPS Battery(V),mbed Battery(V),BMP085 Temperature(C),Pressure,Altitude(ft),GPS Altitude, GPS Course\r\n", nmea.get_date(), nmea.get_time());
    queue_sensor_line.put(message);

    while(true) {
        //get sensor line memory
        sensor_led = !sensor_led;
        sensor_line *message = mpool_sensor_line.alloc();

        //timestamp
        time = nmea.get_time();

        //gps battery
        gps_battery_voltage = gps_battery.read()*BAT_GPS_MUL;

        //mbed battery
        mbed_battery_voltage = mbed_battery.read()*BAT_MBED_MUL;

        //BMP085
        bmp_temperature = (float)alt_sensor.get_temperature() / 10.0;
        bmp_pressure = alt_sensor.get_pressure();
        bmp_altitude = alt_sensor.get_altitude_ft();

        sprintf(message->line, "%f,%f,%f,%f,%d,%f,%f,%f\r\n", time,gps_battery_voltage,mbed_battery_voltage,bmp_temperature,bmp_pressure,bmp_altitude,nmea.get_altitude_ft(),nmea.get_course_d());
        queue_sensor_line.put(message);
    }
}

void parachute_thread(const void *args)
{
    DigitalOut left_turn(LED4);
    DigitalOut right_turn(LED1);

    right_turn = 1;
    Thread::wait(400);
    left_turn = 1;
    Thread::wait(400);
    while(true) {
        right_turn = left_turn = 0;
        parachute_sem.wait();

        float distance = nmea.calc_dist_to_km(target_lat, target_lon);

        if(distance < distance_fudge_km)
            continue; // dont do anything

        float course = nmea.get_course_d();
        float course_to = nmea.calc_course_to(target_lat, target_lon);
        float course_diff = course_to - course;
        
        if(course == 0.0) // not moving fast enough
            continue; // do nothing

        if(course_diff < course_fudge && course_diff > neg_course_fudge) {
            right_turn = left_turn = 1;
            Thread::wait(400);
            continue; // don't do anything
        } else if(course_diff > 180.0 || course_diff < 0.0) {
            left_turn = 1;
            Thread::wait(400); // turn left
        } else {
            right_turn = 1;
            Thread::wait(400); // turn righ
        }
    }
}

int main()
{
    pc.baud(9600);
    Thread thread(gps_thread, NULL, osPriorityHigh);
    Thread thread2(log_thread, NULL, osPriorityNormal);
    Thread thread3(sensor_thread, NULL, osPriorityNormal);
    Thread thread4(parachute_thread, NULL, osPriorityRealtime);

    while(true) ;
}