MRD Lab / SpindleBot_1_5b

Dependencies:   MX12 ServoRingBuffer mbed-src

Fork of SpindleBot by MRD Lab

Revision:
14:7c5beaa9fb01
Parent:
13:6a0a7a04fd91
--- a/main.cpp	Thu Aug 13 17:26:23 2015 +0000
+++ b/main.cpp	Thu Aug 13 17:55:40 2015 +0000
@@ -1,9 +1,6 @@
-// Different modes to select
-#define USE_DYNAMIXELS
-//#define USE_BLUETOOTH
-//#define USE_SD_CARD
-#define ROD_IS_RIGHT
-//#define CALIBRATE_TIME_NOW
+//#define USE_DYNAMIXELS
+#define USE_BLUETOOTH
+#define USE_SD_CARD
 
 // We have different modes for different things
 #define MODE_MANUAL     1
@@ -22,11 +19,11 @@
 #include "ServoRingBuffer.h"
 #include "ram_test.h"
 #include "Serial_Receive.h"
-#include "data_set.h"
 #include <string>
 
 // Specific to Dynamixels
 #ifdef USE_DYNAMIXELS
+#include "MX12.h"
 #include "AD7730.h"
 #endif
 
@@ -51,24 +48,22 @@
     STATE_OPEN_HOLD=3
 };
 
+
 // Define pins and interrupts
-Ticker potISR;                             //Define a recurring timer interrupt
-DigitalOut led1(LED1);                     //Led 1 for debugging purposes
-DigitalOut led2(LED2);                     //Led 2 for debugging purposes
-DigitalOut led3(LED3);                     //Led 3 for debugging purposes
-DigitalOut led4(LED4);                     //Led 4 for debugging purposes
+Ticker potISR;              //Define a recurring timer interrupt
+DigitalOut led1(LED1);      //Led 1 for debugging purposes
+DigitalOut led2(LED2);      //Led 2 for debugging purposes
+DigitalOut led3(LED3);      //Led 3 for debugging purposes
+//DigitalOut led4(LED4);      //Led 4 for debugging purposes
 DigitalOut triggerOut(p11);
-Serial pc(USBTX, USBRX);                   //Set up serial connection to pc
-AnalogIn AinLeftForce(p16);                //Set up left load cell on pin 16
-AnalogIn AinRightForce(p15);               //Set up right load cell on pin 15
-DigitalOut failSafePowerSwitch(p29);       //Set up pin 28 to send HIGH to OpenCM when MBED has power
-
-// Specific to bluetooth
+Serial pc(USBTX, USBRX);    //Set up serial connection to pc
 #ifdef USE_BLUETOOTH
 Serial bt(p13,p14);         //Set up serial connection to bluetooth adapter
 #endif
 
-// Specific to SD Card
+AnalogIn AinLeftForce(p16);          //Set up potentiometer on pin 20
+AnalogIn AinRightForce(p15);          //Set up potentiometer on pin 20
+
 #ifdef USE_SD_CARD
     // Attach SD card
     SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
@@ -81,6 +76,13 @@
 float max_percent_full=0;
 
 // Define variables for the program
+float servoAngle;                   //This is the desired servo angle based on the scaled potentiometer value
+float potData;                      //This is the value of the potentiometer from Ain.read()
+bool collect_data = false;          //This is 
+
+bool keyStrokeFlag = false;         //This is a flag to see if a keystroke has been pressed
+char keyStrokeVal;                  //This is a character storing the value of the keystroke
+
 char g_tissue_type_name[32];
 float g_frequency;
 int g_max_force;
@@ -91,130 +93,36 @@
 unsigned char g_current_mode=MODE_NULL;
 jaw_state g_current_direction=STATE_OPEN_HOLD;
 unsigned char g_current_cycle=0;
-int g_input_pot_1;
-#define NUMBER_OF_TISSUES 2
-float g_error_norm[NUMBER_OF_TISSUES];
-bool g_we_are_grasping=false;
-#define CALIBRATION_READS 200.0
-float g_calibration_offset = 8600000.0;
-float integral_err = 0.0;
-float g_loadCellSlopeCalibration = 2.1e-5;
-float forceInNewtons = 0.0;
-float g_gravity = 9.81;
-
-// Values at first touch
-int g_masterPositionFirstTouch = 2400;
-int g_slavePositionFirstTouch = 2400;
-float g_forceAboveFirstTouch = 3.5;
-float g_timeAtFirstTouch;
-
-///////////Magic numbers courtesy Rod///////////////
-//float Phi1[5]={-8.02086003501975e-08,
-//                1.55286905458007e-05,
-//                0.00795344249784777, 
-//                8.23733045077119,
-//               -0.00299236282304311};
-//float Phi2[5]={-1.24436831310503e-08,                                  
-//                1.23673348605010e-05,
-//                0.00652545188345528,
-//                6.75893262890734,
-//               -0.00228098997419065};
-
-/////////// Zero-Offset Magic Numbers courtesy Rod//////////////
-float Phi1[5] = {-1.80212053214826e-08,
-                 1.69579390650964e-06,
-                 0.000592679062823746,
-                 0.624774980172511,
-                 -0.000283294192960159};
-
-float Phi2[5] = {1.00123534796440e-09,
-                 1.42089516619424e-06,
-                 0.000520811899959219,
-                 0.542284752693981,
-                 -0.000248770560431049};
-                 
-// Magic numbers to determine if we are grasping (CHANGE TO  A DYNAMIC APPROACH!!!!)  
-//float entry_threshold=8.70e6;
-float velocity_threshold=-0.01;
-
-float g_thresh_force[NUMBER_OF_TISSUES]={0.16e6,0.06e6};
-///////////Magic numbers courtesy Rod///////////////
-
-int g_command_corrected;
-
-// These are for load cell initialization of the offset
-float g_loadCellZero = 8600000.0;
-bool calibrateDone = false;
-//long calibrateTotal = 8600;
-int calibCntr = 0;
-//int g_loadCellOffset = 100000;
-//int g_threshOffset1 = 0.2e6;
-//int g_threshOffset2 = 0.15e6;
-long long loadCellTotal = 0;
-
-Timer mytimer;
 
 // Warning, this buffer is large!
 ServoRingBuffer Buffer;
 spindleData tempSpindleData;  //For sending to the buffer
-#ifdef ROD_IS_RIGHT
-    int angle_sum=0;
-    int angle_count=0;
-    int angledot_sum=0;
-    int angledot_count=0;
-    int last_angle=0;
-    int angledotdot_sum=0;
-    int angledotdot_count=0;
-    int last_angledot=0;
-#else
-    data_set recent_pos(30,"Data","Time (us)","Position (encoder counts)");
-    float coeffs[4];
-    bool crunching_data_flag;
-#endif
-
-int bits_received;
 
 Timer ISRDurationTimer;
 Timer AuxSerialTimer;
 int worst_latency=0;
 int current_latency;
 
-// Specific to Dynamixels
 #ifdef USE_DYNAMIXELS
-    Serial cm(p28,p27);         //Set up serial connection to OpenCM 9.04
-    unsigned short left_servo_measured=0;
-    unsigned short right_servo_measured=0;
-    char input_buffer[16];
-    int  input_buffer_location=0;
-
-    float samplingPeriod = 0.001;       //This is the sampling period for the timer interrupt
+    //Dynamixels can only handle 500Hz for now.  Working on it...
+    float samplingPeriod = 0.005;       //This is the sampling period for the timer interrupt
     #define LEFT_JAW_DYNAMIXEL_ID        3
     #define RIGHT_JAW_DYNAMIXEL_ID       4
-//    #define CLOSED_SERVO_ANGLE_LEFT   1001      //This is the closed in encoder counts
-//    #define OPEN_SERVO_ANGLE_LEFT     2663      //This is the open in encoder counts
-//    #define CLOSED_SERVO_ANGLE_RIGHT  3259      //This is the closed in encoder counts
-//    #define OPEN_SERVO_ANGLE_RIGHT    1486      //This is the open in encoder counts
-    #define CLOSED_SERVO_ANGLE_LEFT   1975      //This is the closed in encoder counts
-    #define OPEN_SERVO_ANGLE_LEFT     2560      //This is the open in encoder counts
-    #define CLOSED_SERVO_ANGLE_RIGHT  1975      //This is the closed in encoder counts
-    #define OPEN_SERVO_ANGLE_RIGHT    2560      //This is the open in encoder counts
-    //AD7730( mosi, miso, sclk, ready, cs)
-    AD7730 adc(p11, p12, p13, p14, p15);
-    //AD7730 adc2(p11, p12, p13, p18, p19);
+    #define CLOSED_SERVO_ANGLE_LEFT   1121      //This is the closed in encoder counts
+    #define OPEN_SERVO_ANGLE_LEFT     2783      //This is the open in encoder counts
+    #define CLOSED_SERVO_ANGLE_RIGHT  3259      //This is the closed in encoder counts
+    #define OPEN_SERVO_ANGLE_RIGHT    1486      //This is the open in encoder counts
+    // Dynamixel Object
+    MX12 mx12_left_jaw  (p28, p27, p30, p29, LEFT_JAW_DYNAMIXEL_ID,  1000000);
+    MX12 mx12_right_jaw (p28, p27, p30, p29, RIGHT_JAW_DYNAMIXEL_ID, 1000000);
     
-    
-    AnalogIn AinJoystickFwdBk(p17);          //Set up potentiometer on pin 17
-    AnalogIn AinJoystickLftRt(p16);          //Set up potentiometer on pin 16
-    float JoystickFwdBk_Zero=0.5;
-    float JoystickLftRt_Zero=0.5;
+    AD7730 adc(p9, p26, p11, p12, p25);
     
     /// Set these to inputs so that they don't interfere with the serial communication
     DigitalIn nullOut1(p21);
     DigitalIn nullOut2(p22);
     DigitalIn nullOut3(p23);
     DigitalIn nullOut4(p24);
-    /// This one is in the way of the SMD pads
-    DigitalIn nullOut5(p20);
 #else
     float samplingPeriod = 0.001;       //This is the sampling period for the timer interrupt
     #define SERVO_DEGREE_0    900       //This is the pulse width value for HiTEC-422 in microseconds to turn 0 degrees
@@ -243,42 +151,6 @@
 
 #endif
 
-// Serial interrupt function  
-void serialInterrupt(char buffer){
-  input_buffer[input_buffer_location]=buffer;
-  input_buffer_location++;
-  bits_received+=8;
-  //pc.printf("RC:%d\n",buffer);
-  
-  
-  //Is the packet looking good so far??
-  if(input_buffer[0]==0xFF){
-    //Is the packet looking good so far??????
-    if(input_buffer[1]==0xFF || input_buffer_location ==1){
-      //Do we have a complete packet??
-      if(input_buffer_location>=6){ //This is 6 because we already incremented
-        //We do!  Extract the juicy datas
-        left_servo_measured = ( input_buffer[2] << 8 ) | input_buffer[3];
-        right_servo_measured = ( input_buffer[4] << 8 ) | input_buffer[5];
-        //pc.printf("RP:%d,%d\n",left_servo_measured,right_servo_measured);
-        //Reset the buffer location so we can start over
-        input_buffer_location=0;
-      }
-    }else{
-      //Something is wrong.  We may just not be at the correct location in the packet
-      //Reset the buffer location so we can start over
-      input_buffer_location=0;
-      //printf("Error, Byte 2 not what was expected: 0xFF!=0x%02x\n",input_buffer[1]);
-    }
-  }else{
-    //Something is wrong.  We may just not be at the correct location in the packet
-    //Reset the buffer location so we can start over
-    input_buffer_location=0;
-    //printf("Error, Byte 1 not what was expected: 0xFF!=0x%02x\n",input_buffer[0]);
-  }
-}
-
-
 // Function trapezoidalTrajectory: Function that takes in a time (float in seconds) and outputs a float (0 to 1) that corresponds to a trapezoidal trajectory
 float trapezoidalTrajectory(float t, jaw_state &state, unsigned char &cycle_num) {
     // Define variables specific to this function
@@ -291,7 +163,7 @@
     // Take the time and mod it with the period to be able to break up each cycle into 4 piecewise sections
     timeMod = fmodf(t,period);
     
-    // Determining trajectory
+    //
     if (timeMod < period/4.0)
     {
         y_trapezoid = (-4.0/period)*(timeMod)+1.0;
@@ -323,7 +195,7 @@
 
 // Function timerISRFunction: Timer ISR function to collect data and write to ring buffer
 void timerISRFunction() {
-    //if (calibrateDone){
+    if(collect_data){
         //led 1 is used as a 'thinking' light, brighter=worse
         led1 = 1;
         led2 = 0;
@@ -331,143 +203,50 @@
         
         ISRDurationTimer.reset();
         ISRDurationTimer.start();
-        if(g_current_mode==MODE_AUTOMATIC){
-            
-            // Warning, this calculation is in the ISR and as such is probably slower than we would prefer.  
-            // @todo The math could certainly be optimized with some precalculated constants.  Lookup tables are faster than sin()
-            float percent=trapezoidalTrajectory(g_current_trajectory_time,g_current_direction,g_current_cycle);
-            g_current_trajectory_time+=samplingPeriod;
-            
-            
-            //float angle=g_current_trajectory_time*g_frequency*2.0*M_PI-M_PI_2;
-            //g_current_direction=(cos(angle)<0);
-            //g_current_cycle=(angle+M_PI_2)/(2.0*M_PI);
-            
-    
-            #ifdef USE_DYNAMIXELS
-                //float percent=(sin(angle)+1)/2.0;
-                if(adc.isReady()){
-                    adc.interruptRead();
-                }
-                
-                while(cm.readable()){
-                    led4=1;
-                    serialInterrupt(cm.getc());
-                }
-                led4=0;
-                
-                short left_servo =percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ;
-                short right_servo=percent*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT)+OPEN_SERVO_ANGLE_RIGHT;
-                
-                //Send the commanded position to the OpenCM board
-                cm.putc(0xFF);
-                cm.putc(0xFF);
-                cm.putc(left_servo  >> 8);   //Top 4 bits
-                cm.putc(left_servo  & 0xFF); //Bottom 8 bits
-                cm.putc(right_servo >> 8);   //Top 4 bits
-                cm.putc(right_servo & 0xFF); //Bottom 8 bits
-                
-                tempSpindleData.myServoData[LEFT_SERVO_INDEX].force  = adc.read();
-                tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos    = left_servo_measured;
-                tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = 0;
-                tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos   = right_servo_measured;
-                tempSpindleData.direction=g_current_direction;
-                tempSpindleData.cycle=g_current_cycle;
-                Buffer.write(tempSpindleData);
-            #else   
-                g_theta=(1.0-percent)*(MAX_SERVO_ANGLE_Da_VINCI-MIN_SERVO_ANGLE_Da_VINCI)+MIN_SERVO_ANGLE_Da_VINCI;
-                tempSpindleData.myServoData[LEFT_SERVO_INDEX].force  = AinLeftForce.read_u16();
-                tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos    = AinLeftPosition.read_u16();
-                tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = AinRightForce.read_u16();
-                tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos   = AinRightPosition.read_u16();
-                tempSpindleData.direction=g_current_direction;
-                tempSpindleData.cycle=g_current_cycle;
-                Buffer.write(tempSpindleData);
-                
-                
-                
-                moveServoTo(g_theta); // in degrees, son
-            #endif
-        }else if(g_current_mode==MODE_MANUAL){
-            
-            g_current_trajectory_time+=samplingPeriod;
+        
+        // Warning, this calculation is in the ISR and as such is probably slower than we would prefer.  
+        // @todo The math could certainly be optimized with some precalculated constants.  Lookup tables are faster than sin()
+        float percent=trapezoidalTrajectory(g_current_trajectory_time,g_current_direction,g_current_cycle);
+        g_current_trajectory_time+=samplingPeriod;
+        
+        
+        //float angle=g_current_trajectory_time*g_frequency*2.0*M_PI-M_PI_2;
+        //g_current_direction=(cos(angle)<0);
+        //g_current_cycle=(angle+M_PI_2)/(2.0*M_PI);
+        
+
+        #ifdef USE_DYNAMIXELS
+            //float percent=(sin(angle)+1)/2.0;
             if(adc.isReady()){
                 adc.interruptRead();
             }
             
-            int im_tired_of_this_game=0;
-            while(cm.readable() && im_tired_of_this_game++<100){
-                serialInterrupt(cm.getc());
-            }
-            
-    //        float pot_open=0.75;
-    //        float pot_closed=0.48;
-    //        
-    //        float percent=AinJoystickFwdBk.read();
-    //        percent=(pot_open-percent)/(pot_open-pot_closed);
-    //        float skew   =0;//AinJoystickLftRt.read()-JoystickLftRt_Zero;
-    //        
-    //        // The 'pulling' of the trigger corresponds to open/closed
-    //        short left_servo =percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ;
-    //        short right_servo=percent*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT)+OPEN_SERVO_ANGLE_RIGHT;
-    //        
-    //        g_input_pot_1=left_servo;
-            // Set limits on the max and min value of the grasper (for safety reasons)
-            if (g_command_corrected < 1900){g_command_corrected = 1900;};
-            if (g_command_corrected > 2900){g_command_corrected = 2900;};
-            short left_servo =g_command_corrected;
-            short right_servo=g_command_corrected;
+            short left_servo =percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ;
+            short right_servo=percent*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT)+OPEN_SERVO_ANGLE_RIGHT;
+            mx12_right_jaw.coordinated_move(LEFT_JAW_DYNAMIXEL_ID,left_servo, 0, RIGHT_JAW_DYNAMIXEL_ID,right_servo, 0);
             
-    //        // The 'skewing' of the trigger corresponds to yawing the jaws left or right, while maintaining open/closed
-    //        left_servo +=skew*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT );
-    //        right_servo-=skew*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT);
-    //        
-    //        /// Todo: There is undoubtedly a cleaner way to do this.
-    //        if(OPEN_SERVO_ANGLE_LEFT  < CLOSED_SERVO_ANGLE_LEFT   && left_servo  < OPEN_SERVO_ANGLE_LEFT ){left_servo =OPEN_SERVO_ANGLE_LEFT; }
-    //        if(OPEN_SERVO_ANGLE_LEFT  > CLOSED_SERVO_ANGLE_LEFT   && left_servo  > OPEN_SERVO_ANGLE_LEFT ){left_servo =OPEN_SERVO_ANGLE_LEFT; }
-    //        if(OPEN_SERVO_ANGLE_RIGHT < CLOSED_SERVO_ANGLE_RIGHT  && right_servo < OPEN_SERVO_ANGLE_RIGHT){right_servo=OPEN_SERVO_ANGLE_RIGHT;}
-    //        if(OPEN_SERVO_ANGLE_RIGHT > CLOSED_SERVO_ANGLE_RIGHT  && right_servo > OPEN_SERVO_ANGLE_RIGHT){right_servo=OPEN_SERVO_ANGLE_RIGHT;}
-    //        
-    //        // Just to make sure
-    //        // left_servo=(left_servo+4096)%4096;
-    //        if(left_servo <   0){left_servo =   0;}
-    //        if(left_servo >4095){left_servo =4095;}
-    //        if(right_servo<   0){right_servo=   0;}
-    //        if(right_servo>4095){right_servo=4095;}
-            
-            //Send the commanded position to the OpenCM board
-            cm.putc(0xFF);
-            cm.putc(0xFF);
-            cm.putc(left_servo  >> 8);   //Top 4 bits
-            cm.putc(left_servo  & 0xFF); //Bottom 8 bits
-            cm.putc(right_servo >> 8);   //Top 4 bits
-            cm.putc(right_servo & 0xFF); //Bottom 8 bits
+//            tempSpindleData.myServoData[LEFT_SERVO_INDEX].force  = adc.read();
+//            tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos    = mx12_left_jaw.GetRawPosition();
+//            tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = AinRightForce.read_u16();
+//            tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos   = mx12_right_jaw.GetRawPosition();
+//            tempSpindleData.direction=g_current_direction;
+//            tempSpindleData.cycle=g_current_cycle;
+//            Buffer.write(tempSpindleData);
+        #else   
+            g_theta=(1.0-percent)*(MAX_SERVO_ANGLE_Da_VINCI-MIN_SERVO_ANGLE_Da_VINCI)+MIN_SERVO_ANGLE_Da_VINCI;
+            tempSpindleData.myServoData[LEFT_SERVO_INDEX].force  = AinLeftForce.read_u16();
+            tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos    = AinLeftPosition.read_u16();
+            tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = AinRightForce.read_u16();
+            tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos   = AinRightPosition.read_u16();
+            tempSpindleData.direction=g_current_direction;
+            tempSpindleData.cycle=g_current_cycle;
+            Buffer.write(tempSpindleData);
             
-            #ifdef ROD_IS_RIGHT
-                //Famous Rod's Magical World of Good Ideas Part 1
-                int angle=left_servo_measured;
-                angle_sum+=angle;
-                if(angle_count!=0){
-                    int angledot=(angle-last_angle);
-                    angledot_sum+=angledot;
-                    if(angledot_count!=0){
-                        int angledotdot=(angledot-last_angledot);
-                        angledotdot_sum+=angledotdot;
-                        angledotdot_count++;
-                    }
-                    angledot_count++;
-                    last_angledot=angledot;
-                }
-                angle_count++;
-                last_angle=angle;
-            #else
-                // John's worse than Rod ideas of terribleness
-                if(!crunching_data_flag){ // Only add data if no one is using it
-                    recent_pos.add_data(left_servo_measured,g_current_trajectory_time);
-                }
-            #endif
-        }
+            
             
+            moveServoTo(g_theta); // in degrees, son
+        #endif
+        
         //done thinking
         led1 = 0;
         led2 = 1;
@@ -478,43 +257,20 @@
         if(current_latency>worst_latency){
             worst_latency=current_latency;
         }
-    //}
+    }
 }
 
-// Calibrate Load Cell Function (NOT USING THIS ONE!!!)
-void calibrateLoadCell() {
-    long long loadCellTotal = 0;
-    int intermediateValue;
-    for(int ii=0;ii<CALIBRATION_READS;ii++){
-        intermediateValue = adc.read();
-        //pc.printf("Load Cell Read: %i\n",intermediateValue);
-        loadCellTotal+= intermediateValue;
-        wait_ms(2);
-        //pc.printf("We are calibrating load cells...\n");
-        }
-    g_calibration_offset=float(loadCellTotal)/float(CALIBRATION_READS);
-    //Update values for thresholding based on calibration
-    //g_thresh_force[0]=g_threshOffset1+g_calibration_offset;
-    //g_thresh_force[1]=g_threshOffset2+g_calibration_offset;
-    calibrateDone = true;
-}
 
 int main() {
     // Crazy fast baud rate!
-    pc.baud(115200*8);
-    
-    // For communication with OpenCM 9.04 Board
-    cm.baud(1000000);
+    pc.baud(921600);
     
     #ifdef USE_BLUETOOTH
     bt.baud(9600);
     #endif
     
     // Attach ISR routines
-    potISR.attach(&timerISRFunction, samplingPeriod); // setup serialPot to call every samplingPeriod   
-    
-    // Turn p28 to HIGH signaling the OpenCM to take commands from MBED
-    failSafePowerSwitch = 1;
+    potISR.attach(&timerISRFunction, samplingPeriod); // setup serialPot to call every samplingPeriod
     
     // Some debug info:
     //DisplayRAMBanks();
@@ -543,39 +299,44 @@
     pc.printf("\n\n");
     
     #ifdef USE_DYNAMIXELS
+        mx12_left_jaw.Init();
+        //mx12_left_jaw.SetBaud(3000000);
+        //mx12_left_jaw.SetBaud(1000000);
+        //printf("Current Position=%1.3f\n",mx12_left_jaw.GetPosition());
+        mx12_right_jaw.Set_Return_Delay_Time(0.050);
+        printf("Current ReturnDelay=%f ms\n",mx12_left_jaw.Get_Return_Delay_Time());
+        mx12_left_jaw.Set_Return_Delay_Time(0.050);
+        //mx12_left_jaw.Set_Torque_Limit(99.9);
+        //mx12_right_jaw.Set_Torque_Limit(99.9);
+        mx12_left_jaw.write_short(MX12_REG_MAX_TORQUE,0x03FF);
+        mx12_right_jaw.write_short(MX12_REG_MAX_TORQUE,0x03FF);
+        mx12_left_jaw.Set_P_Gain(4);
+        mx12_right_jaw.Set_P_Gain(4);
+        mx12_left_jaw.Set_I_Gain(8);
+        mx12_right_jaw.Set_I_Gain(8);
+        mx12_left_jaw.Set_Alarm_Shutdown(0x04);
+        mx12_right_jaw.Set_Alarm_Shutdown(0x04);
+        
+        mx12_left_jaw.Dump_OD_to_Serial(pc);
+        mx12_right_jaw.Dump_OD_to_Serial(pc);
+        
+        
+        
         adc.setFilter(256 , false, 1);
         adc.start();
-        
-        JoystickLftRt_Zero=0;
-        int calib_N=100;
-        for(int ii=0;ii<calib_N;ii++){JoystickLftRt_Zero+=AinJoystickLftRt.read();}
-        JoystickLftRt_Zero=JoystickLftRt_Zero/calib_N;
-        g_current_mode=MODE_MANUAL;
     #else
         // Configure Servo for HiTec 422
         myServoLeft.period_ms(20);
         myServoRight.period_ms(20);
     #endif
     
-
-    
     printf("Setup Complete.\n");
     AuxSerialTimer.start();
-    mytimer.start();
     
-    
-    //wait_ms(1000);
-    //calibrateLoadCell(); // This function did not work as well as having it in the main loop
     while(1)
     {
         // spin in a main loop. serialISR will interrupt it to call serialPot
         
-   
-        
-        #ifdef USE_DYNAMIXELS
-        
-        #endif
-        
         ///This checks for any new serial bytes, and returns true if
         ///we have an entire packet ready.  The new packet will live
         ///in newData.
@@ -596,6 +357,7 @@
             g_num_cycles=newData[3];
             g_current_trajectory_time=0;
             g_current_cycle=0;
+            g_current_mode=MODE_AUTOMATIC;
             #ifdef USE_SD_CARD
                 int first_slash=file_name_in.find("/");
                 std::string new_dir="/sd/"+file_name_in.substr(0, first_slash);
@@ -620,13 +382,13 @@
                 fprintf(fp, "%%PositionLeft,ForceLeft,PositionRight,ForceRight,Time(ms),Direction,CycleNum\n");
             #endif
             // We are go-times!
-            g_current_mode=MODE_AUTOMATIC;
+            collect_data=true;
         }
         
-        if( g_current_mode==MODE_AUTOMATIC && g_current_cycle >= g_num_cycles)
+        if( collect_data && g_current_cycle >= g_num_cycles)
         {
             // STOOOOOOOOOP
-            g_current_mode=MODE_NULL;
+            collect_data=false;
             #ifdef USE_SD_CARD
                 // Close the file
                 fclose(fp); 
@@ -634,7 +396,7 @@
             #endif
         }
         
-        // This section of code should run whenever there is free time to save datas
+        // This section of code should run whenever there is free time to print to the screen
         #ifdef USE_SD_CARD
         if(fp != NULL) {
             // Only write to SD if there is a valid file handle
@@ -643,163 +405,20 @@
             led3 = 0;
         }
         #else
-            //Warning, this is a big fat stream of data, 1 minute is approx 3MB
-            //I certainly recommend using the SD card.
             Buffer.dumpBufferToSerial();
         #endif
         
-        if(g_current_mode!=MODE_NULL && AuxSerialTimer.read_us()>1000){
+        if(AuxSerialTimer.read_ms()>100 && collect_data){
             //Send some extra data for GUI purposes
-            #ifdef ROD_IS_RIGHT
-                float angle=0,angledot=0,angledotdot=0;
-                if(angledotdot_count>0){
-                    angle      =float(angle_sum      )/angle_count;
-                    angledot   =float(angledot_sum   )/angledot_count;
-                    angledotdot=float(angledotdot_sum)/angledotdot_count;
-                }
-                angle_sum=0;angle_count=0;
-                angledot_sum=0;angledot_count=0;
-                angledotdot_sum=0;angledotdot_count=0;
-            #else
-                crunching_data_flag=true;
-                recent_pos.least_squares_3rd(coeffs);
-                crunching_data_flag=false;
-                float x=g_current_trajectory_time;
-                int angle      =coeffs[0]+coeffs[1]*x+coeffs[2]*x*x+coeffs[3]*x*x*x;
-                int angledot   =          coeffs[1]+2*coeffs[2]*x+3*coeffs[3]*x*x  ;
-                int angledotdot=                    2*coeffs[2]  +6*coeffs[3]*x    ;
-            #endif
-            
-            
-            
-            float pot_open=0.75;
-            float pot_closed=0.48;
-            
-            float percent=0.0;
-            //Average the pot a bunch, it's NOISY
-            for(int i=0;i<100;i++){
-                percent+=AinJoystickFwdBk.read();
-            }
-            percent=percent/100.0;
-            percent=(pot_open-percent)/(pot_open-pot_closed);
-            
-            // The 'pulling' of the trigger corresponds to open/closed
-            int potread = percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ;
-            
-            //angle=left_servo_measured;
-            
-            //if (!calibrateDone){
-            //    wait_ms(2);
-            //}
-            int loadcell=adc.read();
-
-            if (!calibrateDone){
-                g_command_corrected = 2800;
-                // Begin Calibration of load cells
-                loadCellTotal += (long long) loadcell;
-                calibCntr ++;
-                if (calibCntr == CALIBRATION_READS){
-                    g_loadCellZero = float(loadCellTotal)/float(CALIBRATION_READS); 
-                    calibrateDone = true;
-                }
-            }
-            
-
-            #ifdef CALIBRATE_TIME_NOW
-                if (calibrateDone){
-                    g_command_corrected=potread;
-                    int loadcell_offset = loadcell - g_loadCellZero;
-                    if(loadcell_offset < 0){
-                        loadcell_offset = 0;
-                    }
-                    printf("%6.3f,%0.0f,%2.3f,%2.3f,%d\n",mytimer.read_us()/1000.0,angle, angledot, angledotdot, loadcell_offset);
-            
-                } 
-            #else
-                float loadcell_offset = float(loadcell) - g_loadCellZero;
-                if(loadcell_offset < 0.0){
-                    loadcell_offset = 0.0;
-                }
-                // Convert Load cell read into Newtons
-                forceInNewtons = ((loadcell_offset)*g_loadCellSlopeCalibration)*g_gravity;
-                // Code to determine if we should toggle the variable of "g_we_are_grasping"
-                if(!g_we_are_grasping && forceInNewtons>g_forceAboveFirstTouch && angledot<velocity_threshold){
-                    //Grasp is starting
-                    g_we_are_grasping=true;
-                    // Set the position and time at first touch
-                    g_masterPositionFirstTouch = potread;
-                    g_slavePositionFirstTouch = angle;  
-                    g_timeAtFirstTouch = mytimer.read_us()/1000.0;
-                    for(int i=0;i<NUMBER_OF_TISSUES;i++){
-                        g_error_norm[i]=0.0;
-                    }
-                }
-                if(g_we_are_grasping && potread > 2400 && (mytimer.read_us()/1000.0) > (g_timeAtFirstTouch + 200.0)) {//angledot>-velocity_threshold){
-                    //Grasp is over
-                    g_error_norm[0] = 0;
-                    g_error_norm[1] = 0;
-                    integral_err = 0.0;
-                    g_we_are_grasping=false;
-                }
-                float alpha=0;
-                std::string sstr;
-                if(g_we_are_grasping){
-                    //D_x = [thetadotdot,thetadot,theta,theta^2,theta^3];
-                    g_error_norm[0]+=fabs(float(loadcell_offset)-(Phi1[0]*angledotdot+Phi1[1]*angledot+Phi1[2]*angle+Phi1[3]*angle*angle+Phi1[4]*angle*angle*angle));
-                    g_error_norm[1]+=fabs(float(loadcell_offset )-(Phi2[0]*angledotdot+Phi2[1]*angledot+Phi2[2]*angle+Phi2[3]*angle*angle+Phi2[4]*angle*angle*angle));
-                    
-                    
-                    float offset1 = 100000;
-                    float offset2 = 300000;
-                    int tissue_id=0;
-                    if(g_error_norm[1]>g_error_norm[0]){alpha=(g_error_norm[1]-g_error_norm[0])/(g_error_norm[1]+offset1);sstr="HARD";tissue_id=0;}
-                    if(g_error_norm[0]>g_error_norm[1]){alpha=(g_error_norm[0]-g_error_norm[1])/(g_error_norm[0]+offset2);sstr="SOFT";tissue_id=1;}
-                    alpha += 0.15;
-                    if (alpha > 1.0){alpha = 1.0;}
-                    float force_err=loadcell_offset-g_thresh_force[tissue_id];
-                    integral_err = integral_err + force_err;
-                    float current_time = mytimer.read_us()/1000.0;
-                    float dt = 39.0; //Change to a real approach later
-                    float kp = 10.0/0.1e6;
-                    float ki = 10.0/0.1e8;
-                    if (tissue_id == 0){kp=10.0/0.1e6;}
-                    if (tissue_id == 1){kp=100.0/0.1e6;}
-                    // Collaborative Mode
-                    //g_command_corrected=(1-alpha)*potread+alpha*(kp*force_err+ki*integral_err*dt+angle);
-                    // Fully Autonomous Mode
-                    //g_command_corrected=(kp*force_err+angle);
-                    // Fully Manual Mode
-                    g_command_corrected = potread;
-                }else{
-                    g_command_corrected=potread;
-                }
-                
-                //std::vector<int> data_in=<angle, angledot, angledotdot, loadcell, potread>
-
-                if (!calibrateDone){
-                    g_command_corrected = 2800;
-                }
-                //printf("Data:,%6.3f,%6.3f,%3.4f,%6.3f\n",(float(g_slavePositionFirstTouch)-angle),forceInNewtons,float(g_slavePositionFirstTouch),forceInNewtons);
-                printf("Data:,%6.3f,%6.3f,%6.3f,%6.3f,%6.3f\n",mytimer.read_us()/1000.0,forceInNewtons,(float(g_slavePositionFirstTouch)-angle),angledot,angledotdot);
-                
-                
-                //printf("Data:,%6.3f,%6.3f,%3.4f,%d\n",mytimer.read_us()/1000.0,g_loadCellZero,forceInNewtons,adc.read());
-                
-                
-            #endif
-            
-            //printf("%s",recent_pos.get_string().c_str());
-//            printf("<%d,%d,%d,%d,%d,%d,%d>  ",tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos,
-//                                              tempSpindleData.myServoData[LEFT_SERVO_INDEX].force,
-//                                              tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos,
-//                                              tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force,
-//                                              tempSpindleData.time,
-//                                              tempSpindleData.direction,
-//                                              tempSpindleData.cycle);
-//            printf("    %dus", worst_latency);  
-//            worst_latency=0;
-//            printf("    %0.0fbps\n", bits_received*1000.0/AuxSerialTimer.read_ms());
-//            bits_received=0;
+            printf("<%d,%d,%d,%d,%d,%d,%d>  ",tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos,
+                                              tempSpindleData.myServoData[LEFT_SERVO_INDEX].force,
+                                              tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos,
+                                              tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force,
+                                              tempSpindleData.time,
+                                              tempSpindleData.direction,
+                                              tempSpindleData.cycle);
+            printf("    %dus\n", worst_latency);
+            worst_latency=0;
             AuxSerialTimer.reset();
         }