Last update drone code.

Dependencies:   EthernetNetIf mbed ADXL345_I2C ITG3200 L3G4200D IMUfilter

Files at this revision

API Documentation at this revision

Comitter:
SED9008
Date:
Fri Jun 01 08:17:40 2012 +0000
Commit message:

Changed in this revision

ADXL345_I2C.lib Show annotated file Show diff for this revision Revisions of this file
EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
IMUfilter.lib Show annotated file Show diff for this revision Revisions of this file
ITG3200.lib Show annotated file Show diff for this revision Revisions of this file
L3G4200D.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADXL345_I2C.lib	Fri Jun 01 08:17:40 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/SED9008/code/ADXL345_I2C/#a973ef498a1d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetNetIf.lib	Fri Jun 01 08:17:40 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IMUfilter.lib	Fri Jun 01 08:17:40 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/SED9008/code/IMUfilter/#4e7171d6f97e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ITG3200.lib	Fri Jun 01 08:17:40 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/SED9008/code/ITG3200/#f075e92ce8d2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/L3G4200D.lib	Fri Jun 01 08:17:40 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/SED9008/code/L3G4200D/#13307e4676f9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Jun 01 08:17:40 2012 +0000
@@ -0,0 +1,540 @@
+#include "mbed.h"
+#include "EthernetNetIf.h"
+#include "TCPSocket.h"
+#include "ADXL345_I2C.h"
+#include "ITG3200.h"
+#include "IMUfilter.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.002
+//Sampling accelerometer at 200Hz.
+#define ACC_RATE    0.002
+//Updating filter at 100Hz.
+#define FILTER_RATE 0.01
+#define CORRECTION_MAGNITUDE 50
+
+
+//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);
+I2C i2c(p9, p10); // sda, scl
+ITG3200 gyroscope(p9, p10);
+Ticker accelerometerTicker;
+Ticker gyroscopeTicker;
+Ticker filterTicker;
+Ticker dataTicker;
+Ticker algorithmTicker;
+DigitalOut led1(LED1, "led1");
+DigitalOut led2(LED2, "led2");
+DigitalOut led4(LED4, "led4");
+PwmOut m1(p21);
+PwmOut m2(p22);
+PwmOut m3(p23);
+PwmOut m4(p24);
+
+// EthernetNetIf eth;
+EthernetNetIf eth(
+  IpAddr(192,168,0,25), //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;
+
+int calibrate   = 0,
+    calibrated  = 0,
+    start       = 0,
+    started     = 0,
+    alg_enable  = 0;
+    
+double a_motor_1 = 0,
+       a_motor_2 = 0,
+       a_motor_3 = 0,
+       a_motor_4 = 0;
+      
+float m1_set    = 0.001,
+      m2_set    = 0.001,
+      m3_set    = 0.001,
+      m4_set    = 0.001,
+      thrust_m1 = 3,
+      thrust_m2 = 3,
+      thrust_m3 = 3,
+      thrust_m4 = 3;
+
+char data[128];
+//Offsets 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;
+
+void onConnectedTCPSocketEvent(TCPSocketEvent e);
+void onListeningTCPSocketEvent(TCPSocketEvent e);
+void tcp_send(const char*);
+//Set up the ADXL345 appropriately.
+void initializeAcceleromter(void);
+//Calculate the null bias.
+void calibrateAccelerometer(void);
+//Take a set of samples and average them.
+void sampleAccelerometer(void);
+//Set up the ITG3200 appropriately.
+void initializeGyroscope(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 getI2CAddress();
+
+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 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 initializeGyroscope(void) {
+
+    //Low pass filter bandwidth of 42Hz.
+    gyroscope.setLpBandwidth(LPFBW_42HZ);
+    //Internal sample rate of 200Hz. (1kHz / 5).
+    gyroscope.setSampleRateDivider(4);
+
+}
+
+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++) {
+
+        w_xAccumulator += gyroscope.getGyroX();
+        w_yAccumulator += gyroscope.getGyroY();
+        w_zAccumulator += gyroscope.getGyroZ();
+        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 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.
+        w_xAccumulator += gyroscope.getGyroX();
+        w_yAccumulator += gyroscope.getGyroY();
+        w_zAccumulator += gyroscope.getGyroZ();
+
+        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();
+    alg_enable = 1;
+}
+
+
+void algorithm(void)
+{
+    if(alg_enable){
+    
+        int temp_x = toDegrees(imuFilter.getRoll());
+        int temp_y = toDegrees(imuFilter.getPitch());
+        
+        double x = temp_x;
+        double y = temp_y;
+        
+        a_motor_1   = thrust_m1 + ((((float)x/-2)-((float)y/2))/CORRECTION_MAGNITUDE);
+        thrust_m1   += ((((float)x/-2)-((float)y/2))/CORRECTION_MAGNITUDE)/20;
+        
+        if(a_motor_1 < 0.1){ 
+            m1_set = 0.001175;
+            a_motor_1 = 0.999;
+        }
+        else{m1_set = (a_motor_1+117.5)/100000;}
+  
+  
+        a_motor_2   = thrust_m2 + ((((float)x/-2)+((float)y/2))/CORRECTION_MAGNITUDE);
+        thrust_m2   += ((((float)x/-2)+((float)y/2))/CORRECTION_MAGNITUDE)/20;        
+        if(a_motor_2 < 0.1){ 
+            m2_set = 0.001175;
+            a_motor_2 = 0.999;
+        }
+        else{m2_set = (a_motor_2+117.5)/100000;}
+ 
+        a_motor_3   = thrust_m3 + ((((float)x/2)+((float)y/2))/CORRECTION_MAGNITUDE);
+        thrust_m3   += ((((float)x/2)+((float)y/2))/CORRECTION_MAGNITUDE)/20;
+        if(a_motor_3 < 0.1){ 
+            m3_set = 0.001175;
+            a_motor_3 = 0.999;
+        }
+        else{m3_set = (a_motor_3+117.5)/100000;}
+        
+        a_motor_4   = thrust_m4 + ((((float)x/2)-((float)y/2))/CORRECTION_MAGNITUDE);
+        thrust_m4   += ((((float)x/2)-((float)y/2))/CORRECTION_MAGNITUDE)/20;
+        if(a_motor_4 < 0.1){ 
+            m4_set = 0.001175;
+            a_motor_4 = 0.999;
+        }
+        else{m4_set = (a_motor_4+117.5)/100000;}
+        
+        m1.pulsewidth(m1_set);
+        m2.pulsewidth(m2_set);
+        m3.pulsewidth(m3_set);
+        m4.pulsewidth(m4_set);
+        alg_enable = 0;
+    }
+
+}
+
+void dataSender(void) {
+    char buffer [128];
+    sprintf (buffer, "x:%f | y:%f | am1:%f | am3:%f\r\n",toDegrees(imuFilter.getRoll()),toDegrees(imuFilter.getPitch()),a_motor_1, a_motor_3);
+    tcp_send(buffer);
+}
+
+int main() {
+    EthernetErr ethErr = eth.setup();
+    if(ethErr){
+        printf("Error %d in setup.\r\n", 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));
+    printf("Binding..\r\n");
+    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);
+    wait(0.3);
+    
+    //Initialize inertial sensors.
+    initializeAccelerometer();
+    initializeGyroscope();
+
+                
+    Timer tmr;
+    tmr.start();
+    
+    while(true)
+    {
+        Net::poll();
+        if(tmr.read() > 0.2){
+            led4=!led4;
+            tmr.reset();
+        }
+        
+        if(calibrate && !calibrated){
+            calibrateAccelerometer();
+            calibrateGyroscope();
+            led2 = 1;
+            calibrated = 1;
+            tcp_send("Calibrated\r\n");
+        }
+        
+        if(calibrated && start && !started){
+            //Accelerometer data rate is 500Hz, so we'll sample at this speed.
+            accelerometerTicker.attach(&sampleAccelerometer, 0.002);
+            //Gyroscope data rate is 500Hz, so we'll sample at this speed.
+            gyroscopeTicker.attach(&sampleGyroscope, 0.002);
+            //Update the filter variables at the correct rate.
+            filterTicker.attach(&filter, FILTER_RATE);
+            dataTicker.attach(&dataSender, 0.2);
+            algorithmTicker.attach(&algorithm, 0.001);
+            started = 1;
+        }        
+    }  
+}
+
+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 tcp_send( const char* data ){
+    int len = strlen(data);
+    pConnectedSock->send(data, len);
+}
+
+void onConnectedTCPSocketEvent(TCPSocketEvent e)
+{
+   switch(e)
+    {
+    case TCPSOCKET_CONNECTED:
+        led1 = 1;
+        printf("TCP Socket Connected\r\n");
+        break;
+    case TCPSOCKET_WRITEABLE:
+        led1 = 1;
+        //Can now write some data...
+        printf("TCP Socket Writable\r\n");
+        break;
+    case TCPSOCKET_READABLE:
+        led1 = 1;
+        //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|\r\n", test);
+           tcp_send(buffer);
+           if(test == 99)   {calibrate = 1;}
+           if(test == 115)  {start = 1;}
+           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"); 
+     };
+}
+
+void getI2CAddress()
+{
+    int count = 1;
+    for (int address=0; address<256; address+=2) {
+        if (!i2c.write(address, NULL, 0)) { // 0 returned is ok    
+            char buffer [128];
+            sprintf (buffer, "%i: - %i\n",count, address);
+            tcp_send(buffer);
+            count++;    
+        }           
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Jun 01 08:17:40 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/74b8d43b5817