Last update drone code.
Dependencies: EthernetNetIf mbed ADXL345_I2C ITG3200 L3G4200D IMUfilter
Revision 0:d96713a4739f, committed 2012-06-01
- Comitter:
- SED9008
- Date:
- Fri Jun 01 08:17:40 2012 +0000
- Commit message:
Changed in this revision
diff -r 000000000000 -r d96713a4739f ADXL345_I2C.lib --- /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
diff -r 000000000000 -r d96713a4739f EthernetNetIf.lib --- /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
diff -r 000000000000 -r d96713a4739f IMUfilter.lib --- /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
diff -r 000000000000 -r d96713a4739f ITG3200.lib --- /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
diff -r 000000000000 -r d96713a4739f L3G4200D.lib --- /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
diff -r 000000000000 -r d96713a4739f main.cpp --- /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
diff -r 000000000000 -r d96713a4739f mbed.bld --- /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