most functionality to splashdwon, find neutral and start mission. short timeouts still in code for testing, will adjust to go directly to sit_idle after splashdown

Dependencies:   mbed MODSERIAL FATFileSystem

Revision:
29:6c030ac0c362
Parent:
28:16c83a2fdefa
--- a/StateMachine/StateMachine.cpp	Fri Dec 01 22:43:14 2017 +0000
+++ b/StateMachine/StateMachine.cpp	Sat Dec 02 20:36:29 2017 +0000
@@ -51,19 +51,18 @@
     // finite state machine ... each state has at least one exit criteria
     switch (_state) {
     case SIT_IDLE :
-    case KEYBOARD:
+    case KEYBOARD :
         // there actually is no timeout for SIT_IDLE, but this enables some one-shot actions
         if (!_isTimeoutRunning) {
+            pc().printf("\r\n\nstate: SIT_IDLE\r\n");
+            _isTimeoutRunning = true; // reset FSM one-shot actions
+            _isSubStateTimerRunning = false; //reset sub FSM one-shot actions
+ 
             showMenu();
-            pc().printf("\r\n\nstate: SIT_IDLE\r\n");
-            _isTimeoutRunning = true; 
- 
-            // what is active?
+
+            // what needs to be started?
             bce().pause();
             batt().pause();
-            
-            //reset sub FSM
-            _isSubStateTimerRunning = false;
         }
         
         // how exit?
@@ -74,9 +73,9 @@
         // start local state timer and init any other one-shot actions
         if (!_isTimeoutRunning) {
             pc().printf("\r\n\nstate: EMERGENCY_CLIMB\r\n");
+            _isTimeoutRunning = true; // reset FSM one-shot actions 
             timer.reset(); // timer goes back to zero
             timer.start(); // background timer starts running
-            _isTimeoutRunning = true; 
             
             // what needs to be started?
             bce().unpause();
@@ -91,13 +90,11 @@
         if (timer > _timeout) {
             pc().printf("EC: timed out\r\n");
             _state = FLOAT_BROADCAST;
-            timer.reset();
             _isTimeoutRunning = false;
         }
-        else if (depthLoop().getPosition() < 2.0) { //if the depth is greater than 0.2 feet, go to float broadcast
-            pc().printf("EC: depth: %3.1f, cmd: 0.5 [%0.1f sec]\r",depthLoop().getPosition(), timer.read());
+        else if (depthLoop().getPosition() < 2.0) { //in case nose is vertical at surface, the depth sensor will be < 2ft
+            pc().printf("EC: depth: %3.1f, cmd: 0.5 [%0.1f sec]\r", depthLoop().getPosition(), timer.read());
             _state = FLOAT_BROADCAST;
-            timer.reset();
             _isTimeoutRunning = false;
         }
         break;
@@ -106,15 +103,15 @@
         // start local state timer and init any other one-shot actions
         if (!_isTimeoutRunning) {
             pc().printf("\r\n\nstate: FIND_NEUTRAL\n\r");
+            _isTimeoutRunning = true; // reset FSM one-shot actions
             timer.reset(); // timer goes back to zero
             timer.start(); // background timer starts running
-            _isTimeoutRunning = true;
             
             // what needs to be started?
             bce().unpause();
             batt().unpause();
-            bce().setPosition_mm(_bceFloatPosition);
-            batt().setPosition_mm(_neutral_batt_pos_mm);    //set battery to close-to-neutral setting from config file 
+            bce().setPosition_mm(_bceFloatPosition);     //set bce to float to start find_neutral actions
+            batt().setPosition_mm(_neutral_batt_pos_mm); //set battery to the current neutral setting
             
             //first iteration goes into Neutral Finding Sub-FSM 
             //set the first state of the FSM, and start the sub-FSM
@@ -128,11 +125,11 @@
             runNeutralStateMachine();                  
         }
  
-        // how exit? (exit with the timer, if timer still running continue processing sub FSM)
+        // how exit?
+        //timeout elapsed
         if (timer > _timeout) {
             pc().printf("FN: timed out [time: %0.1f sec]\r\n", timer.read());
-            _state = EMERGENCY_CLIMB;         //new behavior (if this times out it emergency surfaces)
-            timer.reset();
+            _state = EMERGENCY_CLIMB;
             _isTimeoutRunning = false;
             
             //record this to the NEUTRAL sub-FSM tracker
@@ -140,22 +137,21 @@
             _substate_array_counter++;
         }
         
-        //what is active? (neutral finding sub-function runs until completion)        
-        //check if substate returned exit state, if so stop running the sub-FSM
+        //check if sub-fsm returned exit state
         else if (runNeutralStateMachine() == NEUTRAL_EXIT) { 
-            //if successful, FIND_NEUTRAL then goes to RISE
             pc().printf("*************************************** FIND_NEUTRAL sequence complete.  Rising.\n\n\r");
             _state = RISE;
+            _isTimeoutRunning = false;
         }
-        break;   
+        break;
         
     case DIVE :
         // start local state timer and init any other one-shot actions
         if (!_isTimeoutRunning) {
             pc().printf("\r\n\nstate: DIVE\r\n");
+            _isTimeoutRunning = true; // reset FSM one-shot actions
             timer.reset(); // timer goes back to zero
             timer.start(); // background timer starts running
-            _isTimeoutRunning = true; 
             
             // what needs to be started?
             bce().unpause();
@@ -174,14 +170,12 @@
         // how exit?
         if (timer > _timeout) {
             pc().printf("DIVE: timed out\n\n\r");
-            _state = RISE; //new behavior 11/17/2017
-            timer.reset();
+            _state = RISE;
             _isTimeoutRunning = false;
         }
-        else if (depthLoop().getPosition() > depthLoop().getCommand()) {
+        else if (depthLoop().getPosition() > depthLoop().getCommand() - 0.5) { 
             pc().printf("DIVE: depth: %3.1f, cmd: %3.1f\r\n", depthLoop().getPosition(), depthLoop().getCommand());
             _state = RISE;
-            timer.reset();
             _isTimeoutRunning = false;
         }
  
@@ -190,7 +184,8 @@
         bce().setPosition_mm(depthLoop().getOutput());
         batt().setPosition_mm(pitchLoop().getOutput());
         
-        if (depthLoop().getPosition() > _max_recorded_depth_dive) {  //debug
+        // if surpassed previously recorded max depth
+        if (depthLoop().getPosition() > _max_recorded_depth_dive) {
             _max_recorded_depth_dive = depthLoop().getPosition();    //new max depth recorded
         }
         break;
@@ -199,18 +194,18 @@
         // start local state timer and init any other one-shot actions
         if (!_isTimeoutRunning) {
             pc().printf("\r\n\nstate: RISE\r\n");
+            _isTimeoutRunning = true; // reset FSM one-shot actions
             timer.reset(); // timer goes back to zero
             timer.start(); // background timer starts running
-            _isTimeoutRunning = true; 
             
             // what needs to be started?
             bce().unpause();
             batt().unpause();
  
             // what are the commands?
-            depthLoop().setCommand(-1.0);           //make sure to get towards the surface (saw issues at LASR pool)
+            depthLoop().setCommand(0.0); // depth command is the surface at 0ft
             pitchLoop().setCommand(-_pitchCommand);
-            pc().printf("RISE: depth cmd: 0.0\r\n");
+            pc().printf("RISE: depth cmd: %3.1f\r\n",depthLoop().getCommand());
             pc().printf("RISE: pitch cmd: %3.1f\r\n",pitchLoop().getCommand());
         }
  
@@ -218,29 +213,27 @@
         if (timer > _timeout) {
             pc().printf("RISE: timed out\r\n");
             _state = EMERGENCY_CLIMB;
-            timer.reset();
             _isTimeoutRunning = false;
         }
-        else if (depthLoop().getPosition() < 0.5) {    //removed depthLoop().getCommand()
+        else if (depthLoop().getPosition() < depthLoop().getCommand() + 0.5) { // including offset for low momentum approaches
             pc().printf("RISE: depth: %3.1f, cmd: %3.1f\r\n", depthLoop().getPosition(), depthLoop().getCommand());
             _state = FLOAT_BROADCAST;
-            timer.reset();
             _isTimeoutRunning = false;
         }
  
         // what is active?
         pc().printf("RISE: bce pos: %3.1f mm, batt pos: %3.1f mm (depthLoop POS: %3.1f ft) [%0.1f sec]\r", bce().getPosition_mm(), batt().getPosition_mm(), depthLoop().getPosition(), timer.read());
-        bce().setPosition_mm(depthLoop().getOutput());  //constantly checking the Outer Loop output to move the motors
-        batt().setPosition_mm(pitchLoop().getOutput()); 
+        bce().setPosition_mm(depthLoop().getOutput());  //tie the outer loop controller to the inner loop linear actuator controller
+        batt().setPosition_mm(pitchLoop().getOutput()); //tie the outer loop controller to the inner loop linear actuator controller
         break;  
     
     case FLOAT_LEVEL :
         // start local state timer and init any other one-shot actions
         if (!_isTimeoutRunning) {
             pc().printf("\r\n\nstate: FLOAT_LEVEL\r\n");
+            _isTimeoutRunning = true; // reset FSM one-shot actions
             timer.reset(); // timer goes back to zero
             timer.start(); // background timer starts running
-            _isTimeoutRunning = true; 
             
             // what needs to be started?
             bce().unpause();
@@ -255,28 +248,26 @@
         if (timer > _timeout) {
             pc().printf("FL: timed out\r\n");
             _state = FLOAT_BROADCAST;
-            timer.reset();
             _isTimeoutRunning = false;
         }
-        else if (fabs(imu().getPitch() - pitchLoop().getCommand()) < fabs(_pitchTolerance)) {         //current tolerance is 5 degrees
-            pc().printf("FL: pitch: %3.1f mm, set pos: %3.1f mm, deadband: %3.1f mm\r\n",imu().getPitch(), pitchLoop().getCommand(), _pitchTolerance);
+        else if (fabs(pitchLoop().getPosition() - pitchLoop().getCommand()) < fabs(_pitchTolerance)) {
+            pc().printf("FL: pitch: %3.1f mm, set pos: %3.1f mm, tolerance: %3.1f mm\r\n",pitchLoop().getPosition(), pitchLoop().getCommand(), _pitchTolerance);
             _state = FLOAT_BROADCAST;
-            timer.reset();
             _isTimeoutRunning = false;
         }
         
         // what is active?
         pc().printf("FL: pitchLoop output: %3.1f, batt pos: %3.1f, piston pos: %3.1f [%0.1f sec]\r", pitchLoop().getOutput(), batt().getPosition_mm(), bce().getPosition_mm(), timer.read());
-        batt().setPosition_mm(pitchLoop().getOutput());
+        batt().setPosition_mm(pitchLoop().getOutput()); //tie the outer loop controller to the inner loop linear actuator controller
         break;
     
     case FLOAT_BROADCAST :
         // start local state timer and init any other one-shot actions
         if (!_isTimeoutRunning) {
             pc().printf("\r\n\nstate: FLOAT_BROADCAST\r\n");
+            _isTimeoutRunning = true; 
             timer.reset(); // timer goes back to zero
             timer.start(); // background timer starts running
-            _isTimeoutRunning = true; 
             
             // what needs to be started?
             bce().unpause();
@@ -291,14 +282,12 @@
         if (timer > _timeout) {
             pc().printf("FB: timed out\r\n");
             _state = SIT_IDLE;
-            timer.reset();
             _isTimeoutRunning = false;
         }
         else if ( (fabs(bce().getPosition_mm() - bce().getSetPosition_mm()) < bce().getDeadband()) and
                   (fabs(batt().getPosition_mm() - batt().getSetPosition_mm()) < batt().getDeadband()) ) {
-            pc().printf("FB: position: %3.1f mm, set pos: %3.1f mm, deadband: %3.1f mm\r\n",bce().getPosition_mm(), bce().getSetPosition_mm(), bce().getDeadband());
+            pc().printf("FB: position: %3.1f mm, set pos: %3.1f mm, deadband: %3.1f mm\r\n", bce().getPosition_mm(), bce().getSetPosition_mm(), bce().getDeadband());
             _state = SIT_IDLE;
-            timer.reset();
             _isTimeoutRunning = false;
         }
         
@@ -331,21 +320,19 @@
         // how exit?
         if (timer > _timeout) {
             pc().printf("\n\n\rMULTI-DIVE: timed out [time: %0.1f]\n\n\r", timer.read());
-            _state = MULTI_RISE; //new behavior 11/17/2017
-            timer.reset();
+            _state = MULTI_RISE;
             _isTimeoutRunning = false;
         }
-        else if (depthLoop().getPosition() > depthLoop().getCommand()) {
+        else if (depthLoop().getPosition() > depthLoop().getCommand() - 0.5) {
             pc().printf("MULTI-DIVE: depth: %3.1f, cmd: %3.1f\r\n", depthLoop().getPosition(), depthLoop().getCommand());
             _state = MULTI_RISE;
-            timer.reset();
             _isTimeoutRunning = false;
         }
         
         // what is active?
         pc().printf("MULTI-DIVE: bce pos: %3.1f mm, batt pos: %3.1f mm (depthLoop POS: %3.1f ft) [%0.1f sec]\r", bce().getPosition_mm(), batt().getPosition_mm(), depthLoop().getPosition(), timer.read());
-        bce().setPosition_mm(depthLoop().getOutput());
-        batt().setPosition_mm(pitchLoop().getOutput());
+        bce().setPosition_mm(depthLoop().getOutput());  //tie the outer loop controller to the inner loop linear actuator controller
+        batt().setPosition_mm(pitchLoop().getOutput()); //tie the outer loop controller to the inner loop linear actuator controller
         break;
     
     case MULTI_RISE :
@@ -367,8 +354,8 @@
             //retrieve just pitch command from struct
             float sequence_pitchCommand = currentStateStruct.pitch;
  
-            // what are the commands? (send back to 0.5 feet, not surface) // 11/21/2017
-            depthLoop().setCommand(0.5);
+            // what are the commands?
+            depthLoop().setCommand(0.0);
             pitchLoop().setCommand(-sequence_pitchCommand);            
             pc().printf("MULTI-RISE: depth cmd: 0.0 ft, pitch cmd: %3.1f deg\r\n",depthLoop().getCommand(), pitchLoop().getCommand());
         }
@@ -377,17 +364,14 @@
         if (timer > _timeout) {
             pc().printf("MULTI-RISE: timed out [time: %0.1f]\n\n\r", timer.read());
             _state = EMERGENCY_CLIMB;
-            timer.reset();
             _isTimeoutRunning = false;
-            
+
             //reset multi-dive sequence to start
             _multi_dive_counter = 0;
         }
-        else if (depthLoop().getPosition() < 0.5) { // depth is less than 0.5 (zero is surface level)
+        else if (depthLoop().getPosition() < depthLoop().getCommand() + 0.5) {
             pc().printf("MULTI-RISE: depth: %3.1f, cmd: %3.1f\r\n", depthLoop().getPosition(), depthLoop().getCommand());
-            
-            //going to next state            
-            _isTimeoutRunning = false;
+            _isTimeoutRunning = false; //going to one-shot actions next time
             
             //successful dive-rise sequence CONTINUES the multi-dive sequence
             _multi_dive_counter++;
@@ -399,7 +383,7 @@
             //CHECK BEFORE ANYTHING ELSE that you have reached the "exit" state (Float_Level)
             if (currentStateStruct.state == FLOAT_LEVEL) {
                 _state = FLOAT_BROADCAST;
-                return;
+                return; // Dan 2017-12-02: why is this return?  More likely needs to be break; instead.
             }
             
             else 
@@ -410,8 +394,8 @@
         
         // what is active?
         pc().printf("MULTI-RISE: bce pos: %3.1f mm, batt pos: %3.1f mm (depthLoop POS: %3.1f ft) [%0.1f sec]\r", bce().getPosition_mm(), batt().getPosition_mm(), depthLoop().getPosition(), timer.read());
-        bce().setPosition_mm(depthLoop().getOutput());  //constantly checking the Outer Loop output to move the motors
-        batt().setPosition_mm(pitchLoop().getOutput()); 
+        bce().setPosition_mm(depthLoop().getOutput());  //tie the outer loop controller to the inner loop linear actuator controller
+        batt().setPosition_mm(pitchLoop().getOutput()); //tie the outer loop controller to the inner loop linear actuator controller
         break; 
     
     default :
@@ -423,7 +407,6 @@
     if (_previous_state != _state) {
         _state_array[_state_array_counter] = _state;  //save to state array
         _state_array_counter++;
-        
         _previous_state = _state;
     }
 }
@@ -460,97 +443,78 @@
 int StateMachine::runNeutralStateMachine() {                
     switch (_substate) {
         case NEUTRAL_SINKING :
-            //start the 10 second timer
+            //start the timer and do any other one-shot actions
             if (!_isSubStateTimerRunning) {                
+                _isSubStateTimerRunning = true;    //reset the one-shot action entry
+
                 _neutral_timer = timer.read() + 5; //record the time when this block is first entered and add 5 seconds
-                
                 pc().printf("\r\n\nNEUTRAL_SINKING: Next retraction at %0.1f sec [current time: %0.1f] (pitch: %0.1f)\n\r", _neutral_timer, timer.read(), pitchLoop().getPosition());
                 
                 // what are the commands?
-                //move piston at start of sequence (retract 2.5 mm)
-                bce().setPosition_mm(bce().getSetPosition_mm() - 2.5);  //no depth command
-                
-                // it's okay to run the pitch outer loop now since we've already found pitch level in the previous state
-                pitchLoop().setCommand(0.0);
-                
-                pc().printf("NEUTRAL_SINKING: Retracting piston 5 mm [BCE CMD : %0.1f] [pitch cmd: %0.1f] (pitch: %0.1f)\n\r", bce().getSetPosition_mm(), pitchLoop().getCommand(), pitchLoop().getPosition());
-                
-                _isSubStateTimerRunning = true;    //disable this block after one iteration
+                bce().setPosition_mm(bce().getSetPosition_mm() - 2.5); //move piston at start of sequence
+                pitchLoop().setCommand(0.0); // run pitch outer loop controller
+                pc().printf("NEUTRAL_SINKING: Retracting piston [BCE CMD : %0.1f] [pitch cmd: %0.1f] (pitch: %0.1f)\n\r", bce().getSetPosition_mm(), pitchLoop().getCommand(), pitchLoop().getPosition());
             }
  
             // how exit?
-            //once reached the travel limit, no need to keep trying, so exit
-            if (bce().getPosition_mm() <= 0) {
-                pc().printf("\n\rDEBUG: BCE current position is %0.1f mm (NEXT SUBSTATE NEUTRAL EXIT)\n\r", bce().getPosition_mm());
+            if (bce().getPosition_mm() <= 0) { //reached the bce travel limit
+                pc().printf("\r\nNEUTRAL_SINKING: BCE is at travel limit [actual %0.1f mm]\r\n", bce().getPosition_mm());
                 _substate = NEUTRAL_EXIT;
-                _isSubStateTimerRunning = false; // reset the sub state timer
-            }         
-            //once deeper than the commanded setpoint...
-            else if (depthLoop().getPosition() > _depthCommand) {
-                _substate = NEUTRAL_SLOWLY_RISE; // next state
+                _isSubStateTimerRunning = false; //reset the sub state timer
+            }
+            else if (depthLoop().getPosition() > _depthCommand) { //deeper than the commanded setpoint
+                pc().printf("\r\n\nNEUTRAL_SINKING: Depth exceeded < %3.1f ft [time: %0.1f]\r\n", depthLoop().getCommand(), timer.read());
+                _substate = NEUTRAL_SLOWLY_RISE;
                 _isSubStateTimerRunning = false; //reset the sub state timer
             }
  
             // what is active?
-            //once the 10 second timer is complete, reset the timeout so the state one-shot entry will move the setpoint
             if (timer.read() >= _neutral_timer) {
-                pc().printf("\r\n\n NEUTRAL_SINKING TIMER COMPLETE! Retracting BCE piston 5 mm [current time: %0.1f]\r\n", timer.read());
-                
+                pc().printf("\r\n\n NEUTRAL_SINKING timer complete! [current time: %0.1f]\r\n", timer.read());
                 _isSubStateTimerRunning = false; // reset the sub state timer to do one-shot actions again
             }
-            
-            // what is active?
-            batt().setPosition_mm(pitchLoop().getOutput()); // pitch outer loop is running
+            batt().setPosition_mm(pitchLoop().getOutput()); //tie the outer loop controller to the inner loop linear actuator controller
             break;
             
         case NEUTRAL_SLOWLY_RISE:
             if (!_isSubStateTimerRunning) {                                
+                _isSubStateTimerRunning = true;    //reset the one-shot action entry
+                
                 _neutral_timer = timer.read()+ 5; //record the time when this block is first entered and add 5 seconds
-                
                 pc().printf("\r\n\nNEUTRAL_SLOWLY_RISE: Next extension at %0.1f sec) [current time: %0.1f]\r\n",_neutral_timer,timer.read());
                 
                 // what are the commands?
-                //move piston at start of sequence (extend)
-                bce().setPosition_mm(bce().getSetPosition_mm() + 2);  //no depth command
-                
-                // it's okay to run the pitch outer loop now since we've already found pitch level in the previous state
-                pitchLoop().setCommand(0.0);
-                
+                bce().setPosition_mm(bce().getSetPosition_mm() + 2); //move piston at start of sequence (extend)
+                pitchLoop().setCommand(0.0);  // run pitch outer loop controller
                 pc().printf("NEUTRAL_SLOWLY_RISE: Extending BCE piston 5 mm [BCE CMD : %0.1f] [pitch cmd: %0.1f]\n\r", bce().getSetPosition_mm(), pitchLoop().getCommand());
-
-                _isSubStateTimerRunning = true;    //disable this block after one iteration
             }
             
             // how exit?
-            //once at full travel limit (setPosition) and haven't yet risen, time to give up and exit
-            if (bce().getSetPosition_mm() >= bce().getTravelLimit()) {
+            if (bce().getSetPosition_mm() >= bce().getTravelLimit()) { //once at full travel limit
+                pc().printf("\r\nNEUTRAL_SLOWLY_RISE: BCE is at travel limit [actual %0.1f mm]\r\n", bce().getPosition_mm());
                 _substate = NEUTRAL_EXIT;     
                 _isSubStateTimerRunning = false; // reset the sub state timer
             }
-            //depth rate or sink rate < 0 ft/s, go to the next substate the next iteration
-            else if (depthLoop().getVelocity() < 0) { //less than zero ft/s
+            else if (depthLoop().getVelocity() < 0) { //less than zero ft/s means we're rising
                 pc().printf("\r\n\nNEUTRAL_SLOWLY_RISE: Sink Rate < 0 ft/s [time: %0.1f]\r\n", timer.read());
                 _substate = NEUTRAL_CHECK_PITCH;
                 _isSubStateTimerRunning = false; // reset the sub state timer
             }
             
             // what is active?
-            //once 5 second timer complete, reset the timeout so the state one-shot entry will move the setpoint
             if (timer.read() >= _neutral_timer) {
                 pc().printf("\r\n\n NEUTRAL_SLOWLY_RISE TIMER COMPLETE! Extending 1 mm [timer: %0.1f]\r\n", timer.read());
-   
                 _isSubStateTimerRunning = false; // reset the sub state timer to do one-shot actions again
             }
-                        
-            // what is active?
-            batt().setPosition_mm(pitchLoop().getOutput()); // pitch outer loop is running
+            batt().setPosition_mm(pitchLoop().getOutput()); //tie the outer loop controller to the inner loop linear actuator controller
             break;   
                 
         case NEUTRAL_CHECK_PITCH : // fall thru to next state is desired
         case NEUTRAL_FIRST_PITCH : 
             // start local state timer and init any other one-shot actions
-            
             if (!_isSubStateTimerRunning) {                    
+                _isSubStateTimerRunning = true;    //reset the one-shot action entry
+                
                 _neutral_timer = timer.read() + 10; // record time when this block is entered and add several seconds
                 pc().printf("\r\nNEUTRAL_CHECK_PITCH: Next move in %0.1f sec \r\n",_neutral_timer - timer.read());
                 
@@ -563,49 +527,46 @@
                     batt().setPosition_mm(batt().getSetPosition_mm() - 0.5); // move battery aft (using setpoint from linear actuator)
                     pc().printf("\n\rNeutral Check Pitch: moving battery AFT in 1mm increments\n\n\r");
                 }
-
-                _isSubStateTimerRunning = true;    //disable this block after one iteration
             }
  
             // how exit?            
             //pitch angle and pitch rate within small tolerance
-            //benchtop tests confirm angle needs to be around 2 degrees
             if ((fabs(pitchLoop().getPosition()) < 2.0) and (fabs(pitchLoop().getVelocity()) < 5.0)) { 
-                pc().printf("Debug: Found Level (NEUTRAL_CHECK_PITCH or NEUTRAL_FIRST_PITCH)\n\r");    //debug
-                // found level, but don't need to save anything this time
+                pc().printf("NEUTRAL_PITCH Found Level!\n\r");    //debug
                 
-                if (depthLoop().getPosition() > _max_recorded_depth_neutral) {  //debug
+                if (depthLoop().getPosition() > _max_recorded_depth_neutral) {
                     _max_recorded_depth_neutral = depthLoop().getPosition();    //new max depth recorded
                 }
                 
+                // found level, but don't save this time
                 if (_substate == NEUTRAL_FIRST_PITCH) {
-                    _substate = NEUTRAL_SINKING; // next state starts the sinking
+                    pc().printf("NEUTRAL_FIRST_PITCH completed\n\r");
+                    _substate = NEUTRAL_SINKING;
                     _isSubStateTimerRunning = false; // reset the sub state timer to do one-shot actions again
 
                     // save this neutral (not in file) for pitch
                     pitchLoop().setOutputOffset(batt().getPosition_mm());
-                    
-                    pc().printf("substate: NEUTRAL_FIRST_PITCH (next substate: NEUTRAL_SINKING)\n\r");
                 }
                 
                 // found level and at depth too, so save it all now               
                 else if (_substate == NEUTRAL_CHECK_PITCH) {
+                    pc().printf("NEUTRAL_CHECK_PITCH completed\n\r");
+                    _substate = NEUTRAL_EXIT;
+                    _isSubStateTimerRunning = false; // reset the sub state timer to do one-shot actions again
+
                     //save positions locally
+                    _neutral_bce_pos_mm = bce().getPosition_mm();
                     _neutral_batt_pos_mm = batt().getPosition_mm();
-                    _neutral_bce_pos_mm = bce().getPosition_mm();
                     
                     //set the neutral positions in each outer loop
                     depthLoop().setOutputOffset(_neutral_bce_pos_mm);
                     pitchLoop().setOutputOffset(_neutral_batt_pos_mm);
                     
                     // save into the depth.txt and pitch.txt files
+                    configFileIO().saveDepthData(_depth_KP, _depth_KI, _depth_KD, _neutral_bce_pos_mm); //P,I,D, bce zeroOffset
                     configFileIO().savePitchData(_pitch_KP, _pitch_KI, _pitch_KD, _neutral_batt_pos_mm); //P,I,D,batt zeroOffset
-                    configFileIO().saveDepthData(_depth_KP, _depth_KI, _depth_KD, _neutral_bce_pos_mm); //P,I,D, bce zeroOffset
                     
                     pc().printf("\n\rSaving Positions: BCE: %0.1f mm, BATT: %0.1f\n\n\r",_neutral_bce_pos_mm,_neutral_batt_pos_mm);
-                    
-                    _substate = NEUTRAL_EXIT;
-                    _isSubStateTimerRunning = false; // reset the sub state timer to do one-shot actions again
                 }
                 
                 else {