Dependencies:   EthernetNetIf mbed

main.cpp

Committer:
SED9008
Date:
2012-04-12
Revision:
1:5721a5772035
Parent:
0:ad88907cf227
Child:
2:53614df77a8e

File content as of revision 1:5721a5772035:

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "IMUfilter.h"
#include "ADXL345_I2C.h"
#include "L3G4200D.h"

#define TCP_LISTENING_PORT 1337
//Gravity at Earth's surface in m/s/s
#define g0 9.812865328
//Number of samples to average.
#define SAMPLES 4
//Number of samples to be averaged for a null bias calculation
//during calibration.
#define CALIBRATION_SAMPLES 128
//Convert from radians to degrees.
#define toDegrees(x) (x * 57.2957795)
//Convert from degrees to radians.
#define toRadians(x) (x * 0.01745329252)
//ITG-3200 sensitivity is 14.375 LSB/(degrees/sec).
#define GYROSCOPE_GAIN (1 / 14.375)
//Full scale resolution on the ADXL345 is 4mg/LSB.
#define ACCELEROMETER_GAIN (0.004 * g0)
//Sampling gyroscope at 200Hz.
#define GYRO_RATE   0.005
//Sampling accelerometer at 200Hz.
#define ACC_RATE    0.005
//Updating filter at 20Hz.
#define FILTER_RATE 0.025
//Defines the delay for the corrections made by the algorithm
#define CORRECTION_DELAY 5

//At rest the gyroscope is centred around 0 and goes between about
//-5 and 5 counts. As 1 degrees/sec is ~15 LSB, error is roughly
//5/15 = 0.3 degrees/sec.
IMUfilter imuFilter(FILTER_RATE, 0.3);
ADXL345_I2C accelerometer(p9, p10);
L3G4200D gyroscope(p9, p10);

PwmOut m1(p21);
PwmOut m2(p22);
PwmOut m3(p23);
PwmOut m4(p24);

Ticker accelerometerTicker;
Ticker gyroscopeTicker;
Ticker filterTicker;
Ticker motorTicker;

//Variables for the tcp controls
int connected   = 0,
    calibrated  = 0,
    led1        = 0;
    
//stabilizing variables, these control the thrust and wanted x/y level
float m1_set    = 0.001,
      m2_set    = 0.001,
      m3_set    = 0.001,
      m4_set    = 0.001;
      
double    a_motor_1   = 0,
          a_motor_2   = 0,
          a_motor_3   = 0,
          a_motor_4   = 0;

int x_level_1   = 0,
    x_level_2   = 0,
    x_level_3   = 0,
    x_level_4   = 0,
    y_level_1   = 0,
    y_level_2   = 0,
    y_level_3   = 0,
    y_level_4   = 0;
    
//O1ffsets for the gyroscope.
//The readings we take when the gyroscope is stationary won't be 0, so we'll
//average a set of readings we do get when the gyroscope is stationary and
//take those away from subsequent readings to ensure the gyroscope is offset
//or "biased" to 0.
double w_xBias;
double w_yBias;
double w_zBias;

//Offsets for the accelerometer.
//Same as with the gyroscope.
double a_xBias;
double a_yBias;
double a_zBias;

//Accumulators used for oversampling and then averaging.
volatile double a_xAccumulator = 0;
volatile double a_yAccumulator = 0;
volatile double a_zAccumulator = 0;
volatile double w_xAccumulator = 0;
volatile double w_yAccumulator = 0;
volatile double w_zAccumulator = 0;

//Accelerometer and gyroscope readings for x, y, z axes.
volatile double a_x;
volatile double a_y;
volatile double a_z;
volatile double w_x;
volatile double w_y;
volatile double w_z;

//Buffer for accelerometer readings.
int readings[3];
//Number of accelerometer samples we're on.
int accelerometerSamples = 0;
//Number of gyroscope samples we're on.
int gyroscopeSamples = 0;

/**
 * Prototypes
 */
//Set up the ADXL345 appropriately.
void initializeAccelerometer(void);
//Calculate the null bias.
void calibrateAccelerometer(void);
//Take a set of samples and average them.
void sampleAccelerometer(void);
//Calculate the null bias.
void calibrateGyroscope(void);
//Take a set of samples and average them.
void sampleGyroscope(void);
//Update the filter and calculate the Euler angles.
void filter(void);
void motor(void);
void tcp_send(const char*);
void onConnectedTCPSocketEvent(TCPSocketEvent e);
void onListeningTCPSocketEvent(TCPSocketEvent e);

// EthernetNetIf eth;
EthernetNetIf eth(
  IpAddr(192,168,0,16), //IP Address
  IpAddr(255,255,255,0), //Network Mask
  IpAddr(192,168,0,1), //Gateway
  IpAddr(192,168,0,1)  //DNS
);

TCPSocket ListeningSock;
TCPSocket* pConnectedSock; // for ConnectedSock
Host client;
TCPSocketErr err;

void sampleAccelerometer(void) {

    //Have we taken enough samples?
    if (accelerometerSamples == SAMPLES) {

        //Average the samples, remove the bias, and calculate the acceleration
        //in m/s/s.
        a_x = ((a_xAccumulator / SAMPLES) - a_xBias) * ACCELEROMETER_GAIN;
        a_y = ((a_yAccumulator / SAMPLES) - a_yBias) * ACCELEROMETER_GAIN;
        a_z = ((a_zAccumulator / SAMPLES) - a_zBias) * ACCELEROMETER_GAIN;

        a_xAccumulator = 0;
        a_yAccumulator = 0;
        a_zAccumulator = 0;
        accelerometerSamples = 0;

    } else {
        //Take another sample.
        accelerometer.getOutput(readings);

        a_xAccumulator += (int16_t) readings[0];
        a_yAccumulator += (int16_t) readings[1];
        a_zAccumulator += (int16_t) readings[2];

        accelerometerSamples++;

    }

}

void sampleGyroscope(void) {

    //Have we taken enough samples?
    if (gyroscopeSamples == SAMPLES) {

        //Average the samples, remove the bias, and calculate the angular
        //velocity in rad/s.
        w_x = toRadians(((w_xAccumulator / SAMPLES) - w_xBias) * GYROSCOPE_GAIN);
        w_y = toRadians(((w_yAccumulator / SAMPLES) - w_yBias) * GYROSCOPE_GAIN);
        w_z = toRadians(((w_zAccumulator / SAMPLES) - w_zBias) * GYROSCOPE_GAIN);

        w_xAccumulator = 0;
        w_yAccumulator = 0;
        w_zAccumulator = 0;
        gyroscopeSamples = 0;

    } else {
        //Take another sample.
        int g[3];
        gyroscope.read(g);
        w_xAccumulator += g[0];
        w_yAccumulator += g[1];
        w_zAccumulator += g[2];

        gyroscopeSamples++;

    }

}

void filter(void) {

    //Update the filter variables.
    imuFilter.updateFilter(w_y, w_x, w_z, a_y, a_x, a_z);
    //Calculate the new Euler angles.
    imuFilter.computeEuler();

}

void motor(void) {
            int x = toDegrees(imuFilter.getRoll());
            int y = toDegrees(imuFilter.getPitch());
            a_motor_1 = a_motor_1+((float)(x/2)/CORRECTION_DELAY)+((float)(y/2)/CORRECTION_DELAY);
            if(a_motor_1>99){       m1_set = 0.002;}
            else if(a_motor_1 < 1){ m1_set = 0.001175;}
            else{                   m1_set = (a_motor_1+117.5)/100000;}
    m1.pulsewidth(m1_set);
    m2.pulsewidth(m2_set);
    m3.pulsewidth(m3_set);
    m4.pulsewidth(m4_set); 
}

int main() {
   
    EthernetErr ethErr = eth.setup();
    if(ethErr)  { return -1;}
    IpAddr ip = eth.getIp();    
    // Set the callbacks for Listening
    ListeningSock.setOnEvent(&onListeningTCPSocketEvent);     
    // bind and listen on TCP
    err=ListeningSock.bind(Host(IpAddr(), TCP_LISTENING_PORT));
    //Deal with that error...
    if(err){printf("Binding Error\n");} 
    err=ListeningSock.listen(); // Starts listening
    if(err){printf("Listening Error\r\n");}
    
    m1.pulsewidth(0.001);
    m2.pulsewidth(0.001);
    m3.pulsewidth(0.001);
    m4.pulsewidth(0.001); 
    
    //Initialize inertial sensors.
    initializeAccelerometer();
    calibrateAccelerometer();
    calibrateGyroscope();

    //Set up timers.
    //Accelerometer data rate is 200Hz, so we'll sample at this speed.
//    accelerometerTicker.attach(&sampleAccelerometer, 0.005);
    //Gyroscope data rate is 200Hz, so we'll sample at this speed.
//    gyroscopeTicker.attach(&sampleGyroscope, 0.005);
    //Update the filter variables at the correct rate.
//    filterTicker.attach(&filter, FILTER_RATE);
        
    Timer tmr;
    tmr.start();
      
    while(true)
    {
        wait(0.2);
        
        Net::poll();
        if(tmr.read() > 0.2){
//            led4=!led4; //Show that we are alive
            tmr.reset();
        } 
        if(connected & led1 == 0){
            tcp_send("Connected\r\n");
            led1    = 1;
            calibrated = 1;
            
//            m1_set = 0.001175;
//            m2_set = 0.001175;
//            m3_set = 0.001175;
//            m4_set = 0.001175; 
            
            //Set up timers.
            //Accelerometer data rate is 200Hz, so we'll sample at this speed.
            accelerometerTicker.attach(&sampleAccelerometer, 0.005);
            //Gyroscope data rate is 200Hz, so we'll sample at this speed.
            gyroscopeTicker.attach(&sampleGyroscope, 0.005);
            //Update the filter variables at the correct rate.
            filterTicker.attach(&filter, FILTER_RATE);
            
            motorTicker.attach(&motor, 0.02);

            tcp_send("Done initializing\r\n");

        }

        if(calibrated){
            

            

            
/*            a_motor_2 = a_motor_2-((((x_level_2-x)/2)-((y_level_2-y)/2))/CORRECTION_DELAY);
            if(a_motor_2>99){       m2_set = (100+117.5)/100000;}
            else if(a_motor_2 < 1){ m2_set = (0+117.5)/100000;}
            else{                   m2_set = (a_motor_2+117.5)/100000;}
            
            a_motor_3 = a_motor_3+((((x_level_3-x)/2)-((y_level_3-y)/2))/CORRECTION_DELAY);
            if(a_motor_3>99){       m3_set = (100+117.5)/100000;}
            else if(a_motor_3 < 1){ m3_set = (0+117.5)/100000;}
            else{                   m3_set = (a_motor_3+117.5)/100000;}
            
            a_motor_4 = a_motor_4+((((x_level_4-x)/2)+((y_level_4-y)/2))/CORRECTION_DELAY);
            if(a_motor_4>99){       m4_set = (100+117.5)/100000;}
            else if(a_motor_4 < 1){ m4_set = (0+117.5)/100000;}
            else{                   m4_set = (a_motor_4+117.5)/100000;}*/
        
        
            char buffer [128];
            sprintf (buffer, "x:%f - y:%f - z:%f \r\n",toDegrees(imuFilter.getRoll()),
                                                        toDegrees(imuFilter.getPitch()),
                                                        toDegrees(imuFilter.getYaw()));
            tcp_send(buffer);   
            sprintf (buffer, "am1:%f\r\n",a_motor_1);
            tcp_send(buffer);   
        }
    }  
}

void initializeAccelerometer(void) {

    //Go into standby mode to configure the device.
    accelerometer.setPowerControl(0x00);
    //Full resolution, +/-16g, 4mg/LSB.
    accelerometer.setDataFormatControl(0x0B);
    //200Hz data rate.
    accelerometer.setDataRate(ADXL345_200HZ);
    //Measurement mode.
    accelerometer.setPowerControl(0x08);
    //See http://www.analog.com/static/imported-files/application_notes/AN-1077.pdf
    wait_ms(22);

}

void calibrateAccelerometer(void) {

    a_xAccumulator = 0;
    a_yAccumulator = 0;
    a_zAccumulator = 0;
    
    //Take a number of readings and average them
    //to calculate the zero g offset.
    for (int i = 0; i < CALIBRATION_SAMPLES; i++) {

        accelerometer.getOutput(readings);

        a_xAccumulator += (int16_t) readings[0];
        a_yAccumulator += (int16_t) readings[1];
        a_zAccumulator += (int16_t) readings[2];

        wait(ACC_RATE);

    }

    a_xAccumulator /= CALIBRATION_SAMPLES;
    a_yAccumulator /= CALIBRATION_SAMPLES;
    a_zAccumulator /= CALIBRATION_SAMPLES;

    //At 4mg/LSB, 250 LSBs is 1g.
    a_xBias = a_xAccumulator;
    a_yBias = a_yAccumulator;
    a_zBias = (a_zAccumulator - 250);

    a_xAccumulator = 0;
    a_yAccumulator = 0;
    a_zAccumulator = 0;

}

void calibrateGyroscope(void) {

    w_xAccumulator = 0;
    w_yAccumulator = 0;
    w_zAccumulator = 0;

    //Take a number of readings and average them
    //to calculate the gyroscope bias offset.
    for (int i = 0; i < CALIBRATION_SAMPLES; i++) {
        int g[3];
        gyroscope.read(g);
        w_xAccumulator += g[0];
        w_yAccumulator += g[1];
        w_zAccumulator += g[2];
        wait(GYRO_RATE);

    }

    //Average the samples.
    w_xAccumulator /= CALIBRATION_SAMPLES;
    w_yAccumulator /= CALIBRATION_SAMPLES;
    w_zAccumulator /= CALIBRATION_SAMPLES;

    w_xBias = w_xAccumulator;
    w_yBias = w_yAccumulator;
    w_zBias = w_zAccumulator;

    w_xAccumulator = 0;
    w_yAccumulator = 0;
    w_zAccumulator = 0;

}



void tcp_send( const char* data ){
    int len = strlen(data);
    pConnectedSock->send(data, len);
}

void onConnectedTCPSocketEvent(TCPSocketEvent e)
{
   switch(e)
    {
    case TCPSOCKET_CONNECTED:
        printf("TCP Socket Connected\r\n");
        break;
    case TCPSOCKET_WRITEABLE:
      //Can now write some data...
        printf("TCP Socket Writable\r\n");
        break;
    case TCPSOCKET_READABLE:
      //Can now read dome data...
        printf("TCP Socket Readable\r\n");
       // Read in any available data into the buffer
       char buff[128];
       while ( int len = pConnectedSock->recv(buff, 128) ) {
       // And send straight back out again
//           pConnectedSock->send(buff, len);
           int test = buff[0];
           char buffer[128];
           sprintf(buffer, "|%i|", test);
           tcp_send(buffer); 
           if(test == 115)  {connected = 1;}
           if(test == 112)  {
                a_motor_1 += 5;
                a_motor_1 += 5;
                a_motor_1 += 5;
                a_motor_1 += 5;
           }
           if(test == 49)   {
                m1_set += 0.00002;
                sprintf (buffer, " %f\r\n",m1_set);
                tcp_send(buffer);
           }
           if(test == 50)   {
                m2_set += 0.00002;
                sprintf (buffer, " %f\r\n",m2_set);
                tcp_send(buffer);
           }
           if(test == 51)   {
                m3_set += 0.00002;
                sprintf (buffer, " %f\r\n",m3_set);
                tcp_send(buffer);
           }
           if(test == 52)   {
                m4_set += 0.00002;
                sprintf (buffer, " %f\r\n",m4_set);
                tcp_send(buffer);;
           }
           if(test == 113)  {
                m1_set -= 0.00002;
           }
           if(test == 119)  {
                m2_set -= 0.00002;
           }
           if(test == 101)  {
                m3_set -= 0.00002;
           }
           if(test == 114)  {
                m4_set -= 0.00002;
           }
           if(test == 107)  {
                m1_set = 0.0011;
                m2_set = 0.0011;
                m3_set = 0.0011;
                m4_set = 0.0011;
           }
                 

           buff[len]=0; // make terminater
           printf("Received&Wrote:%s\r\n",buff);
       }
       break;
    case TCPSOCKET_CONTIMEOUT:
        printf("TCP Socket Timeout\r\n");
        break;
    case TCPSOCKET_CONRST:
        printf("TCP Socket CONRST\r\n");
        break;
    case TCPSOCKET_CONABRT:
        printf("TCP Socket CONABRT\r\n");
        break;
    case TCPSOCKET_ERROR:
        printf("TCP Socket Error\r\n");
        break;
    case TCPSOCKET_DISCONNECTED:
    //Close socket...
        printf("TCP Socket Disconnected\r\n");        
        pConnectedSock->close();
        break;
    default:
        printf("DEFAULT\r\n"); 
      }
}


void onListeningTCPSocketEvent(TCPSocketEvent e)
{
    switch(e)
    {
    case TCPSOCKET_ACCEPT:
        printf("Listening: TCP Socket Accepted\r\n");
        // Accepts connection from client and gets connected socket.   
        err=ListeningSock.accept(&client, &pConnectedSock);
        if (err) {
            printf("onListeningTcpSocketEvent : Could not accept connection.\r\n");
            return; //Error in accept, discard connection
        }
        // Setup the new socket events
        pConnectedSock->setOnEvent(&onConnectedTCPSocketEvent);
        // We can find out from where the connection is coming by looking at the
        // Host parameter of the accept() method
        IpAddr clientIp = client.getIp();
        printf("Listening: Incoming TCP connection from %d.%d.%d.%d\r\n", 
           clientIp[0], clientIp[1], clientIp[2], clientIp[3]);
       break;
    // the following cases will not happen
    case TCPSOCKET_CONNECTED:
        printf("Listening: TCP Socket Connected\r\n");
        break;
    case TCPSOCKET_WRITEABLE:
        printf("Listening: TCP Socket Writable\r\n");
        break;
    case TCPSOCKET_READABLE:
        printf("Listening: TCP Socket Readable\r\n");
        break;
    case TCPSOCKET_CONTIMEOUT:
        printf("Listening: TCP Socket Timeout\r\n");
        break;
    case TCPSOCKET_CONRST:
        printf("Listening: TCP Socket CONRST\r\n");
        break;
    case TCPSOCKET_CONABRT:
        printf("Listening: TCP Socket CONABRT\r\n");
        break;
    case TCPSOCKET_ERROR:
        printf("Listening: TCP Socket Error\r\n");
        break;
    case TCPSOCKET_DISCONNECTED:
    //Close socket...
        printf("Listening: TCP Socket Disconnected\r\n");        
        ListeningSock.close();
        break;
    default:
        printf("DEFAULT\r\n"); 
     };
}