JAN 16 2019

Dependencies:   mbed BNO055 MBed_Adafruit-GPS-Library

main.cpp

Committer:
LukeMar
Date:
2019-03-14
Revision:
1:4b4d5d18fc57
Parent:
0:f4edd3407cc5

File content as of revision 1:4b4d5d18fc57:


/*
  Sailbot Hull 14
  L Marino and D Robinson,
  with D Evangelista, P Frontera, M Kutzer, A Laun
  2018

  Threaded version using mbed OS5
  Serial links between nodes
  Stepper motors with Pololu 2968 drivers (MP6500 based)
  Piher PST360 angle sensors
  Adafruit Absolute GPS
  Telemetry via ???Ubiquity???
*/

//Thread for logging time and Gps, heading and encoder values is mostly complete
//control thread is a work in progress

#include "mbed.h"
#include "MBed_Adafruit_GPS.h"
#include "BNO055.h"
#include "Spektrum.h"
#include "unity.h"

Serial pc(USBTX, USBRX, 115200);
Spektrum rx(p13, p14);
int i;
int j;
float now;
//***Mast universal variables***
AnalogIn   ain(p20);
PwmOut  motor( p25 );
DigitalOut   dir( p24 );
DigitalOut    I(p26);
DigitalOut slp(p29); //sleep
float d_ang = 180.0;
float pos = 180.0;
float RC_O;
//***rudder universal variables***
AnalogIn   r_ain(p15);
PwmOut  rudder( p22 );
DigitalOut   r_dir( p21 );
DigitalOut    r_I(p23);
DigitalOut r_slp(p30); //sleep
float r_ang;
float r_pos;
float RC_1;

float xx = 5.5; //changes the threshold that the motor goes to sleep on
float gg = 9.5; //changes the threshold that the motor goes to sleep on for mast
float zz = 121; //changes wait at end of rc thread
float ww = 5; //changes wait time at end of if statments in mast rudder threads
int ff = 65;//changes wait at end of telemetry
//****universal variables for Telemetry****
DigitalOut heartbeat(LED1);
Serial * gps_Serial;
BNO055 bno(p28, p27);
char c; //when read via Adafruit_GPS::read(), the class returns single character stored here
float info; //a multiuse variable used for sending things over GPS
Timer refresh_Timer; //sets up a timer for use in loop; how often do we print GPS info?
const int refresh_Time = 2000; //refresh time in ms
       //wait time between pieces of telemetry info


union Float {       //slightly mysterious data type that we use to send data over serial
    float    m_float;
    uint8_t  m_bytes[sizeof(float)];
};
float        data;
uint8_t      bytes[sizeof(float)];
Float        myFloat;

//**get position**
float posi();
float posr();

//*********read reads yaw from IMU **************
void yaw_read()
{
    bno.get_angles();
    data = bno.euler.yaw;
    myFloat.m_float = data;
    data = myFloat.m_float;   // get the float back from the union
    pc.printf("%.1f", data);
    Thread::wait(ff);

}

void roll_read()
{
    bno.get_angles();
    data = bno.euler.roll;
    myFloat.m_float = data;
    data = myFloat.m_float;   // get the float back from the union
    pc.printf("%.1f", data);
    Thread::wait(ff);

}

//********concatenate time (not currently in use)**********
float conc(float hr, float min, float sec )
{
    return hr+(min/60.0)+(sec/3600.0);
}
//********Initialize IMU************

void bno_init(void)
{
    if(bno.check()) {
        //pc.printf("BNO055 connected\r\n");
        bno.reset();
        Thread::wait(30);
        bno.setmode(OPERATION_MODE_CONFIG);
        bno.SetExternalCrystal(1);
        //bno.set_orientation(1);
        bno.setmode(OPERATION_MODE_NDOF);  //Uses magnetometer
        //bno.setmode(OPERATION_MODE_NDOF_FMC_OFF);   //no magnetometer
        bno.set_angle_units(RADIANS);
    } else {
        //pc.printf("BNO055 NOT connected\r\n Program Trap.");
        while(1);
    }
}

// *****threading*****
Thread telemetry_thread;
Thread mast_thread;
Thread rudder_thread;

void telemetry_callback(void);
void mast_callback(void);
void rudder_callback(void);

int main()
{
    //start all threads
    wait(1);
    telemetry_thread.start(callback(telemetry_callback));
    mast_thread.start(callback(mast_callback));
    rudder_thread.start(callback(rudder_callback));
    //could have a heart beat but I tried to reduce the number of threads fighting for time
}//end main

float posi()
{
    float p1;
    float p2;
    float p3;
    p1 = ain*449.0-147.53;  //ain*447.73-147.53;
    Thread::wait(3);
    p2 = ain*447.73-147.53;
    Thread::wait(3);
    p3 = ain*447.73-147.53;
    
    return (p1+p2+p3)/3.0;
}
float posr()
{
    float r1;
    float r2;
    float r3;
    r1 = (r_ain-.108)/.002466;
    Thread::wait(3);
    r2 = (r_ain-.108)/.002466;
    Thread::wait(3);
    r3 = (r_ain-.108)/.002466;
    return (r1+r2+r3)/3.0;
}

void telemetry_callback(void)
{
    //uint64_t now;
    //debug("telemetry_thread started\r\n");

    
    gps_Serial = new Serial(p9,p10); //serial object for use w/ GPS
    Adafruit_GPS myGPS(gps_Serial); //object of Adafruit's GPS class

    myGPS.begin(9600);  //sets baud rate for GPS communication; note this may be changed via Adafruit_GPS::sendCommand(char *)
    //a list of GPS commands is available at http://www.adafruit.com/datasheets/PMTK_A08.pdf

    myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation
    myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
    myGPS.sendCommand(PGCMD_ANTENNA);

    //pc.printf("Connection established at 115200 baud...\n");
    bno_init();

    Thread::wait(100);
    refresh_Timer.start();  //starts the clock on the timer

    while(true) {

        c = myGPS.read();   //queries the GPS
        bno.get_angles();
        //check if we recieved a new message from GPS, if so, attempt to parse it,
        if ( myGPS.newNMEAreceived() ) {
            if ( !myGPS.parse(myGPS.lastNMEA()) ) {
                continue;
            }//if ( !myGPS.parse..

            if (refresh_Timer.read_ms() >= refresh_Time) {
                refresh_Timer.reset();

               /* data = conc(myGPS.hour, myGPS.minute, myGPS.seconds );               // conc(myGPS.hour, myGPS.minute, myGPS.seconds );
                myFloat.m_float = data;
                data = myFloat.m_float;   // get the float back from the union
                pc.printf("%2.0f", data);
                Thread::wait(ff);*/
                //  this part can send hr min second separately, commented to save thread space
                data = myGPS.hour;               // conc(myGPS.hour, myGPS.minute, myGPS.seconds );
                myFloat.m_float = data;
                data = myFloat.m_float;   // get the float back from the union
                pc.printf("%2.0f", data);
                Thread::wait(35);
                //send min
                data = myGPS.minute;               // conc(myGPS.hour, myGPS.minute, myGPS.seconds );
                myFloat.m_float = data;
                data = myFloat.m_float;   // get the float back from the union
                pc.printf("%2.0f", data);
                Thread::wait(35);
                //send sec
                data = myGPS.seconds;               // conc(myGPS.hour, myGPS.minute, myGPS.seconds );
                myFloat.m_float = data;
                data = myFloat.m_float;   // get the float back from the union
                pc.printf("%2.0f", data);
                Thread::wait(35);
                
                if (myGPS.fix) {
                    //rudder and mast position will log here
                    //send mast angle
                   /* data = posi();
                    myFloat.m_float = data;
                    data = myFloat.m_float;   // get the float back from the union
                    pc.printf("%.1f", data);
                    Thread::wait(ff);
                    //send rudder angle
                    data = posr();
                    myFloat.m_float = data;
                    data = myFloat.m_float;   // get the float back from the union
                    pc.printf("%.1f", data);
                    Thread::wait(ff);*/
                    //send latitude
                    data = myGPS.latitude;
                    myFloat.m_float = data;
                    data = myFloat.m_float;   // get the float back from the union
                    pc.printf("%.3f", data);
                    Thread::wait(ff);
                    //send logitude
                    data = myGPS.longitude;
                    myFloat.m_float = data;
                    data = myFloat.m_float;   // get the float back from the union
                    pc.printf("%.3f", data);
                    Thread::wait(ff);
                    //send yaw
                    yaw_read();
                    roll_read();
                    //send transmittion
                    pc.printf("q");
                    Thread::wait(1000);
                }//if (myGPS.fix)
            }//if (refresh_Timer..
        }//if ( myGPS.newNMEAreceived() )
    }//while(true)
} // telemetry_callback()

void mast_callback(void)
{

    I=0; //sets for 1.5amp output
    motor.period(.001); //sets the pulse width modulation period
    motor.pulsewidth(0);
    slp = 0;
    r_slp = 0; //sstarts the current driver in off state
    Thread::wait(10);
    // loop
    while(1) {

        if (rx.valid) {
            RC_O = rx.channel[0];
        } else {
            //pc.printf(" invalid\r\n");
            slp = 0;
        }
        //39.19
        d_ang = (RC_O/6.77)-10.0;      //(RC_O/6.77)+39.19;
        pos = posi();
        //printf("%f\n",ain);
        if((pos > (d_ang-gg))&& (pos < (d_ang+gg))) {
            motor.pulsewidth(0);
            slp = 0;
        }
        if( (pos > (d_ang+gg))) {
            slp = 1;
            dir = 1; //left??
            motor.pulsewidth(.0005);
            //pc.printf("pos: %.3f\n",pos);
            Thread::wait(ww);
            pos = posi();
        }//if pos
        if((pos < (d_ang-gg))) {
            slp = 1;
            dir = 0; //right??
            motor.pulsewidth(.0005);
            //pc.printf("pos: %.3f\n",pos);
            Thread::wait(ww);
            pos = posi();
        }
        ThisThread::sleep_until(zz);
    }//while(1)
}//mast callback

void rudder_callback(void)
{

    r_I=0; //sets for 1.5amp output
    rudder.period(.001); //sets the pulse width modulation period
    rudder.pulsewidth(0);
    slp = 0;
    r_slp = 0; //sstarts the current driver in off state
    Thread::wait(10);

    // loop
    while(1) {

        if (rx.valid) {
            RC_1 = rx.channel[1];
        } else {
            //pc.printf(" invalid\r\n");
            r_slp = 0;
        }
        //39.19
        r_ang = (RC_1/6.77)-5.0;
        r_pos = posr();

        if((r_pos > (r_ang-xx)) && (r_pos < (r_ang+xx))) {
            rudder.pulsewidth(0);
            r_slp = 0;
        }
        if( (r_pos > (r_ang+xx)) ) {  //&& r_pos < 235.0
            r_slp = 1;
            r_dir = 1; //left??
            rudder.pulsewidth(.0005);
            Thread::wait(ww);
            r_pos = posr();
        }//if pos
        if((r_pos < (r_ang-xx)) ) {   // && r_pos > 55.0
            r_slp = 1;
            r_dir = 0; //right??
            rudder.pulsewidth(.0005);
            Thread::wait(ww);
            r_pos = posr();
        }
        ThisThread::sleep_until(zz);
    }//while(1)
}//rudder callback