car using PID from centre line

Dependencies:   FRDM-TFC mbed CBuffer XBEE mbed_angular_speed motor2 MMA8451Q

Fork of KL25Z_Camera_Test by GDP 4

Revision:
8:7c5e6b1e7aa5
Parent:
7:ad893fc41b95
Child:
9:aa2ce38dec6b
diff -r ad893fc41b95 -r 7c5e6b1e7aa5 main.cpp
--- a/main.cpp	Mon Nov 14 11:11:13 2016 +0000
+++ b/main.cpp	Mon Nov 14 13:42:22 2016 +0000
@@ -1,20 +1,51 @@
+//Autonomous Car GDP controller
+//Written by various group members
+//Commented & cleaned up by Max/Adam
+
+//To-do
+// -Change xbee transmission to non-blocking
+// -Improve start/stop detection and resultant action (setting PID values?)
+
+#include <stdarg.h>
+#include <stdio.h>
+
 #include "mbed.h"
 #include "TFC.h"
 #include "XBEE.h"
+
+#define BAUD_RATE 57600
 #define CAM_THRESHOLD 109
- 
- 
-DigitalOut myled(LED1);
+#define CAM_DIFF 10
+
 //Serial pc(USBTX,USBRX);
 Serial pc(PTD3,PTD2);
 XBEE xb(&pc);
 
+//Woo global variables!
+bool onTrack;
 char curr_line[128];
 uint8_t curr_left;
 uint8_t curr_right;
-
 uint8_t right;
 uint8_t left;
+int8_t leftChange;
+int8_t rightChange;
+int diff;
+int prev;
+int i = 0;
+float measuredValBuffer[5];
+uint8_t valBufferIndex;
+
+//Some PID variables
+float Kp;
+float Ki;
+float Kd;
+float dt;
+float p_error;
+float pid_error;
+float integral;
+float measured_value, desired_value, derivative;
+float output;
 
 Timer t;
 
@@ -22,43 +53,112 @@
 
 float speed = 0.3;
 int frame_counter = 0;
- 
- int startstop = 0;
+
+//Hacky start/stop signal detection
+int startstop = 0;
 bool seen = false;
- 
+
+void sendString(const char *format, ...);
+void initVariables();
+inline void handleComms();
+inline float findCentreValue();
+inline void PIDController();
+inline void sendImage();
+
 int main() {
+    //Set up TFC driver stuff
     TFC_Init();
     TFC_InitServos(0.00052,0.00122,0.02);
+    //Old things to make the car move at run-time
+    //Should tie these to a button for the actual races
     //TFC_HBRIDGE_ENABLE;
     //TFC_SetMotorPWM(0.3,0.3);
     
-    
-    pc.baud(57600);
+    //Setup baud rate for serial link, do not change!
+    pc.baud(BAUD_RATE);
     
-    float p_error, error;
-    float integral;
-    float measured_value, desired_value,derivative;
-    float output;
-      //tunable variables
-    float Kp, Ki,Kd;
-        Kp=125/25.0f;
-    Ki=12.0f/25.0f;
-    Kd=0.0;
-    myled = 0;// Test
-        float dt=0;
-    p_error=0;
-    error=0;
-    integral=0;
-    measured_value= 0;
-    desired_value=0;
-    derivative=0;
-        // measured value is a float between -1.0 and 1.0
-    // desired value is always 0 ( as in car is in the middle of the road)
+    //Initialise/reset PID variables
+    initVariables();
     
-    uint8_t i = 0;
     while(1) {
         
-        if(curr_cmd != 0) {
+        handleComms();
+        
+        //If we have an image ready
+        if(TFC_LineScanImageReady>0) {       
+            measured_value = findCentreValue();
+            
+            PIDController();
+            
+            sendImage();
+            
+            //Hacky way to detect the start/stop signal
+            if(right - left < 60) {
+                pc.putc('E');
+                pc.printf("START STOP!! &d",startstop);
+                pc.putc(0);            
+                
+                if(seen) {
+                    seen = false;
+                } else {
+                    startstop++;
+                    seen = true;    
+                }    
+                //If we've done 5 laps, stop the car
+                if(startstop >= 1) {
+                    TFC_SetMotorPWM(0.0,0.0);
+                    TFC_HBRIDGE_DISABLE;
+                    startstop = 0;      
+                }
+            }
+            
+            //Reset image ready flag
+            TFC_LineScanImageReady=0;
+        }
+    }
+}
+
+void sendString(const char *format, ...) {
+    va_list arg;
+
+    pc.putc('E');
+    va_start (arg, format); 
+    pc.vprintf(format,arg);
+    va_end (arg);
+    pc.putc(0);
+}
+
+void initVariables() {
+    //Tunable PID variables
+    Kp = 125   / 25.0f;
+    Ki = 12.0f / 25.0f;
+    Kd = 0.0f;
+    dt = 0;
+    p_error = 0;
+    pid_error = 0;
+    integral = 0;
+    measured_value = 0;
+    desired_value = 0;
+    derivative = 0;
+    
+    valBufferIndex = 0;
+    //Measured value is a float between -1.0 and 1.0 (from left to right)
+    //Desired value is always 0.0 (as in, car is in the middle of the road)
+}
+
+inline void sendImage() {
+     //Only send 1/3 of camera frames to GUI program
+    if((frame_counter % 3) == 0) {
+        pc.putc('H');
+        for(i = 0; i < 128; i++) {
+            pc.putc((int8_t)(TFC_LineScanImage0[i] >> 4) & 0xFF);    
+        }
+    }
+    frame_counter++;
+}
+
+inline void handleComms() {
+    if(curr_cmd != 0) {
             switch(curr_cmd) {
                 case 'A':
                     if(xb.cBuffer->available() >= 3) {
@@ -69,8 +169,9 @@
                         Ki = i/25.0f;
                         Kd = d/25.0f;
                         pc.putc('E');
-                        pc.printf("pid change");
+                        pc.printf("pid change, Kp: %f, Ki: %f, Kd: %f, p: %u, i: %u, d: %u", Kp, Ki, Kd, p, i, d);
                         pc.putc(0);
+                        
                         curr_cmd = 0;        
                     }    
                 break;
@@ -111,135 +212,85 @@
             }
             
         }
-        
-        //If we have an image ready
-        if(TFC_LineScanImageReady>0) {       
-            //left = 0;
-            //right = 0;
-            int diff = 0;
-            int prev = -1;
-            for(i = 63; i > 0; i--) {
-                curr_left = (int8_t)(TFC_LineScanImage0[i] >> 4) & 0xFF;
-               /* if(curr_left < CAM_THRESHOLD) {
-                    left = i;
-                    break;
-                }
-                */
-                
-                diff = prev - curr_left;
-                if(abs(diff) >= 10 && curr_left <= 100 && prev != -1) {
-                    left = i;
-                    break;    
-                }
-                
-                prev = curr_left;
-            }
-            
-            prev = -1;
-            for(i = 64; i < 128; i++) {
-                curr_right = (int8_t)(TFC_LineScanImage0[i] >> 4) & 0xFF;
-                /*
-                if(curr_right < CAM_THRESHOLD) {
-                    right = i;
-                    break;
-                }
-                */
-                
-                int diff = prev - curr_right;
-                if(abs(diff) >= 10 && curr_right <= 100 && prev != -1) {
-                    right = i;
-                    break;    
-                }
-                
-                prev = curr_right;
-            }
+}
+inline float findCentreValue() {
+    float measuredValue;
+   
+    diff = 0;
+    prev = -1;
+    leftChange = left;
+    for(i = 63; i > 0; i--) {
+        curr_left = (int8_t)(TFC_LineScanImage0[i] >> 4) & 0xFF;              
+        diff = prev - curr_left;
+        if(abs(diff) >= 10 && curr_left <= 100 && prev != -1) {
+            left = i;
+            break;
+        }
+        prev = curr_left;
+    }
+    
+    prev = -1;
+    rightChange = right;
+    for(i = 64; i < 128; i++) {
+        curr_right = (int8_t)(TFC_LineScanImage0[i] >> 4) & 0xFF;
+        int diff = prev - curr_right;
+        if(abs(diff) >= 10 && curr_right <= 100 && prev != -1) {
+            right = i;
+            break;
+        }
+        prev = curr_right;
+    }
+    
+    //Calculate how left/right we are
+    measuredValue = (64 - ((left+right)/2))/64.f;
+    measuredValBuffer[valBufferIndex % 5] = measuredValue;
+    valBufferIndex++;
+    
+    return measuredValue;
+}
 
-            if((frame_counter % 3) == 0) {
-            pc.putc('H');
-            for(i = 0; i < 128; i++) {
-                pc.putc((int8_t)(TFC_LineScanImage0[i] >> 4) & 0xFF);    
-            }
-            }
-            frame_counter++;
-            
-            measured_value = (64 - ((left+right)/2))/64.f;
-            
-            if(right - left < 60) {
-                pc.putc('E');
-                pc.printf("START STOP!! &d",startstop);
-                pc.putc(0);            
-                
-                if(seen) {
-                    seen = false;
-                } else {
-                    startstop++;
-                    seen = true;    
-                }    
-            
-            if(startstop >= 5) {
-                TFC_SetMotorPWM(0.0,0.0);
-                TFC_HBRIDGE_DISABLE;
-                startstop = 0;      
-            }
-            
-            } 
-            
+inline void PIDController() {
+    //PID Stuff!
     t.start();
-    dt=t.read();
-    error = desired_value - measured_value;
-   integral=integral+error*dt;
-   derivative=(error-p_error)/dt;
-   output=Kp*error+Ki*integral+Kd*derivative;
-   p_error=error;
-   
-   
-   if(integral > 1.0f) {
+    dt = t.read();
+    pid_error = desired_value - measured_value;
+    integral = integral + pid_error * dt;
+    derivative = (pid_error - p_error) / dt;
+    output = Kp * pid_error + Ki * integral + Kd * derivative;
+    p_error = pid_error;
+    
+    if(integral > 1.0f) {
         integral = 1.0f;   
     }
     if(integral < -1.0f) {
         integral = -1.0f;   
     }
-   
     
-   if((-1.0<=output)&&(output<=1.0))
-   {
-      TFC_SetServo(0,output);
- 
-    }
-    else
+    if((-1.0 <= output) && (output <= 1.0))
     {
-          
-            pc.putc('E');
-    pc.printf("pid unhappy\0");
-    pc.putc('E');
-    pc.printf("out = %f p_err = %f\0",output, p_error);
-    TFC_InitServos(0.00052,0.00122,0.02);
-    //output, error, p_error, integral, derivative = 0;
+        TFC_SetServo(0, output);
+    }
+    else //Unhappy PID state
+    {        
+        pc.putc('E');
+        pc.printf("pid unhappy");
+        pc.putc(0);
+        pc.putc('E');
+        pc.printf("out = %f p_err = %f", output, p_error);
+        pc.putc(0);
+        TFC_InitServos(0.00052, 0.00122, 0.02);
+        //output, pid_error, p_error, integral, derivative = 0;
+        
+        if(output >= 1.0f) {
+            TFC_SetServo(0, 0.9f);
+            output = 1.0f;
+        } else {
+            TFC_SetServo(0, -0.9f);
+            output = -1.0f;
+        }
+    }
     
-    if(output >= 1.0f) {
-        TFC_SetServo(0,0.9f);
-        output = 1.0f;
-    } else {
-        TFC_SetServo(0,-0.9f);
-        output = -1.0f;
-    } 
-    
-    
-  
-    
-    
-   }
-       
     t.stop();
     t.reset();
     t.start();
- 
-            
-        
-
-            //Reset image ready flag
-            TFC_LineScanImageReady=0;
-            wait(0.02f);
-        }
-    }
 }
\ No newline at end of file