New stuff

Fork of ES_CW2_Starter by Edward Stott

Files at this revision

API Documentation at this revision

Comitter:
Bachoru
Date:
Fri Mar 24 00:48:47 2017 +0000
Parent:
2:4e88faab6988
Commit message:
New stuff

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 4e88faab6988 -r 620fbdd7b6c6 main.cpp
--- a/main.cpp	Tue Feb 28 14:44:23 2017 +0000
+++ b/main.cpp	Fri Mar 24 00:48:47 2017 +0000
@@ -1,15 +1,37 @@
 #include "mbed.h"
-#include "rtos.h"
+
+/////////////////////
+// Pin definitions //
+/////////////////////
 
 //Photointerrupter input pins
 #define I1pin D2
 #define I2pin D11
 #define I3pin D12
 
+DigitalIn I1(I1pin);
+DigitalIn I2(I2pin);
+DigitalIn I3(I3pin);
+
+InterruptIn I1intr(I1pin);
+InterruptIn I2intr(I2pin);
+InterruptIn I3intr(I3pin);
+
 //Incremental encoder input pins
 #define CHA   D7
 #define CHB   D8  
 
+DigitalIn CHAR(CHA);
+DigitalIn CHBR(CHB);
+
+InterruptIn CHAintr(CHA);
+InterruptIn CHBintr(CHB);
+
+//Status LED
+DigitalOut led1 (LED1);
+DigitalOut led2 (LED2);
+DigitalOut led3 (LED3);
+
 //Motor Drive output pins   //Mask in output byte
 #define L1Lpin D4           //0x01
 #define L1Hpin D5           //0x02
@@ -18,6 +40,13 @@
 #define L3Lpin D9           //0x10
 #define L3Hpin D10          //0x20
 
+PwmOut L1L(L1Lpin);
+PwmOut L1H(L1Hpin);
+PwmOut L2L(L2Lpin);
+PwmOut L2H(L2Hpin);
+PwmOut L3L(L3Lpin);
+PwmOut L3H(L3Hpin);
+
 //Mapping from sequential drive states to motor phase outputs
 /*
 State   L1  L2  L3
@@ -30,92 +59,304 @@
 6       -   -   -
 7       -   -   -
 */
+
 //Drive state to output table
 const int8_t driveTable[] = {0x12,0x18,0x09,0x21,0x24,0x06,0x00,0x00};
 
 //Mapping from interrupter inputs to sequential rotor states. 0x00 and 0x07 are not valid
 const int8_t stateMap[] = {0x07,0x05,0x03,0x04,0x01,0x00,0x02,0x07};  
-//const int8_t stateMap[] = {0x07,0x01,0x03,0x02,0x05,0x00,0x04,0x07}; //Alternative if phase order of input or drive is reversed
+const int8_t stateMapReversed[] = {0x07,0x01,0x03,0x02,0x05,0x00,0x04,0x07}; //Alternative if phase order of input or drive is reversed
 
 //Phase lead to make motor spin
-const int8_t lead = -2;  //2 for forwards, -2 for backwards
+volatile int8_t lead = 2;  //2 for forwards, -2 for backwards
+
+
+
+//////////////////////
+// Global variables //
+//////////////////////
 
-//Status LED
-DigitalOut led1(LED1);
+volatile float targetSpeed; // User defined instantaneous speed
+volatile float targetPosition;
+volatile float revPerSec = 0; // Instantaneous speed estimate
+volatile float slitPosition = 0;
+volatile float photoPosition = 0;
+volatile float positionEstimate = 0;
+volatile float previousTime = 0; // Used to calculate revPerSec
+volatile float previousSpeed = 0; // Previous value of revPerSec
+volatile float errorPrev = 0.0; //Previous value of error
+volatile float integralError = 0.0; //Integral of the error
+volatile float dutyCycle; // PWM duty cycle between 0 and 1
+volatile float timeMap[] = {0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 }; // Keep track of last state
+Timer timer; // To keep track of time
+Serial pc(SERIAL_TX,SERIAL_RX); // Serial connection
+
 
-//Photointerrupter inputs
-DigitalIn I1(I1pin);
-DigitalIn I2(I2pin);
-DigitalIn I3(I3pin);
+///////////////
+// Functions //
+///////////////
+
+float parseNumber (int position, int *new_pos, char *inPut){
+  char number[8];
+  int count = position;
+  
+  while((inPut[count] > '0' && inPut[count] < '9') || inPut[count] == '-' || inPut[count] == '.')
+  {
+      count ++;   
+  }
+  for (int i = position; i < count; i++)
+  {
+      number[i-position] = inPut[i];
+  }
+      number[count] = '\0';
+      *new_pos = count;
+      return atof(number);  
+  } 
+void parseTones(char *inPut)
+{
+    int count = 1;
+    while (inPut[count] != 13)
+    {
+        //Depends on the format of the tone output
+        }
+    } 
 
-//Motor Drive outputs
-DigitalOut L1L(L1Lpin);
-DigitalOut L1H(L1Hpin);
-DigitalOut L2L(L2Lpin);
-DigitalOut L2H(L2Hpin);
-DigitalOut L3L(L3Lpin);
-DigitalOut L3H(L3Hpin);
+// THREAD: Parse input
+void parseRegex(char *inPut, float *speed, float *rev){
+    
+        int pos_pointer = 0;
+        switch (inPut[0])
+        {
+            case 'R':
+            //printf("%d\r\n",pos_pointer);
+            *rev = parseNumber(1, &pos_pointer, inPut);
+            //printf("%d\r\n",pos_pointer);
+            if (inPut[pos_pointer] == 'V'){
+                //both R and V defined
+                *speed = parseNumber(pos_pointer+1, &pos_pointer, inPut);
+               // printf("%d\r\n",pos_pointer);
+                }
+            else if (inPut[pos_pointer] != '\r')
+            {
+                 pc.printf("Invalid syntax");
+                }
+            
+            break;
+            case 'V':
+            *speed = parseNumber(1, &pos_pointer, inPut);
+            break;
+            case 'T':
+            parseTones(inPut);
+            break;
+            default:
+            pc.printf("Invalid syntax");
+            //wrong format
+            break;
+            }
+        pc.printf("Revolutions entered: %f, Desired speed: %f\n\r", rev, speed);
+        
+    }
+
+// THREAD: Print instantaneous speed
+void printStatus() {
+    while(1){
+        led3 = !led3;
+        pc.printf("%f\n\r",revPerSec);
+        wait(2);
+    }
+}
 
-//Set a given drive state
-void motorOut(int8_t driveState){
+// THREAD: Control loop
+void controlSpeed(float *targetSpeed){
+    while(true){
+        float error = *targetSpeed - revPerSec;
+        float errorDer = (error - errorPrev);
+        integralError += error;
+        float k = 0.4;
+        float kd = 0.0;
+        float ki = 0.00015;
+        dutyCycle = k*error + ki*integralError;
+        
+        errorPrev = error; //remeber error
+        wait(0.01);
+    }
+}
+
+// THREAD: Control loop
+void controlPosition(float *targetPosition){
+    while(true){
+        positionEstimate = photoPosition + slitPosition;
+        float error = *targetPosition - positionEstimate;
+        float errorDer = (error - errorPrev);
+        float k = 1.0;
+        float kd = 240.0;
+        float limit = 0.5;
+        if (error < 50.0){k = 10.0; limit = 0.2;}
+        dutyCycle = k*error + kd*errorDer;
+        if (dutyCycle < 0) {lead = -2; led1 = 0;} else {lead = 2; led1 = 1;}
+        if (dutyCycle > limit) {dutyCycle = limit;}
+        errorPrev = error; //remeber error
+        wait(0.001);
+    }
+}
+
+// Measure speed using slits
+void measureSpeedSlits(){
+    float currentTime = timer.read();
+    revPerSec = 0.4*previousSpeed + 0.6*((0.0021367521)/(currentTime-previousTime));
+    previousTime = currentTime;
+    previousSpeed = revPerSec;
+}
+
+void measurePositionSlits(){
+    slitPosition += 0.0021367521;
+}
+
+// Measure speed using photointerrupters
+void measureSpeedPhoto(){
+    led3 = !led3;
+    float speedTime;
+    speedTime = timer.read();
+    revPerSec = 1.0/(speedTime - timeMap[I1 + 2*I2 + 4*I3]);
+    timeMap[I1 + 2*I2 + 4*I3] = speedTime;
+}          
+
+void measurePositionPhoto(){
+    photoPosition += 0.16666666;
+    slitPosition = 0.0;
+}    
     
+// Set motor states
+void motorOut(int8_t driveState, float dutyCycle){
     //Lookup the output byte from the drive state.
     int8_t driveOut = driveTable[driveState & 0x07];
       
     //Turn off first
-    if (~driveOut & 0x01) L1L = 0;
-    if (~driveOut & 0x02) L1H = 1;
-    if (~driveOut & 0x04) L2L = 0;
-    if (~driveOut & 0x08) L2H = 1;
-    if (~driveOut & 0x10) L3L = 0;
-    if (~driveOut & 0x20) L3H = 1;
+    if (~driveOut & 0x01) L1L.write(0);         // = 0
+    if (~driveOut & 0x02) L1H.write(dutyCycle); // = 1;
+    if (~driveOut & 0x04) L2L.write(0);         // = 0;
+    if (~driveOut & 0x08) L2H.write(dutyCycle); // = 1;
+    if (~driveOut & 0x10) L3L.write(0);         // = 0;
+    if (~driveOut & 0x20) L3H.write(dutyCycle); // = 1;
     
     //Then turn on
-    if (driveOut & 0x01) L1L = 1;
-    if (driveOut & 0x02) L1H = 0;
-    if (driveOut & 0x04) L2L = 1;
-    if (driveOut & 0x08) L2H = 0;
-    if (driveOut & 0x10) L3L = 1;
-    if (driveOut & 0x20) L3H = 0;
-    }
+    if (driveOut & 0x01) L1L.write(dutyCycle);  // = 1;
+    if (driveOut & 0x02) L1H.write(0);          // = 0;
+    if (driveOut & 0x04) L2L.write(dutyCycle);  // = 1;
+    if (driveOut & 0x08) L2H.write(0);          // = 0;
+    if (driveOut & 0x10) L3L.write(dutyCycle);  // = 1;
+    if (driveOut & 0x20) L3H.write(0);          // = 0;
+}
     
-    //Convert photointerrupter inputs to a rotor state
+//Convert photointerrupter inputs to a rotor state
 inline int8_t readRotorState(){
-    return stateMap[I1 + 2*I2 + 4*I3];
-    }
+    if (lead > 0){return stateMap[I1 + 2*I2 + 4*I3];}
+    else {return stateMapReversed[I1 + 2*I2 + 4*I3];}
+    //return stateMap[I1 + 2*I2 + 4*I3];
+}
 
 //Basic synchronisation routine    
 int8_t motorHome() {
     //Put the motor in drive state 0 and wait for it to stabilise
-    motorOut(0);
-    wait(1.0);
+    motorOut(0,1);
+    wait(7.0);
     
     //Get the rotor state
     return readRotorState();
 }
+
+
+//////////
+// Main //
+//////////     
+
+int main() {
     
-//Main
-int main() {
+    // Initialize threads
+    Thread speedControlThread(osPriorityNormal, DEFAULT_STACK_SIZE/4);
+    Thread positionControlThread(osPriorityNormal, DEFAULT_STACK_SIZE/4);
+    Thread playTones(osPriorityNormal, DEFAULT_STACK_SIZE/4);
+
+    timer.start();
+    
+    //Initialize the serial port
+    Serial pc(SERIAL_TX, SERIAL_RX);
+    pc.printf("Device on \n\r");
+    
     int8_t orState = 0;    //Rotot offset at motor state 0
-    
-    //Initialise the serial port
-    Serial pc(SERIAL_TX, SERIAL_RX);
     int8_t intState = 0;
     int8_t intStateOld = 0;
-    pc.printf("Hello\n\r");
+    
+    float PWM_period = 0.001f; 
+
+    L1L.period(PWM_period);
+    L1H.period(PWM_period);
+    L2L.period(PWM_period);
+    L2H.period(PWM_period);
+    L3L.period(PWM_period);
+    L3H.period(PWM_period);
+    
+    // Slits interrupts
+    CHAintr.rise(&measurePositionSlits);
+    CHBintr.rise(&measurePositionSlits);
+    CHAintr.fall(&measurePositionSlits);
+    CHBintr.fall(&measurePositionSlits);
     
     //Run the motor synchronisation
     orState = motorHome();
-    pc.printf("Rotor origin: %x\n\r",orState);
-    //orState is subtracted from future rotor state inputs to align rotor and motor states
+    
+    // USE FOR PHOTOINTERRUPTERS
+    // Photointerrupters interrupts
+    I1intr.rise(&measurePositionPhoto);
+    I2intr.rise(&measurePositionPhoto);
+    I3intr.rise(&measurePositionPhoto);
+    I1intr.fall(&measurePositionPhoto);
+    I2intr.fall(&measurePositionPhoto);
+    I3intr.fall(&measurePositionPhoto);
     
     //Poll the rotor state and set the motor outputs accordingly to spin the motor
     while (1) {
+        
+        // Read serial input
+        if (pc.readable()){
+            speedControlThread.terminate();
+            positionControlThread.terminate();
+
+            int c = 0;
+            char input[50];
+            char tmp;
+            float rev = 0;
+            float speed = 0;
+            
+            while((tmp = pc.getc()) != '\r'){
+                input[c] = tmp;
+                pc.printf("%c",tmp);
+                c++;
+            }
+            
+            input[c] = '\r';
+            parseRegex(input, &speed, &rev);
+            orState = motorHome();
+            intState = 0;
+            intStateOld = 0;
+            integralError = 0.0;
+            
+            if (rev == 0.0 && speed != 0.0){
+                speedControlThread.start(callback(controlSpeed, &speed));
+            }
+            
+            else if (rev != 0.0 && speed == 0.0){
+                slitPosition = 0.0;
+                photoPosition = 0.0;
+                positionEstimate = 0.0;
+                positionControlThread.start(callback(controlPosition, &rev));
+            }
+        }
+        
         intState = readRotorState();
         if (intState != intStateOld) {
             intStateOld = intState;
-            motorOut((intState-orState+lead+6)%6); //+6 to make sure the remainder is positive
+            motorOut((intState-orState+2+6)%6, dutyCycle); //+6 to make sure the remainder is positive
         }
     }
-}
-
+}
\ No newline at end of file