NOT FINISHED YET!!! My first try to get a self built fully working Quadrocopter based on an mbed, a self built frame and some other more or less cheap parts.

Dependencies:   mbed MODI2C

Files at this revision

API Documentation at this revision

Comitter:
maetugr
Date:
Wed Oct 17 08:37:08 2012 +0000
Parent:
9:4e0c3936c756
Child:
11:9bf69bc6df45
Commit message:
neue Acc_Winkelberechnung, vor Kompassklassenrevision

Changed in this revision

HMC5883/HMC5883.cpp Show annotated file Show diff for this revision Revisions of this file
PID.lib Show annotated file Show diff for this revision Revisions of this file
RC/RC_Channel.cpp Show annotated file Show diff for this revision Revisions of this file
RC/RC_Channel.h Show annotated file Show diff for this revision Revisions of this file
Sensors/Acc/ADXL345.cpp Show annotated file Show diff for this revision Revisions of this file
Sensors/Acc/ADXL345.h Show annotated file Show diff for this revision Revisions of this file
Sensors/Gyro/L3G4200D.cpp Show annotated file Show diff for this revision Revisions of this file
Sensors/Gyro/L3G4200D.h 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
--- a/HMC5883/HMC5883.cpp	Tue Oct 16 10:21:32 2012 +0000
+++ b/HMC5883/HMC5883.cpp	Wed Oct 17 08:37:08 2012 +0000
@@ -10,10 +10,10 @@
     Init();
     // MYINIT ----------
     //Kompass kalibrieren  --> Problem fremde Magnetfelder!
-    //AutoCalibration = 1;
-    short MagRawMin[3]= {-400, -400, -400};     //Gespeicherte Werte verwenden
-    short MagRawMax[3]= {400, 400, 400};
-    Calibrate(MagRawMin, MagRawMax);
+    AutoCalibration = 1;
+    //short MagRawMin[3]= {-400, -400, -400};     //Gespeicherte Werte verwenden
+    //short MagRawMax[3]= {400, 400, 400};
+    //Calibrate(MagRawMin, MagRawMax);
     //Calibrate(20);
     // MYINIT ----------
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PID.lib	Wed Oct 17 08:37:08 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/aberk/code/PID/#6e12a3e5af19
--- a/RC/RC_Channel.cpp	Tue Oct 16 10:21:32 2012 +0000
+++ b/RC/RC_Channel.cpp	Wed Oct 17 08:37:08 2012 +0000
@@ -3,8 +3,10 @@
 
 RC_Channel::RC_Channel(PinName mypin) : myinterrupt(mypin)
 {
+    time = -1; // start value to see if there was any value yet
     myinterrupt.rise(this, &RC_Channel::rise);
     myinterrupt.fall(this, &RC_Channel::fall);
+    timeoutchecker.attach(this, &RC_Channel::timeoutcheck, 1);
 }
 
 int RC_Channel::read()
@@ -22,4 +24,11 @@
     timer.stop();
     time = timer.read_us();
     timer.reset();
+    timer.start();
+}
+
+void RC_Channel::timeoutcheck()
+{
+    if (timer.read() > 0.3)
+        time = 0;
 }
\ No newline at end of file
--- a/RC/RC_Channel.h	Tue Oct 16 10:21:32 2012 +0000
+++ b/RC/RC_Channel.h	Wed Oct 17 08:37:08 2012 +0000
@@ -6,15 +6,18 @@
 class RC_Channel
 {
     public:
-        RC_Channel(PinName mypin); // noooo p19/p20!!!!
-        int read();
+        RC_Channel(PinName mypin); // NO p19/p20!!!!, they don't support InterruptIn
+        int read(); // read the last measured data
        
     private:
-        InterruptIn myinterrupt;
-        void rise();
-        void fall();
-        Timer timer;
-        int time;
+        InterruptIn myinterrupt; // interrupt on the pin to react when signal falls or rises
+        void rise(); // start the time measurement when signal rises
+        void fall(); // stop the time mesurement and save the value when signal falls
+        Timer timer; // timer to measure the up time of the signal and if the signal timed out
+        int time; // last measurement data
+        
+        Ticker timeoutchecker; // Ticker to see if signal broke down
+        void timeoutcheck(); // to check for timeout, checked every second
 };
 
 #endif
\ No newline at end of file
--- a/Sensors/Acc/ADXL345.cpp	Tue Oct 16 10:21:32 2012 +0000
+++ b/Sensors/Acc/ADXL345.cpp	Wed Oct 17 08:37:08 2012 +0000
@@ -45,13 +45,19 @@
     writeReg(ADXL345_POWER_CTL_REG, 0x08); // set mode
 }
 
-void ADXL345::read(int a[3]){
+void ADXL345::read(){
     char buffer[6];    
     readMultiReg(ADXL345_DATAX0_REG, buffer, 6);
     
-    a[0] = (short) ((int)buffer[1] << 8 | (int)buffer[0]);
-    a[1] = (short) ((int)buffer[3] << 8 | (int)buffer[2]);
-    a[2] = (short) ((int)buffer[5] << 8 | (int)buffer[4]);
+    data[0] = (short) ((int)buffer[1] << 8 | (int)buffer[0]);
+    data[1] = (short) ((int)buffer[3] << 8 | (int)buffer[2]);
+    data[2] = (short) ((int)buffer[5] << 8 | (int)buffer[4]);
+    
+    // calculate the angles for roll and pitch (0,1)
+    float R = sqrt(pow((float)data[0],2) + pow((float)data[1],2) + pow((float)data[2],2));
+    angle[0] = -(Rad2Deg * acos((float)data[1] / R)-90);
+    angle[1] =   Rad2Deg * acos((float)data[0] / R)-90;
+    angle[2] =   Rad2Deg * acos((float)data[2] / R);
 }
 
 int ADXL345::writeReg(char address, char data){ 
--- a/Sensors/Acc/ADXL345.h	Tue Oct 16 10:21:32 2012 +0000
+++ b/Sensors/Acc/ADXL345.h	Wed Oct 17 08:37:08 2012 +0000
@@ -64,14 +64,17 @@
 #define ADXL345_Y           0x01
 #define ADXL345_Z           0x02
 
+#define Rad2Deg         57.295779513082320876798154814105
+
 typedef char byte;
 
 class ADXL345
 {
     public:
         ADXL345(PinName sda, PinName scl); // constructor, uses i2c
-        void read(int a[3]); // read all axis to array
-        
+        void read(); // read all axis to array
+        int data[3]; // where the measured data is saved
+        float angle[3]; // where the calculated angles are stored
        
     private:
         I2C i2c; // i2c object to communicate
--- a/Sensors/Gyro/L3G4200D.cpp	Tue Oct 16 10:21:32 2012 +0000
+++ b/Sensors/Gyro/L3G4200D.cpp	Wed Oct 17 08:37:08 2012 +0000
@@ -38,12 +38,11 @@
             offset[j] = 0;
             
     float Gyro_calib[3] = {0,0,0}; // temporary to sum up
-    float Gyro_data[3];
     
     for (int i = 0; i < count; i++) {
-        read(Gyro_data);
+        read();
         for (int j = 0; j < 3; j++)
-            Gyro_calib[j] += Gyro_data[j];
+            Gyro_calib[j] += data[j];
         wait(0.001); // maybe less or no wait !!
     }
     
@@ -73,7 +72,7 @@
 }
 
 // Reads the 3 gyro channels and stores them in vector g
-void L3G4200D::read(float g[3])
+void L3G4200D::read()
 {
     byte buffer[6]; // 8-Bit pieces of axis data
     // assert the MSB of the address to get the gyro 
@@ -93,13 +92,13 @@
     uint8_t zla = buffer[4];
     uint8_t zha = buffer[5];
 
-    g[0] = (short) (xha << 8 | xla);
-    g[1] = (short) (yha << 8 | yla);
-    g[2] = (short) (zha << 8 | zla);
+    data[0] = (short) (xha << 8 | xla);
+    data[1] = (short) (yha << 8 | yla);
+    data[2] = (short) (zha << 8 | zla);
     
     //with offset of calibration
     for (int j = 0; j < 3; j++)
-            g[j] -= offset[j];
+            data[j] -= offset[j];
 }
 
 // Reads the gyros Temperature
--- a/Sensors/Gyro/L3G4200D.h	Tue Oct 16 10:21:32 2012 +0000
+++ b/Sensors/Gyro/L3G4200D.h	Wed Oct 17 08:37:08 2012 +0000
@@ -43,8 +43,9 @@
 {
     public:            
         L3G4200D(PinName sda, PinName scl); // constructor, uses i2c
-        void read(float g[3]); // read all axis to array
+        void read(); // read all axis to array
         int readTemp(); // read temperature from sensor
+        float data[3]; // where the measured data is saved
         
     private:
         float offset[3]; // offset that's subtracted from every measurement
--- a/main.cpp	Tue Oct 16 10:21:32 2012 +0000
+++ b/main.cpp	Wed Oct 17 08:37:08 2012 +0000
@@ -1,51 +1,51 @@
 #include "mbed.h"       // Standard Library
 #include "LED.h"        // LEDs framework for blinking ;)
+#include "PC.h"         // Serial Port via USB for debugging in TeraTerm (driver needed: https://mbed.org/media/downloads/drivers/mbedWinSerial_16466.exe)
 #include "L3G4200D.h"   // Gyro (Gyroscope)
 #include "ADXL345.h"    // Acc (Accelerometer)
 #include "HMC5883.h"    // Comp (Compass)
 #include "BMP085.h"     // Alt (Altitude sensor)
 #include "RC_Channel.h" // RemoteControl Chnnels with PPM
 #include "Servo.h"      // Motor PPM
-#include "PC.h"         // Serial Port via USB for debugging
+#include "PID.h"        // PID Library from Aaron Berk
 
-#define PI             3.1415926535897932384626433832795
-#define Rad2Deg        57.295779513082320876798154814105
+#define PI              3.1415926535897932384626433832795
+#define Rad2Deg         57.295779513082320876798154814105
+#define RATE            0.02 // speed of Ticker/PID
 
 Timer GlobalTimer; // global time to calculate processing speed
 Ticker Datagetter; // timecontrolled interrupt to get data form IMU and RC
+PID controller(1.0, 0.0, 0.0, RATE); // test PID controller for throttle
+PID pid(1.0, 1.0, 0.0, RATE); // test PID controller for throttle
 
 // initialisation of hardware
 LED         LEDs;
-PC          pc(USBTX, USBRX, 57600);        //Achtung: Treiber auf PC fuer Serial-mbed installieren. hier herunterladen https://mbed.org/media/downloads/drivers/mbedWinSerial_16466.exe
+PC          pc(USBTX, USBRX, 57600);
 L3G4200D    Gyro(p28, p27);
 ADXL345     Acc(p28, p27);
 HMC5883     Comp(p28, p27, GlobalTimer);
 BMP085      Alt(p28, p27);
 RC_Channel  RC[] = {(p10), (p11), (p12), (p13)}; // noooo p19/p20!!!!
-//Servo       Motor[] = {(p15), (p16), (p17), (p18)};
+Servo       Motor[] = {(p15), (p16), (p17), (p18)};
 
 // variables for loop
 unsigned long   dt = 0;
 unsigned long   time_loop = 0;
 float           angle[3] = {0,0,0}; // angle of calculated situation
-float           Gyro_data[3];
-int             Acc_data[3];
-float           Acc_angle[2] = {0,0};
 float           Comp_angle = 0;
 float           tempangle = 0;
+int             Motorvalue[3];
+
+float pidtester;
 
 void get_Data()
 {
     // read data from sensors
-    Gyro.read(Gyro_data);
-    Acc.read(Acc_data);
+    Gyro.read();
+    Acc.read();
     Comp.Update();
     Alt.Update();
 
-    // calculate the angles for roll and pitch from accelerometer
-    Acc_angle[0] = Rad2Deg * atan2((float)Acc_data[1], (float)Acc_data[2]);
-    Acc_angle[1] = 3 -Rad2Deg * atan2((float)Acc_data[0], (float)Acc_data[2]); // TODO Offset accelerometer einstellen
-    
     //calculate angle for yaw from compass
     Comp_angle = Comp.getAngle(Comp.Mag[0], Comp.Mag[1]);
     
@@ -54,15 +54,20 @@
     time_loop = GlobalTimer.read_us();      // set new time for next measurement
     
     // calculate angles for roll, pitch an yaw
-    angle[0] += (Acc_angle[0] - angle[0])/50 + Gyro_data[0] *dt/15000000.0;
-    angle[1] += (Acc_angle[1] - angle[1])/50 + Gyro_data[1] *dt/15000000.0;
-    tempangle += (Comp_angle - tempangle)/50 - Gyro_data[2] *dt/15000000.0;
-    angle[2] -= Gyro_data[2] *dt/15000000.0; // gyro only here
+    angle[0] += (Acc.angle[0] - angle[0])/50 + Gyro.data[0] *dt/15000000.0;
+    angle[1] += (Acc.angle[1]+3 - angle[1])/50 + Gyro.data[1] *dt/15000000.0;// TODO Offset accelerometer einstellen
+    tempangle += (Comp_angle - tempangle)/50 - Gyro.data[2] *dt/15000000.0;
+    angle[2] += Gyro.data[2] *dt/15000000.0; // gyro only here
     
     // Read RC data
-    //RC[0].read() // TODO: RC daten lesen und einberechnen!
-    
-    LEDs.rollnext();
+    controller.setProcessValue(RC[3 -1].read());
+    for (int j = 0; j < 4; j++)
+        Motorvalue[j] = controller.compute(); // throttle
+        
+    for (int j = 0; j < 4; j++)
+        Motor[j] = 1000 + 5*abs(angle[1]);//Motorvalue[j]; // set new motorspeeds
+    pid.setProcessValue(angle[0]);
+    pidtester = pid.compute();
 }
 
 
@@ -72,20 +77,33 @@
     pc.printf("Flybed v0.2");
     LEDs.roll(2);
     
+    controller.setInputLimits(1000.0, 2000.0);
+    controller.setOutputLimits(1000.0, 2000.0);
+    controller.setMode(AUTO_MODE);
+    
+    pid.setInputLimits(-90.0, 90.0);
+    pid.setOutputLimits(-90.0, 90.0);
+    pid.setMode(AUTO_MODE);
+    pid.setSetPoint(0.0);
+    
     // Start!
     GlobalTimer.start();
-    Datagetter.attach(&get_Data, 0.02);     // start to get data all 10ms
+    Datagetter.attach(&get_Data, RATE);     // start to get data all 10ms
     while(1) {
         pc.locate(10,5); // PC output
         pc.printf("dt:%dms  %6.1fm   ", dt/1000, Alt.CalcAltitude(Alt.Pressure));
         pc.locate(10,8);
         pc.printf("Roll:%6.1f Pitch:%6.1f Yaw:%6.1f    ", angle[0], angle[1], angle[2]);
+        pc.locate(10,9);
+        pc.printf("ACC: Roll:%6.1f Pitch:%6.1f Yaw:%6.1f    ", Acc.angle[0], Acc.angle[1], Acc.angle[2]);
         pc.locate(10,10);
         pc.printf("Debug_Yaw:  Comp:%6.1f tempangle:%6.1f  ", Comp_angle, tempangle);
         pc.locate(10,12);
         pc.printf("Comp_Raw: %6.1f %6.1f %6.1f   ", Comp.RawMag[0], Comp.RawMag[1], Comp.RawMag[2]);
         pc.locate(10,13);
         pc.printf("Comp_Mag: %6.1f %6.1f %6.1f   ", Comp.Mag[0], Comp.Mag[1], Comp.Mag[2]);
-        //Motor_left = 1000 + 5*abs(angle[1]);
+        pc.locate(10,15);
+        pc.printf("pidtester: %6.1f   RC: %d %d %d %d     ", pidtester, RC[0].read(), RC[1].read(), RC[2].read(), RC[3].read());
+        LEDs.rollnext();
     }
 }