Balancing Bot using MAX32630FTHR

Dependencies:   BMI160 max32630fthr mbed SDFileSystem

Revision:
3:7807a40b2459
Parent:
2:5af1d818331f
Child:
4:4144ef007743
--- a/main.cpp	Fri Jan 06 20:32:13 2017 +0000
+++ b/main.cpp	Mon Jan 09 19:08:30 2017 +0000
@@ -45,6 +45,7 @@
 #include "mbed.h"
 #include "max32630fthr.h"
 #include "bmi160.h"
+#include "SDFileSystem.h"
 
 
 //Setup interrupt in from imu
@@ -62,14 +63,52 @@
 bool start = false;
 void startStopISR()
 {
-    if(start)
-    {
-        start = false;
-    }
-    else
-    {
-        start = true;
-    }
+    start = !start;
+}
+
+
+//Setup callibrate button
+DigitalIn callibrateBtn(P5_2, PullUp);
+InterruptIn callibrate(P5_2);
+bool cal = false;
+void callibrateISR()
+{
+    cal = !cal;
+}
+
+
+//Ping sensor trigger
+DigitalOut pingTrigger(P3_2, 0);
+Ticker pingTriggerTimer;
+
+void triggerPing()
+{
+    pingTrigger = !pingTrigger;
+    wait_us(1);
+    pingTrigger = !pingTrigger;
+}
+
+DigitalIn p51(P5_1, PullNone);
+InterruptIn pingEchoRiseInt(P5_1);
+DigitalIn p45(P4_5, PullNone);
+InterruptIn pingEchoFallInt(P4_5);
+Timer pingTimer;
+
+float cm = 0;
+bool pingReady = false;
+const float US_PER_CM = 29.387;
+
+void echoStartISR()
+{
+    pingTimer.reset();
+}
+
+void echoStopISR()
+{
+    uint32_t us = pingTimer.read_us()/2;
+    
+    cm = (us/ US_PER_CM);
+    pingReady = true;
 }
 
 
@@ -105,6 +144,32 @@
     DigitalOut gLED(LED2, LED_OFF);
     DigitalOut bLED(LED3, LED_OFF);
     
+    uint32_t failures = 0;
+    
+    DigitalIn uSDdetect(P2_2, PullUp);
+    SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd");  // mosi, miso, sclk, cs
+    static const uint32_t N = 8000;
+    uint32_t samples = 0;
+    float pitchBuff[N];
+    float gyroBuff[N];
+    float accBuff[N];
+    FILE *fp;
+    //Erase old log and start a new one
+    if(!uSDdetect)
+    {   
+        fp = fopen("/sd/balBot.txt", "w");
+        if(fp != NULL)
+        {
+            fprintf(fp, "Balance Bot Data,\n");
+            fclose(fp);
+        }
+        else
+        {
+            printf("Failed to open file\n");
+            failures++;
+        }
+    }
+    
     //Setup I2C bus for IMU
     I2C i2cBus(P5_7, P6_0);
     i2cBus.frequency(400000);
@@ -112,8 +177,6 @@
     //Get IMU instance and configure it
     BMI160_I2C imu(i2cBus, BMI160_I2C::I2C_ADRS_SDO_LO);
     
-    uint32_t failures = 0;
-    
     BMI160::AccConfig accConfig;
     BMI160::AccConfig accConfigRead;
     accConfig.range = BMI160::SENS_2G;
@@ -230,8 +293,8 @@
         //PID coefficients
         static const float DT = 0.000625F;
         static const float KP = 4.25F;
-        static const float KI = (8.0F * DT);
-        static const float KD = (0.04F / DT);
+        static const float KI = (8.5F * DT);
+        static const float KD = (0.0425F / DT);
         float setPoint = 0.0F;
         
         //Control loop vars
@@ -246,12 +309,31 @@
         imu.writeRegister(BMI160::INT_OUT_CTRL, 0x0A); 
         //Map data ready interrupt to INT1
         imu.writeRegister(BMI160::INT_MAP_1, 0x80); 
+        
         //Tie INT1 to callback fx
         imuIntIn.rise(&imuISR);
         
         //Tie SW2 to callback fx
         startStop.fall(&startStopISR);
         
+        //Tie P5_2 to callback fx
+        callibrate.fall(&callibrateISR);
+        bool firstCal = true;
+        
+        //Callbacks for echo measurement
+        pingEchoRiseInt.fall(&echoStartISR);
+        pingEchoFallInt.rise(&echoStopISR);
+        
+        //Timer for echo measurements  
+        pingTimer.start();
+        
+        //Timer for trigger
+        pingTriggerTimer.attach(&triggerPing, 0.05);
+        
+        //Position control vars/constants
+        static const float PING_SP = 20.0F;
+        float pingCurrentError = 0.0F;
+        
         //control loop timming indicator
         DigitalOut loopPulse(P5_3, 0);
         
@@ -260,61 +342,54 @@
         
         while(1)
         {
-            rLED = LED_ON;
-            gLED = LED_ON;
-            pitch = 0.0F;
-            setPoint = 0.0F;
-            rightPwm.pulsewidth_us(0);
-            leftPwm.pulsewidth_us(0);
-            start = false;
-            drdy = false;
             
-            while(offsetCount < 3200)
+            if(cal || (firstCal == true))
             {
-                if(drdy)
+                cal = false;
+                firstCal = false;
+                pitch = 0.0F;
+                setPoint = 0.0F;
+                
+                rLED = LED_ON;
+                gLED = LED_ON;
+                
+                while(offsetCount < 3200)
                 {
-                    //Clear data ready flag
-                    drdy = false;
-                    
-                    //Read feedback sensors
-                    imu.getGyroAccXYZandSensorTime(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range);
-                    
-                    //Feedback Block, Complementary filter
-                    //Prediction estimate
-                    thetaGyro = (pitch + (gyroData.xAxis.scaled * DT));
-                    //Measurement estimate
-                    thetaAcc = ((180.0F/3.14F) * atan(accData.yAxis.scaled/accData.zAxis.scaled));
-                    //Feedback, Pitch estimate in degrees
-                    pitch = ((K * thetaGyro) + ((1.0F - K) * thetaAcc));
-                    
-                    //Accumalate pitch measurements
-                    setPoint += pitch;
-                    offsetCount++;
+                    if(drdy)
+                    {
+                        //Clear data ready flag
+                        drdy = false;
+                        
+                        //Read feedback sensors
+                        imu.getGyroAccXYZandSensorTime(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range);
+                        
+                        //Feedback Block, Complementary filter
+                        //Prediction estimate
+                        thetaGyro = (pitch + (gyroData.xAxis.scaled * DT));
+                        //Measurement estimate
+                        thetaAcc = ((180.0F/3.14F) * atan(accData.yAxis.scaled/accData.zAxis.scaled));
+                        //Feedback, Pitch estimate in degrees
+                        pitch = ((K * thetaGyro) + ((1.0F - K) * thetaAcc));
+                        
+                        //Accumalate pitch measurements
+                        setPoint += pitch;
+                        offsetCount++;
+                    }
                 }
+                
+                //Average measurements
+                setPoint = setPoint/3200.0F;
+                printf("setPoint = %5.2f\n\n", setPoint);
+                //Clear count for next time
+                offsetCount = 0;
             }
             
-            //Clear count for next time
-            offsetCount = 0;
-            
-            //Average measurements
-            setPoint = setPoint/3200.0F;
-            
-            printf("setPoint = %5.2f\n\n", setPoint);
-            
-            while(!start)
-            {
-                rLED = LED_ON;
-                gLED = LED_ON;
-                wait(0.25);
-                rLED = LED_OFF;
-                gLED = LED_OFF;
-                wait(0.25);
-            }
             
             while(start && (pitch > -30.0F) && (pitch < 30.0F))
             {
                 rLED = LED_OFF;
                 gLED = LED_ON;
+                
                 if(drdy)
                 {
                     //Start, following takes ~456us on MAX32630FTHR with 400KHz I2C bus
@@ -335,6 +410,14 @@
                     //Feedback, Pitch estimate in degrees
                     pitch = ((K * thetaGyro) + ((1.0F - K) * thetaAcc));
                     
+                    if(samples < N)
+                    {
+                        pitchBuff[samples] = pitch;
+                        gyroBuff[samples] = thetaGyro;
+                        accBuff[samples] = thetaAcc;
+                        samples++;
+                    }
+                    
                     //PID Block
                     //Error signal
                     currentError = (setPoint - pitch);
@@ -358,10 +441,22 @@
                     //Derivative term, dt is included in KD
                     derivative = (currentError - previousError);
                     
+                    
                     //Set right/left pulsewidth
                     //Just balance for now, so both left/right are the same
                     pulseWidth = ((KP * currentError) + (KI * integral) + (KD * derivative));
                     
+                    
+                    if(pingReady)
+                    {
+                        //Get error signal
+                        pingReady = false;
+                        pingCurrentError = PING_SP - cm;
+                    }
+                    
+                    //pulseWidth += pingCurrentError * -1.0F;
+                    
+                    
                     //Clamp to maximum duty cycle and check for forward/reverse 
                     //based on sign of error signal (negation of pitch since setPoint = 0)
                     if(pulseWidth > MAX_PULSEWIDTH_US)
@@ -404,6 +499,49 @@
                     loopPulse = !loopPulse;
                 }
             }
+            
+            rightPwm.pulsewidth_us(0);
+            leftPwm.pulsewidth_us(0);
+            
+            rLED = LED_ON;
+            gLED = LED_ON;
+            wait(0.25);
+            rLED = LED_OFF;
+            gLED = LED_OFF;
+            wait(0.25);
+            
+            if(!uSDdetect && (samples > 0))
+            {   
+                samples = 0;
+                fp = fopen("/sd/balBot.txt", "a");
+                if(fp != NULL)
+                {
+                    bLED = LED_ON;
+                    fprintf(fp, "KI and KD have DT rolled into them; ie * or / respectively.\n");
+                    fprintf(fp, "Setpoint,%5.2f,\n", setPoint);
+                    fprintf(fp, "K, %f,\n", K);
+                    fprintf(fp, "KP, %f,\n", KP);
+                    fprintf(fp, "KI, %f,\n", KI);
+                    fprintf(fp, "KD, %f,\n", KD);
+                    fprintf(fp, "DT, %f,\n", DT);
+                    fprintf(fp, "Time, Pitch, Gyro, Acc,\n");
+                    for(uint32_t idx = 0; idx < N; idx++) 
+                    {
+                        fprintf(fp, "%f,", idx*DT);
+                        fprintf(fp, "%5.2f,", pitchBuff[idx]);
+                        fprintf(fp, "%5.2f,", gyroBuff[idx]);
+                        fprintf(fp, "%5.2f,", accBuff[idx]);
+                        fprintf(fp, "\n");
+                    }
+                    fprintf(fp, "\n");
+                    fclose(fp);
+                    bLED = LED_OFF;
+                }
+                else
+                {
+                    printf("Failed to open file\n");
+                }
+            }   
         }
     }
     else