Script for a drone PID tuning interface using buttons, potentiometers and a 3-D printed platform.

Dependencies:   mbed HMC5883L

Fork of Robosub_test by Rogelio Vazquez

Files at this revision

API Documentation at this revision

Comitter:
roger_wee
Date:
Mon Feb 12 07:27:47 2018 +0000
Parent:
3:394c971eab83
Commit message:
Script for a Drone PID tuning plaform

Changed in this revision

HMC5883L.lib Show diff for this revision Revisions of this file
MARGfilter.lib Show diff for this revision Revisions of this file
Sensors/HMC5883L.lib Show annotated file Show diff for this revision Revisions of this file
Sensors/IMU.h Show annotated file Show diff for this revision Revisions of this file
Sensors/MPU6050.h Show annotated file Show diff for this revision Revisions of this file
Sensors/MS5837.cpp Show diff for this revision Revisions of this file
Sensors/MS5837.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/HMC5883L.lib	Sun Jun 04 06:58:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-https://developer.mbed.org/users/roger_wee/code/HMC5883L/#f5f6aaf24be0
--- a/MARGfilter.lib	Sun Jun 04 06:58:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-https://mbed.org/users/elromulous/code/MARGfilter/#6259fdd04e83
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sensors/HMC5883L.lib	Mon Feb 12 07:27:47 2018 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/users/roger_wee/code/HMC5883L/#f5f6aaf24be0
--- a/Sensors/IMU.h	Sun Jun 04 06:58:45 2017 +0000
+++ b/Sensors/IMU.h	Mon Feb 12 07:27:47 2018 +0000
@@ -77,9 +77,9 @@
         mpu6050.getAres();
  
         // Now we'll calculate the accleration value into actual g's
-        ax = (float)accelCount[0]*aRes - accelBias[0];  // get actual g value, this depends on scale being set
-        ay = (float)accelCount[1]*aRes - accelBias[1];
-        az = (float)accelCount[2]*aRes - accelBias[2];
+        ax = (float)accelCount[0] *aRes - accelBias[0];  // get actual g value, this depends on scale being set
+        ay = (float)accelCount[1] *aRes - accelBias[1];
+        az = (float)accelCount[2] *aRes - accelBias[2];
  
         mpu6050.readGyroData(gyroCount);  // Read the x/y/z adc values
         mpu6050.getGres();
@@ -100,7 +100,7 @@
         
     Now = t.read_us();
     deltat = (float)((Now - lastUpdate)/1000000.0f) ; // set integration time by time elapsed since last filter update
-    sampleFreq = 1/deltat;
+    //sampleFreq = 1/deltat;
     lastUpdate = Now;
  
     sum += deltat;
@@ -111,11 +111,13 @@
         zeta = 0.015; // increasey bias drift gain after stabilized
     }
     
-    //Convert gyro rate as rad/s
+    // Convert gyro rate as rad/s
     gx *= PI/180.0f;
     gy *= PI/180.0f;
     gz *= PI/180.0f;
     
+    // Calculate position if time
+    mpu6050.getDisplacement(ax,ay);
 
     // Pass gyro rate as rad/s
     mpu6050.MadgwickQuaternionUpdate(ax, ay, az, gx, gy, gz, magdata[0], magdata[1], magdata[2]);
@@ -124,20 +126,6 @@
     delt_t = t.read_ms() - count;
     if (delt_t > 0) { // update LCD once per half-second independent of read rate
  
-     //   pc.printf("ax = %f", 1000*ax);
-     //   pc.printf(" ay = %f", 1000*ay);
-     //   pc.printf(" az = %f  mg\n\r", 1000*az);
- 
-     //   pc.printf("gx = %f", gx);
-     //   pc.printf(" gy = %f", gy);
-     //   pc.printf(" gz = %f  deg/s\n\r", gz);
- 
-     //   pc.printf(" temperature = %f  C\n\r", temperature);
- 
-     //   pc.printf("q0 = %f\n\r", q[0]);
-     //   pc.printf("q1 = %f\n\r", q[1]);
-     //   pc.printf("q2 = %f\n\r", q[2]);
-     //   pc.printf("q3 = %f\n\r", q[3]);
         
         // Define output variables from updated quaternion---these are Tait-Bryan angles, commonly used in aircraft orientation.
         // In this coordinate system, the positive z-axis is down toward Earth.
--- a/Sensors/MPU6050.h	Sun Jun 04 06:58:45 2017 +0000
+++ b/Sensors/MPU6050.h	Mon Feb 12 07:27:47 2018 +0000
@@ -167,6 +167,12 @@
 float temperature;
 float SelfTest[6];
 
+signed int accelerationx[2], accelerationy[2];
+signed long velocityx[2], velocityy[2];
+signed long positionX[2];
+signed long positionY[2];
+signed long positionZ[2]; 
+unsigned char countx, county;
 
 float heading = 0;
 float magdata[3];
@@ -174,11 +180,11 @@
 int delt_t = 0; // used to control display output rate
 int count = 0;  // used to control display output rate
  
-// parameters for 6 DoF sensor fusion calculations
+// parameters for 9 DoF sensor fusion calculations
 float PI = 3.14159265358979323846f;
-float GyroMeasError = PI * (40.0f / 180.0f);     // gyroscope measurement error in rads/s (start at 60 deg/s), then reduce after ~10 s to 3
+float GyroMeasError = PI * (90.0f / 180.0f);     // gyroscope measurement error in rads/s (start at 60 deg/s), then reduce after ~10 s to 3
 float beta = sqrt(3.0f / 4.0f) * GyroMeasError;  // compute beta
-float GyroMeasDrift = PI * (1.0f / 180.0f);      // gyroscope measurement drift in rad/s/s (start at 0.0 deg/s/s)
+float GyroMeasDrift = PI * (3.0f / 180.0f);      // gyroscope measurement drift in rad/s/s (start at 0.0 deg/s/s)
 float zeta = sqrt(3.0f / 4.0f) * GyroMeasDrift;  // compute zeta, the other free parameter in the Madgwick scheme usually set to a small or zero value
 float yaw, pitch, roll;
 float deltat = 0.0f;                              // integration interval for both filter schemes
@@ -797,7 +803,89 @@
             q[3] = q4 * norm;
 
         }
-    
+        
+        void getDisplacement(float ax, float ay)
+        {
+            unsigned char count2 ;
+            count2=0;
+
+            do{
+                accelerationx[1] = accelerationx[1] + ax; //filtering routine for noise attenuation
+                accelerationy[1] = accelerationy[1] + ay; //64 samples are averaged. The resulting 
+
+                //average represents the acceleration of
+                //an instant
+                count2++;
+            }while (count2!=0x40); // 64 sums of the acceleration sample
+
+            accelerationx[1]= accelerationx[1]>>6; // division by 64
+            accelerationy[1]= accelerationy[1]>>6;
+
+            //accelerationx[1] = accelerationx[1] - (int)sstatex; //eliminating zero reference
+            //offset of the acceleration data
+            //accelerationy[1] = accelerationy[1] - (int)sstatey; // to obtain positive and negative
+            //acceleration
+
+
+            if ((accelerationx[1] <=3)&&(accelerationx[1] >= -3)) //Discrimination window applied
+            {accelerationx[1] = 0;} // to the X axis acceleration variable
+
+            if ((accelerationy[1] <=3)&&(accelerationy[1] >= -3))
+            {accelerationy[1] = 0;}
+
+            //first X integration:
+            velocityx[1]= velocityx[0]+ accelerationx[0]+ ((accelerationx[1] - accelerationx[0])>>1);
+            //second X integration:
+            positionX[1]= positionX[0] + velocityx[0] + ((velocityx[1] - velocityx[0])>>1);
+            //first Y integration:
+            velocityy[1] = velocityy[0] + accelerationy[0] + ((accelerationy[1] -accelerationy[0])>>1);
+            //second Y integration:
+            positionY[1] = positionY[0] + velocityy[0] + ((velocityy[1] - velocityy[0])>>1);
+
+            accelerationx[0] = accelerationx[1]; //The current acceleration value must be sent
+            //to the previous acceleration
+            accelerationy[0] = accelerationy[1]; //variable in order to introduce the new
+            //acceleration value.
+
+            velocityx[0] = velocityx[1]; //Same done for the velocity variable
+            velocityy[0] = velocityy[1];
+
+            positionX[1] = positionX[1]<<18; //The idea behind this shifting (multiplication)
+            //is a sensibility adjustment.
+            positionY[1] = positionY[1]<<18; //Some applications require adjustments to a
+            //particular situation i.e. mouse application
+
+            positionX[1] = positionX[1]>>18; //once the variables are sent them must return to
+            positionY[1] = positionY[1]>>18; //their original state
+ 
+            movement_end_check();
+
+            positionX[0] = positionX[1]; //actual position data must be sent to the
+            positionY[0] = positionY[1]; //previous position
+        }
+        
+        void movement_end_check(void)
+        {
+            if (accelerationx[1]==0) //we count the number of acceleration samples that equals cero
+            { countx++;}
+            else { countx =0;}
+
+            if (countx>=25) //if this number exceeds 25, we can assume that velocity is cero
+            {
+                velocityx[1]=0;
+                velocityx[0]=0;
+            }
+
+            if (accelerationy[1]==0) //we do the same for the Y axis
+            { county++;}
+            else { county =0;}
+
+            if (county>=25)
+            {
+                velocityy[1]=0;
+                velocityy[0]=0;
+            }
+        }
  
 };
 #endif
\ No newline at end of file
--- a/Sensors/MS5837.cpp	Sun Jun 04 06:58:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-#include <stdlib.h>
-#include "MS5837.h"
- //Pressure Sensor
- 
-/*
- * Sensor operating function according data sheet
- */
- 
-void MS5837::MS5837Init(void)
-{
-    MS5837Reset();
-    MS5837ReadProm();
-    return;
-}
- 
-/* Send soft reset to the sensor */
-void MS5837::MS5837Reset(void)
-{
-    /* transmit out 1 byte reset command */
-    ms5837_tx_data[0] = ms5837_reset;
-    if ( i2c.write( device_address,  ms5837_tx_data, 1 ) );
-    //printf("send soft reset");
-    wait_ms(20);
-}
- 
-/* read the sensor calibration data from rom */
-void MS5837::MS5837ReadProm(void)
-{
-    uint8_t i,j;
-    for (i=0; i<8; i++) {
-        j = i;
-        ms5837_tx_data[0] = ms5837_PROMread + (j<<1);
-        if ( i2c.write( device_address,  ms5837_tx_data, 1 ) );
-        if ( i2c.read( device_address,  ms5837_rx_data, 2 ) );
-        C[i]   = ms5837_rx_data[1] + (ms5837_rx_data[0]<<8);
-    }
-}
- 
-/* Start the sensor pressure conversion */
-void MS5837::MS5837ConvertD1(void)
-{
-    ms5837_tx_data[0] = ms5837_convD1;
-    if ( i2c.write( device_address,  ms5837_tx_data, 1 ) );
-}
- 
-/* Start the sensor temperature conversion */
-void MS5837:: MS5837ConvertD2(void)
-{
-    ms5837_tx_data[0] = ms5837_convD2;
-    if ( i2c.write( device_address,  ms5837_tx_data, 1 ) );
-}
- 
-/* Read the previous started conversion results */
-int32_t MS5837::MS5837ReadADC(void)
-{
-    int32_t adc;
-    wait_ms(150);
-    ms5837_tx_data[0] = ms5837_ADCread;
-    if ( i2c.write( device_address,  ms5837_tx_data, 1 ) );
-    if ( i2c.read( device_address,  ms5837_rx_data, 3 ) );
-    adc = ms5837_rx_data[2] + (ms5837_rx_data[1]<<8) + (ms5837_rx_data[0]<<16);
-    return (adc);
-}
- 
-/* return the results */
-float MS5837::MS5837_Pressure (void)
-{
-    return P_MS5837;
-}
-float MS5837::MS5837_Temperature (void)
-{
-    return T_MS5837;
-}
- 
-/* Sensor reading and calculation procedure */
-void MS5837::Barometer_MS5837(void)
-{
-    int32_t dT, temp;
-    int64_t OFF, SENS, press;
- 
-    //no need to do this everytime!
-    //MS5837Reset();                 // reset the sensor
-    //MS5837ReadProm();             // read the calibration values
-    
-    
-    MS5837ConvertD1();             // start pressure conversion
-    D1 = MS5837ReadADC();        // read the pressure value
-    MS5837ConvertD2();             // start temperature conversion
-    D2 = MS5837ReadADC();         // read the temperature value
- 
-    /* calculation according MS5837-01BA data sheet DA5837-01BA_006 */
-    dT       = D2 - (C[5]* 256);
-    OFF      = (int64_t)C[2] * (1<<16) + ((int64_t)dT * (int64_t)C[4]) / (1<<7);
-    SENS     = (int64_t)C[1] * (1<<15) + ((int64_t)dT * (int64_t)C[3]) / (1<<8);
- 
-    temp     = 2000 + (dT * C[6]) / (1<<23);
-    T_MS5837 = (float) temp / 100.0f;                 // result of temperature in deg C in this var
-    press    = (((int64_t)D1 * SENS) / (1<<21) - OFF) / (1<<13);
-    P_MS5837 = (float) press / 10.0f;                 // result of pressure in mBar in this var
-}
\ No newline at end of file
--- a/Sensors/MS5837.h	Sun Jun 04 06:58:45 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-#include "mbed.h"
- 
-#ifndef MS5837_H
-#define MS5837_H
- 
-#define MS5837_RX_DEPTH 3 //
-#define MS5837_TX_DEPTH 2 //
- 
-// choose your connection here
-#define ms5837_addr_no_CS  0x76 //0b1110110
- 
-#define ms5837_reset       0x1E // Sensor Reset
- 
-#define ms5837_convD1_256  0x40 // Convert D1 OSR 256
-#define ms5837_convD1_512  0x42 // Convert D1 OSR 512
-#define ms5837_convD1_1024 0x44 // Convert D1 OSR 1024
-#define ms5837_convD1_2048 0x46 // Convert D1 OSR 2048
-#define ms5837_convD1_4096 0x48 // Convert D1 OSR 4096
-#define ms5837_convD1_8192 0x4A // Convert D1 OSR 8192
- 
-#define ms5837_convD1 ms5837_convD1_4096 // choose your sampling rate here
- 
-#define ms5837_convD2_256  0x50 // Convert D2 OSR  256
-#define ms5837_convD2_512  0x52 // Convert D2 OSR  512
-#define ms5837_convD2_1024 0x54 // Convert D2 OSR 1024
-#define ms5837_convD2_2048 0x56 // Convert D2 OSR 2048
-#define ms5837_convD2_4096 0x58 // Convert D2 OSR 4096
-#define ms5837_convD2_8192 0x5A // Convert D2 OSR 8192
- 
-#define ms5837_convD2 ms5837_convD2_4096 // choose your sampling rate here
- 
-#define ms5837_ADCread     0x00 // read ADC command
-#define ms5837_PROMread    0xA0 // read PROM command base address
- 
-class MS5837{
-private:
-    int D1, D2, Temp, C[8];
-    float T_MS5837, P_MS5837;
-    /* Data buffers */
-    char ms5837_rx_data[MS5837_RX_DEPTH];
-    char ms5837_tx_data[MS5837_TX_DEPTH];
- 
-public:
-    MS5837 (PinName sda, PinName scl,
-            char ms5837_addr = ms5837_addr_no_CS  )
-            : i2c( sda, scl ), device_address( ms5837_addr << 1 ) {
-    }
-    void MS5837Init(void);
-    void MS5837Reset(void);
-    void MS5837ReadProm(void);
-    void MS5837ConvertD1(void);
-    void MS5837ConvertD2(void);
-    int32_t MS5837ReadADC(void);
-    float MS5837_Pressure (void);
-    float MS5837_Temperature (void);
-    void Barometer_MS5837(void);
- 
- 
-private:
-    I2C     i2c;
-    char    device_address;
- 
-};
-#endif
\ No newline at end of file
--- a/main.cpp	Sun Jun 04 06:58:45 2017 +0000
+++ b/main.cpp	Mon Feb 12 07:27:47 2018 +0000
@@ -1,6 +1,5 @@
 #include "IMU.h"
 #include "PID.h"
-#include "MS5837.h"
 #include "Motor.h"
 #include "HMC5883L.h"
 
@@ -11,69 +10,124 @@
   return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
 }
 
-double myPitch, sOut, setPoint;
-double k_p, k_i, k_d;
+
+DigitalOut  my_led(LED1);
 
-//Declare digital button input
-DigitalIn tuningButton(USER_BUTTON);
+// Individual pid parameters
+double myYaw, yawPoint, yawOut;
+double myPitch, pitchPoint, pitchOut;
+double myRoll, rollPoint, rollOut;
+double myDepth, depthPoint, depthOut;
 
+//Declare digital button input                  tuning parameters   //FIXME
+DigitalIn tuningButton(USER_BUTTON);            
 
-// Declare mpu object
+// Declare mpu6050 and compass object
 MPU6050 mpu1;
 HMC5883L compass;
 
-MS5837 pressure_sensor = MS5837(D14, D15, ms5837_addr_no_CS);
+// Declare analog input pin ( kp, ki, kd )      tuning parameters
+AnalogIn    tuneKnob(A0);
 
-// Declare motor objects
-Motor mBlack(D3,D2,D9); // pwm, fwd, rev
-Motor mWhite(D4,D5,D8);
+// Declare motor pins
+PwmOut      m1(D3);
+PwmOut      m2(D4);
+PwmOut      m3(D5);
+PwmOut      m4(D6);
 
-// Declare analog input pin 
-AnalogIn    kpKnob(A0);
-AnalogIn    kiKnob(A1);
-AnalogIn    kdKnob(A2);
+// PWM output variable for each motor
+int m1pwm, m2pwm, m3pwm, m4pwm;
 
 // Input, Output, SetPoint, kp, ki, kd, Controller Direction
-PID pidp(&myPitch, &sOut, &setPoint, 1, 1, 1, DIRECT);
+PID pidy(&myYaw, &yawOut, &yawPoint, 1, 1, 1, DIRECT);
+PID pidp(&myPitch, &pitchOut, &pitchPoint, 1, 1, 1, DIRECT);
+PID pidr(&myRoll, &rollOut, &rollPoint, 1, 1, 1, DIRECT);
+PID pidd(&myDepth, &depthOut, &depthPoint, 1, 1, 1, DIRECT);
 
 //Serial pc(USBTX, USBRX);
 
+// Serial communication between Arduino NANO
+RawSerial device(PA_11, PA_12);  //TX RX
+
+Timer calibrate;
+
+int depth = 1;
+
 int main()
 {   
     // Initialize IMU
     IMUinit(mpu1);
+    
+    // Initialize Magnetometer
     compass.init();
-    // Initialize pressure sensor
- //   pressure_sensor.MS5837Init();
+    
+    // Initialize PID's 
+    pidy.SetMode(AUTOMATIC);            // Yaw PID
+    pidy.SetOutputLimits(1500, 1700);
     
-    // Initialize PID 
-    pidp.SetMode(AUTOMATIC);    
-    pidp.SetOutputLimits(0.5, 1);
+    pidp.SetMode(AUTOMATIC);            // Pitch PID
+    pidp.SetOutputLimits(1500, 1700); 
+    
+    pidr.SetMode(AUTOMATIC);            // Roll PID
+    pidr.SetOutputLimits(1500, 1700);
     
-    //Default kp ki kd parameters
+    pidd.SetMode(AUTOMATIC);            // Depth PID
+    pidd.SetOutputLimits(1500, 1700); 
+
+    
+    // Default kp ki kd parameters
     float kpKnobVal = .028;
     float kiKnobVal = .01;
     float kdKnobVal = .025;
-    pidp.SetTunings(kpKnobVal, kiKnobVal, kdKnobVal);
-    setPoint = 0;
+    
+    // Configure PID's
+    pidd.SetTunings(kpKnobVal, kiKnobVal, kdKnobVal);
+    depthPoint = 0;
     
-   // float pressure;
+    //Calibrate IMU
+    calibrate.start();
+    while(calibrate.read() < 5);
+    {
+        IMUPrintData(mpu1, compass);
+        my_led = 1;
+    }
+    my_led = 0;
+    
+    calibrate.stop();
 
     while(1)
     {    
+        //-------------------------SENSE--------------------------------
     
-        // Read pressure sensor data
-       // pressure_sensor.Barometer_MS5837();
-       // pressure = pressure_sensor.MS5837_Temperature();
-       // pc.printf("pressure: %f \n", pressure);
+        // Read pressure sensor data if available
+        if (device.readable())
+        {
+            // Receive depth in inches as an integer
+            depth = device.getc();
+            
+            // Convert to feet
+            
+            // Display received data
+           // pc.printf("%d \n", pressure);
+        }
+        
+        // Obtain mpu data -> pass through filter -> obtain yaw pitch roll
+        IMUPrintData(mpu1, compass);
+        
+        // Assign feedback variables
+        myDepth = depth;
+        
+        //------------------------End SENSE----------------------------
+        
+        
+        //------------------------Tuning ADJUST-------------------------    FIXMEEEEEE
         
         // If button is pressed kp ki kd values can be adjusted
         if(!tuningButton)
         {
             // Read raw potentiometer values from k-knob and map to kpknobVal
-            kpKnobVal = map(kpKnob.read(), 0.000, 1.000, 0.000, .050);
-            kiKnobVal = map(kiKnob.read(), 0.000, 1.000, 0.000, 0.008);
-            kdKnobVal = map(kdKnob.read(), 0.000, 1.000, 0.000, .040);
+            kpKnobVal = map(tuneKnob.read(), 0.000, 1.000, 0.000, .050);
+           
             
             // Adjust tunings
             pidp.SetTunings(kpKnobVal,kiKnobVal,kdKnobVal);
@@ -82,28 +136,35 @@
         //print mapped joystick values
        // pc.printf("kp: %f -- ki: %f -- kd %f \n", kpKnobVal, kiKnobVal, kdKnobVal);  
         
-        // Obtain mpu data -> pass through filter -> obtain yaw pitch roll
-        IMUPrintData(mpu1, compass);
-        //myPitch = pitch;
+        //------------------------End tuning ADJUST-----------------------
         
-       // char textA[90];
-       // sprintf(textA, "%f,%f,%f,%f \n", heading, magdata[0], magdata[1], heading);
-       // pc.printf("%s", textA);
+        
+        //------------------------Motor Control LOOP----------------------
         
         // Compute output using pid controller
-        //pidp.Compute();
+        pidd.Compute();
+        
+        // Assign pid output pwm to individual pwm variables
+        m1pwm = depthOut;
+        m2pwm = depthOut;
+        m3pwm = depthOut;
+        m4pwm = depthOut;
         
-        // Send pwm output to Motors
-        //float s2Out = 1.5 - sOut;
-        //mWhite.speed(s2Out); 
-        //mBlack.speed(-sOut);
-                
-        //Display telemetry
+        // Output pwm
+        m1.pulsewidth_us(m1pwm);
+        m2.pulsewidth_us(m2pwm);
+        m3.pulsewidth_us(m3pwm);
+        m4.pulsewidth_us(m4pwm);
+        
+        //------------------------End Motor Control LOOP-------------------    
+        
+        
+        //------------------------Display TELEMETRY------------------------
         char text[90];
-        sprintf(text, "%f,%f,%f \n", yaw, pitch, roll);
+        sprintf(text, "%f,%f,%f,%d \n", yaw, pitch, roll, depth);
         pc.printf("%s", text);
+        //--------------------------End TELEMETRY--------------------------
         
-        wait(.01);
     }
 }