Implement endstops using new motion control
authorJim Morris <morris@wolfman.com>
Fri, 17 Jun 2016 01:30:05 +0000 (18:30 -0700)
committerJim Morris <morris@wolfman.com>
Fri, 17 Jun 2016 01:30:05 +0000 (18:30 -0700)
  this breaks some backwards compatibility
    1. XY can home at the same time but not Z so by default XY homes then Z (on cartesians)
    2. the alpha_max, beta_max and gamma_max must be defined to limit the homing movement for that axis
    3. corexy can now only home each axis one at a time
  delta is not done yet
renamed THEKERNEL->robot to THEROBOT

32 files changed:
src/libs/Kernel.h
src/libs/StepTicker.cpp
src/libs/StepperMotor.h
src/modules/communication/GcodeDispatch.cpp
src/modules/robot/Conveyor.cpp
src/modules/robot/Planner.cpp
src/modules/robot/Planner.h
src/modules/robot/Robot.cpp
src/modules/robot/Robot.h
src/modules/tools/drillingcycles/Drillingcycles.cpp
src/modules/tools/endstops/Endstops.cpp
src/modules/tools/endstops/Endstops.h
src/modules/tools/extruder/Extruder.cpp
src/modules/tools/rotarydeltacalibration/RotaryDeltaCalibration.cpp
src/modules/tools/scaracal/SCARAcal.cpp
src/modules/tools/toolmanager/ToolManager.cpp
src/modules/tools/zprobe/DeltaCalibrationStrategy.cpp
src/modules/tools/zprobe/DeltaGridStrategy.cpp
src/modules/tools/zprobe/ThreePointStrategy.cpp
src/modules/tools/zprobe/ZGridStrategy.cpp
src/modules/tools/zprobe/ZProbe.cpp
src/modules/utils/motordrivercontrol/MotorDriverControl.cpp
src/modules/utils/motordrivercontrol/drivers/TMC26X/TMC26X.cpp
src/modules/utils/panel/PanelScreen.cpp
src/modules/utils/panel/screens/3dprinter/MainMenuScreen.cpp
src/modules/utils/panel/screens/3dprinter/WatchScreen.cpp
src/modules/utils/panel/screens/cnc/ControlScreen.cpp
src/modules/utils/panel/screens/cnc/DirectJogScreen.cpp
src/modules/utils/panel/screens/cnc/MainMenuScreen.cpp
src/modules/utils/panel/screens/cnc/WatchScreen.cpp
src/modules/utils/player/Player.cpp
src/modules/utils/simpleshell/SimpleShell.cpp

index 6ddd6fa..4a2feb7 100644 (file)
@@ -10,6 +10,7 @@
 
 #define THEKERNEL Kernel::instance
 #define THECONVEYOR THEKERNEL->conveyor
+#define THEROBOT THEKERNEL->robot
 
 #include "Module.h"
 #include <array>
index 31f7d8d..54c4406 100644 (file)
@@ -187,11 +187,11 @@ void StepTicker::step_tick (void)
             ++current_block->tick_info[m].step_count;
 
             // step the motor
-            motor[m]->step();
+            bool ismoving= motor[m]->step(); // returns false if the moving flag was set to false externally (probes, endstops etc)
             // we stepped so schedule an unstep
             unstep.set(m);
 
-            if(current_block->tick_info[m].step_count == current_block->tick_info[m].steps_to_move) {
+            if(!ismoving || current_block->tick_info[m].step_count == current_block->tick_info[m].steps_to_move) {
                 // done
                 current_block->tick_info[m].steps_to_move = 0;
                 motor[m]->moving= false; // let motor know it is no longer moving
index c995988..7d8842f 100644 (file)
@@ -16,7 +16,7 @@ class StepperMotor  : public Module {
         ~StepperMotor();
 
         // called from step ticker ISR
-        inline void step() { step_pin.set(1); current_position_steps += (direction?-1:1); }
+        inline bool step() { step_pin.set(1); current_position_steps += (direction?-1:1); return moving; }
         // called from unstep ISR
         inline void unstep() { step_pin.set(0); }
         // called from step ticker ISR
@@ -25,6 +25,7 @@ class StepperMotor  : public Module {
         inline void enable(bool state) { en_pin.set(!state); };
         inline bool is_enabled() const { return !en_pin.get(); };
         inline bool is_moving() const { return moving; };
+        void stop_moving() { moving= false; }
 
         void manual_step(bool dir);
 
index 17eed0c..72cabf2 100644 (file)
@@ -196,7 +196,7 @@ try_again:
                                 }
                             }
                             // makes it handle the parameters as a machine position
-                            THEKERNEL->robot->next_command_is_MCS= true;
+                            THEROBOT->next_command_is_MCS= true;
 
                         }
 
index 02d0d85..546f94d 100644 (file)
@@ -122,7 +122,7 @@ void Conveyor::on_idle(void*)
 bool Conveyor::is_idle() const
 {
     if(queue.is_empty()) {
-        for(auto &a : THEKERNEL->robot->actuators) {
+        for(auto &a : THEROBOT->actuators) {
             if(a->is_moving()) return false;
         }
         return true;
index 77ae7bc..9af7461 100644 (file)
@@ -54,7 +54,7 @@ void Planner::config_load()
 
 
 // Append a block to the queue, compute it's speed factors
-void Planner::append_block( ActuatorCoordinates &actuator_pos, float rate_mm_s, float distance, float unit_vec[] )
+void Planner::append_block( ActuatorCoordinates &actuator_pos, float rate_mm_s, float distance, float *unit_vec)
 {
     float acceleration, junction_deviation;
 
@@ -63,14 +63,14 @@ void Planner::append_block( ActuatorCoordinates &actuator_pos, float rate_mm_s,
 
 
     // Direction bits
-    for (size_t i = 0; i < THEKERNEL->robot->actuators.size(); i++) {
-        int steps = THEKERNEL->robot->actuators[i]->steps_to_target(actuator_pos[i]);
+    for (size_t i = 0; i < THEROBOT->actuators.size(); i++) {
+        int steps = THEROBOT->actuators[i]->steps_to_target(actuator_pos[i]);
 
         block->direction_bits[i] = (steps < 0) ? 1 : 0;
 
         // Update current position
-        THEKERNEL->robot->actuators[i]->last_milestone_steps += steps;
-        THEKERNEL->robot->actuators[i]->last_milestone_mm = actuator_pos[i];
+        THEROBOT->actuators[i]->last_milestone_steps += steps;
+        THEROBOT->actuators[i]->last_milestone_mm = actuator_pos[i];
 
         block->steps[i] = labs(steps);
     }
@@ -87,9 +87,14 @@ void Planner::append_block( ActuatorCoordinates &actuator_pos, float rate_mm_s,
 
     block->acceleration = acceleration; // save in block
 
+    // if it is a SOLO move from extruder, zprobe or endstops we do not use junction deviation
+    if(unit_vec == nullptr) {
+        junction_deviation= 0.0F;
+    }
+
     // Max number of steps, for all axes
     uint32_t steps_event_count = 0;
-    for (size_t s = 0; s < THEKERNEL->robot->actuators.size(); s++) {
+    for (size_t s = 0; s < THEROBOT->actuators.size(); s++) {
         steps_event_count = std::max(steps_event_count, block->steps[s]);
     }
     block->steps_event_count = steps_event_count;
@@ -167,7 +172,11 @@ void Planner::append_block( ActuatorCoordinates &actuator_pos, float rate_mm_s,
     block->recalculate_flag = true;
 
     // Update previous path unit_vector and nominal speed
-    memcpy(this->previous_unit_vec, unit_vec, sizeof(previous_unit_vec)); // previous_unit_vec[] = unit_vec[]
+    if(unit_vec != nullptr) {
+        memcpy(this->previous_unit_vec, unit_vec, sizeof(previous_unit_vec)); // previous_unit_vec[] = unit_vec[]
+    }else{
+        clear_vector_float(this->previous_unit_vec);
+    }
 
     // Math-heavy re-computing of the whole queue to take the new
     this->recalculate();
index 7b1463b..3087b82 100644 (file)
@@ -15,15 +15,15 @@ class Planner
 {
 public:
     Planner();
-    void append_block(ActuatorCoordinates &target, float rate_mm_s, float distance, float unit_vec[] );
     float max_allowable_speed( float acceleration, float target_velocity, float distance);
-    void recalculate();
     float get_acceleration() const { return acceleration; }
     float get_z_acceleration() const { return z_acceleration > 0.0F ? z_acceleration : acceleration; }
 
     friend class Robot; // for acceleration, junction deviation, minimum_planner_speed
 
 private:
+    void append_block(ActuatorCoordinates &target, float rate_mm_s, float distance, float unit_vec[] );
+    void recalculate();
     void config_load();
     float previous_unit_vec[3];
     float acceleration;          // Setting
index 7d4d603..7809775 100644 (file)
@@ -828,7 +828,7 @@ void Robot::reset_position_from_current_actuator_position()
 // Convert target (in machine coordinates) from millimeters to steps, and append this to the planner
 // target is in machine coordinates without the compensation transform, however we save a last_machine_position that includes
 // all transforms and is what we actually convert to actuator positions
-bool Robot::append_milestone(Gcode * gcode, const float target[], float rate_mm_s)
+bool Robot::append_milestone(Gcode *gcode, const float target[], float rate_mm_s)
 {
     float deltas[3];
     float unit_vec[3];
@@ -900,6 +900,58 @@ bool Robot::append_milestone(Gcode * gcode, const float target[], float rate_mm_
     return true;
 }
 
+// Used to plan a single move used by things like endstops when homing, zprobe, extruder retracts etc.
+bool Robot::solo_move(const float *delta, float rate_mm_s)
+{
+    if(THEKERNEL->is_halted()) return false;
+
+    // catch negative or zero feed rates and return the same error as GRBL does
+    if(rate_mm_s <= 0.0F) {
+        return false;
+    }
+
+    // Compute how long this move moves, so we can attach it to the block for later use
+    float millimeters_of_travel = sqrtf( powf( delta[X_AXIS], 2 ) +  powf( delta[Y_AXIS], 2 ) +  powf( delta[Z_AXIS], 2 ) );
+
+    // it is unlikely but we need to protect against divide by zero, so ignore insanely small moves here
+    // as the last milestone won't be updated we do not actually lose any moves as they will be accounted for in the next move
+    if(millimeters_of_travel < 0.00001F) return false;
+
+    // this is the new machine position
+    for (int axis = X_AXIS; axis <= Z_AXIS; axis++) {
+        this->last_machine_position[axis] += delta[axis];
+    }
+
+    // Do not move faster than the configured cartesian limits
+    for (int axis = X_AXIS; axis <= Z_AXIS; axis++) {
+        if ( max_speeds[axis] > 0 ) {
+            float axis_speed = fabsf(delta[axis] / millimeters_of_travel * rate_mm_s);
+
+            if (axis_speed > max_speeds[axis])
+                rate_mm_s *= ( max_speeds[axis] / axis_speed );
+        }
+    }
+
+    // find actuator position given the machine position, use actual adjusted target
+    ActuatorCoordinates actuator_pos;
+    arm_solution->cartesian_to_actuator( this->last_machine_position, actuator_pos );
+
+    float isecs = rate_mm_s / millimeters_of_travel;
+    // check per-actuator speed limits
+    for (size_t actuator = 0; actuator < actuators.size(); actuator++) {
+        float actuator_rate  = fabsf(actuator_pos[actuator] - actuators[actuator]->last_milestone_mm) * isecs;
+        if (actuator_rate > actuators[actuator]->get_max_rate()) {
+            rate_mm_s *= (actuators[actuator]->get_max_rate() / actuator_rate);
+            isecs = rate_mm_s / millimeters_of_travel;
+        }
+    }
+
+    // Append the block to the planner
+    THEKERNEL->planner->append_block(actuator_pos, rate_mm_s, millimeters_of_travel, nullptr);
+
+    return true;
+}
+
 // Append a move to the queue ( cutting it into segments if needed )
 bool Robot::append_line(Gcode *gcode, const float target[], float rate_mm_s )
 {
index 0d19459..383f1df 100644 (file)
@@ -52,6 +52,7 @@ class Robot : public Module {
         std::vector<wcs_t> get_wcs_state() const;
         std::tuple<float, float, float, uint8_t> get_last_probe_position() const { return last_probe_position; }
         void set_last_probe_position(std::tuple<float, float, float, uint8_t> p) { last_probe_position = p; }
+        bool solo_move(const float target[], float rate_mm_s);
 
         BaseSolution* arm_solution;                           // Selected Arm solution ( millimeters to step calculation )
 
index 07446c2..f63837a 100644 (file)
@@ -207,9 +207,9 @@ void Drillingcycles::on_gcode_received(void* argument)
         THEKERNEL->conveyor->wait_for_empty_queue();
         // get actual position from robot
         float pos[3];
-        THEKERNEL->robot->get_axis_position(pos);
+        THEROBOT->get_axis_position(pos);
         // convert to WCS
-        Robot::wcs_t wpos= THEKERNEL->robot->mcs2wcs(pos);
+        Robot::wcs_t wpos= THEROBOT->mcs2wcs(pos);
         // backup Z position as Initial-Z value
         this->initial_z = std::get<X_AXIS>(wpos); // must use the work coordinate position
         // set retract type
@@ -233,7 +233,7 @@ void Drillingcycles::on_gcode_received(void* argument)
     // in cycle
     else if (this->cycle_started) {
         // relative mode not supported for now...
-        if (THEKERNEL->robot->absolute_mode == false) {
+        if (THEROBOT->absolute_mode == false) {
             gcode->stream->printf("Drillingcycles: relative mode not supported.\r\n");
             gcode->stream->printf("Drillingcycles: skip hole...\r\n");
             // exit
index 6903030..889a6e6 100644 (file)
@@ -16,7 +16,6 @@
 #include "libs/StepperMotor.h"
 #include "wait_api.h" // mbed.h lib
 #include "Robot.h"
-#include "Stepper.h"
 #include "Config.h"
 #include "SlowTicker.h"
 #include "Planner.h"
 #define homing_order_checksum            CHECKSUM("homing_order")
 #define move_to_origin_checksum          CHECKSUM("move_to_origin_after_home")
 
-#define STEPPER THEKERNEL->robot->actuators
+#define STEPPER THEROBOT->actuators
 #define STEPS_PER_MM(a) (STEPPER[a]->get_steps_per_mm())
 
 
@@ -125,6 +124,7 @@ Endstops::Endstops()
 {
     this->status = NOT_HOMING;
     home_offset[0] = home_offset[1] = home_offset[2] = 0.0F;
+    debounce.fill(0);
 }
 
 void Endstops::on_module_loaded()
@@ -139,10 +139,10 @@ void Endstops::on_module_loaded()
     register_for_event(ON_GET_PUBLIC_DATA);
     register_for_event(ON_SET_PUBLIC_DATA);
 
-    THEKERNEL->step_ticker->register_acceleration_tick_handler([this]() {acceleration_tick(); });
-
     // Settings
     this->load_config();
+
+    THEKERNEL->slow_ticker->attach(1000, this, &Endstops::read_endstops);
 }
 
 // Get config
@@ -193,6 +193,11 @@ void Endstops::load_config()
     this->homing_position[1]        =  this->home_direction[1] ? THEKERNEL->config->value(beta_min_checksum )->by_default(0)->as_number() : THEKERNEL->config->value(beta_max_checksum )->by_default(200)->as_number();
     this->homing_position[2]        =  this->home_direction[2] ? THEKERNEL->config->value(gamma_min_checksum)->by_default(0)->as_number() : THEKERNEL->config->value(gamma_max_checksum)->by_default(200)->as_number();
 
+    // used to set maximum movement on homing
+    this->alpha_max= THEKERNEL->config->value(alpha_max_checksum)->by_default(500)->as_number();
+    this->beta_max= THEKERNEL->config->value(beta_max_checksum)->by_default(500)->as_number();
+    this->gamma_max= THEKERNEL->config->value(gamma_max_checksum)->by_default(500)->as_number();
+
     this->is_corexy                 =  THEKERNEL->config->value(corexy_homing_checksum)->by_default(false)->as_bool();
     this->is_delta                  =  THEKERNEL->config->value(delta_homing_checksum)->by_default(false)->as_bool();
     this->is_rdelta                 =  THEKERNEL->config->value(rdelta_homing_checksum)->by_default(false)->as_bool();
@@ -225,7 +230,7 @@ void Endstops::load_config()
     this->limit_enable[Y_AXIS] = THEKERNEL->config->value(beta_limit_enable_checksum)->by_default(false)->as_bool();
     this->limit_enable[Z_AXIS] = THEKERNEL->config->value(gamma_limit_enable_checksum)->by_default(false)->as_bool();
 
-    // set to true by default for deltas duwe to trim, false on cartesians
+    // set to true by default for deltas due to trim, false on cartesians
     this->move_to_origin_after_home = THEKERNEL->config->value(move_to_origin_checksum)->by_default(is_delta)->as_bool();
 
     if(this->limit_enable[X_AXIS] || this->limit_enable[Y_AXIS] || this->limit_enable[Z_AXIS]) {
@@ -314,7 +319,7 @@ void Endstops::on_idle(void *argument)
 
 // if limit switches are enabled, then we must move off of the endstop otherwise we won't be able to move
 // checks if triggered and only backs off if triggered
-void Endstops::back_off_home(char axes_to_move)
+void Endstops::back_off_home()
 {
     std::vector<std::pair<char, float>> params;
     this->status = BACK_OFF_HOME;
@@ -327,7 +332,7 @@ void Endstops::back_off_home(char axes_to_move)
     } else {
         // cartesians, concatenate all the moves we need to do into one gcode
         for( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-            if( ((axes_to_move >> c ) & 1) == 0) continue; // only for axes we asked to move
+            if(!axis_to_home[c]) continue; // only for axes we asked to move
 
             // if not triggered no need to move off
             if(this->limit_enable[c] && debounced_get(c + (this->home_direction[c] ? 0 : 3)) ) {
@@ -344,276 +349,162 @@ void Endstops::back_off_home(char axes_to_move)
         char gcode_buf[64];
         append_parameters(gcode_buf, params, sizeof(gcode_buf));
         Gcode gc(gcode_buf, &(StreamOutput::NullStream));
-        THEKERNEL->robot->push_state();
-        THEKERNEL->robot->absolute_mode = false; // needs to be relative mode
-        THEKERNEL->robot->on_gcode_received(&gc); // send to robot directly
+        THEROBOT->push_state();
+        THEROBOT->absolute_mode = false; // needs to be relative mode
+        THEROBOT->on_gcode_received(&gc); // send to robot directly
         // Wait for above to finish
         THEKERNEL->conveyor->wait_for_empty_queue();
-        THEKERNEL->robot->pop_state();
+        THEROBOT->pop_state();
     }
 
     this->status = NOT_HOMING;
 }
 
 // If enabled will move the head to 0,0 after homing, but only if X and Y were set to home
-void Endstops::move_to_origin(char axes_to_move)
+void Endstops::move_to_origin()
 {
-    if( (axes_to_move & 0x03) != 3 ) return; // ignore if X and Y not homing
+    if(!(axis_to_home[X_AXIS] && axis_to_home[Y_AXIS])) return; // ignore if X and Y not homing
 
     // Do we need to check if we are already at 0,0? probably not as the G0 will not do anything if we are
-    // float pos[3]; THEKERNEL->robot->get_axis_position(pos); if(pos[0] == 0 && pos[1] == 0) return;
+    // float pos[3]; THEROBOT->get_axis_position(pos); if(pos[0] == 0 && pos[1] == 0) return;
 
     this->status = MOVE_TO_ORIGIN;
     // Move to center using a regular move, use slower of X and Y fast rate
     float rate = std::min(this->fast_rates[0], this->fast_rates[1]) * 60.0F;
     char buf[32];
     snprintf(buf, sizeof(buf), "G53 G0 X0 Y0 F%1.4f", rate); // must use machine coordinates in case G92 or WCS is in effect
-    THEKERNEL->robot->push_state();
+    THEROBOT->push_state();
     struct SerialMessage message;
     message.message = buf;
     message.stream = &(StreamOutput::NullStream);
     THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message ); // as it is a multi G code command
     // Wait for above to finish
     THEKERNEL->conveyor->wait_for_empty_queue();
-    THEKERNEL->robot->pop_state();
+    THEROBOT->pop_state();
     this->status = NOT_HOMING;
 }
 
-bool Endstops::wait_for_homed(char axes_to_move)
+// Called every millisecond in an ISR
+uint32_t Endstops::read_endstops(uint32_t dummy)
 {
-    bool running = true;
-    unsigned int debounce[3] = {0, 0, 0};
-    while (running) {
-        running = false;
-        THEKERNEL->call_event(ON_IDLE);
-
-        // check if on_halt (eg kill)
-        if(THEKERNEL->is_halted()) return false;
+    if(this->status >= NOT_HOMING) return 0; // not doing anything we need to monitor for
 
-        for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-            if ( ( axes_to_move >> c ) & 1 ) {
-                if ( this->pins[c + (this->home_direction[c] ? 0 : 3)].get() ) {
-                    if ( debounce[c] < debounce_count ) {
-                        debounce[c]++;
-                        running = true;
-                    } else if ( STEPPER[c]->is_moving() ) {
-                        STEPPER[c]->move(0, 0);
-                        axes_to_move &= ~(1 << c); // no need to check it again
+    if(!is_corexy) {
+        // check each axis
+        for ( int m = X_AXIS; m <= Z_AXIS; m++ ) {
+            if(STEPPER[m]->is_moving()) {
+                // if it is moving then we check the associated endstop, and debounce it
+                if(this->pins[m + (this->home_direction[m] ? 0 : 3)].get()) {
+                    if(debounce[m] < debounce_count) {
+                        debounce[m]++;
+                    } else {
+                        // we signal the motor to stop, which will preempt any moves on that axis
+                        STEPPER[m]->stop_moving();
                     }
+
                 } else {
                     // The endstop was not hit yet
-                    running = true;
-                    debounce[c] = 0;
+                    debounce[m] = 0;
                 }
             }
         }
-    }
-    return true;
-}
-
-void Endstops::do_homing_cartesian(char axes_to_move)
-{
-    // check if on_halt (eg kill)
-    if(THEKERNEL->is_halted()) return;
 
-    // this homing works for cartesian and delta printers
-    // Start moving the axes to the origin
-    this->status = MOVING_TO_ENDSTOP_FAST;
-    for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-        if ( ( axes_to_move >> c) & 1 ) {
-            this->feed_rate[c] = this->fast_rates[c];
-            STEPPER[c]->move(this->home_direction[c], 10000000, 0);
-        }
-    }
-
-    // Wait for all axes to have homed
-    if(!this->wait_for_homed(axes_to_move)) return;
-
-    // Move back a small distance
-    this->status = MOVING_BACK;
-    bool inverted_dir;
-    for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-        if ( ( axes_to_move >> c ) & 1 ) {
-            inverted_dir = !this->home_direction[c];
-            this->feed_rate[c] = this->slow_rates[c];
-            STEPPER[c]->move(inverted_dir, this->retract_mm[c]*STEPS_PER_MM(c), 0);
-        }
-    }
+    } else {
+        // corexy is different as the actuators are not directly related to the XY axis
+        // so we check the axis that is currently homing then stop all motors
+        for ( int m = X_AXIS; m <= Z_AXIS; m++ ) {
+            if(axis_to_home[m]) {
+                if(this->pins[m + (this->home_direction[m] ? 0 : 3)].get()) {
+                    if(debounce[m] < debounce_count) {
+                        debounce[m]++;
+                    } else {
+                        // we signal all the motors to stop, as on corexy X and Y motors will move for X and Y axis homing and we only hom eone axis at a time
+                        STEPPER[X_AXIS]->stop_moving();
+                        STEPPER[Y_AXIS]->stop_moving();
+                        STEPPER[Z_AXIS]->stop_moving();
+                    }
 
-    // Wait for moves to be done
-    for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-        if (  ( axes_to_move >> c ) & 1 ) {
-            while ( STEPPER[c]->is_moving() ) {
-                THEKERNEL->call_event(ON_IDLE);
-                if(THEKERNEL->is_halted()) return;
+                } else {
+                    // The endstop was not hit yet
+                    debounce[m] = 0;
+                }
             }
         }
     }
 
-    // Start moving the axes to the origin slowly
-    this->status = MOVING_TO_ENDSTOP_SLOW;
-    for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-        if ( ( axes_to_move >> c ) & 1 ) {
-            this->feed_rate[c] = this->slow_rates[c];
-            STEPPER[c]->move(this->home_direction[c], 10000000, 0);
-        }
-    }
-
-    // Wait for all axes to have homed
-    if(!this->wait_for_homed(axes_to_move)) return;
-}
-
-bool Endstops::wait_for_homed_corexy(int axis)
-{
-    bool running = true;
-    unsigned int debounce[3] = {0, 0, 0};
-    while (running) {
-        running = false;
-        THEKERNEL->call_event(ON_IDLE);
-
-        // check if on_halt (eg kill)
-        if(THEKERNEL->is_halted()) return false;
-
-        if ( this->pins[axis + (this->home_direction[axis] ? 0 : 3)].get() ) {
-            if ( debounce[axis] < debounce_count ) {
-                debounce[axis] ++;
-                running = true;
-            } else {
-                // turn both off if running
-                if (STEPPER[X_AXIS]->is_moving()) STEPPER[X_AXIS]->move(0, 0);
-                if (STEPPER[Y_AXIS]->is_moving()) STEPPER[Y_AXIS]->move(0, 0);
-            }
-        } else {
-            // The endstop was not hit yet
-            running = true;
-            debounce[axis] = 0;
-        }
-    }
-    return true;
+    return 0;
 }
 
-void Endstops::corexy_home(int home_axis, bool dirx, bool diry, float fast_rate, float slow_rate, unsigned int retract_steps)
+void Endstops::home()
 {
-    // check if on_halt (eg kill)
-    if(THEKERNEL->is_halted()) return;
+    // reset debounce counts
+    debounce.fill(0);
 
+    // Start moving the axes to the origin
     this->status = MOVING_TO_ENDSTOP_FAST;
-    this->feed_rate[X_AXIS] = fast_rate;
-    STEPPER[X_AXIS]->move(dirx, 10000000, 0);
-    this->feed_rate[Y_AXIS] = fast_rate;
-    STEPPER[Y_AXIS]->move(diry, 10000000, 0);
 
-    // wait for primary axis
-    if(!this->wait_for_homed_corexy(home_axis)) return;
-
-    // Move back a small distance
+    if(axis_to_home[X_AXIS] && axis_to_home[Y_AXIS]) {
+        // Home XY first so as not to slow them down by homing Z at the same time
+        float delta[3] {alpha_max, beta_max, 0};
+        if(!this->home_direction[X_AXIS]) delta[X_AXIS]= -delta[X_AXIS];
+        if(!this->home_direction[Y_AXIS]) delta[Y_AXIS]= -delta[Y_AXIS];
+        float feed_rate = std::min(fast_rates[X_AXIS], fast_rates[Y_AXIS]);
+        THEROBOT->solo_move(delta, feed_rate);
+
+        // Wait for XY to have homed
+        THECONVEYOR->wait_for_empty_queue();
+
+    } else if(axis_to_home[X_AXIS]) {
+        // now home X only
+        float delta[3] {alpha_max, 0, 0};
+        if(!this->home_direction[X_AXIS]) delta[X_AXIS]= -delta[X_AXIS];
+        THEROBOT->solo_move(delta, fast_rates[X_AXIS]);
+        // wait for X
+        THECONVEYOR->wait_for_empty_queue();
+
+    } else if(axis_to_home[Y_AXIS]) {
+        // now home Y only
+        float delta[3] {0, beta_max, 0};
+        if(!this->home_direction[Y_AXIS]) delta[Y_AXIS]= -delta[Y_AXIS];
+        THEROBOT->solo_move(delta, fast_rates[Y_AXIS]);
+        // wait for Y
+        THECONVEYOR->wait_for_empty_queue();
+    }
+
+    if(axis_to_home[Z_AXIS]) {
+        // now home z
+        float delta[3] {0, 0, gamma_max};
+        if(!this->home_direction[Z_AXIS]) delta[Z_AXIS]= -delta[Z_AXIS];
+        THEROBOT->solo_move(delta, fast_rates[Z_AXIS]);
+        // wait for Z
+        THECONVEYOR->wait_for_empty_queue();
+    }
+
+    float delta[3]{0,0,0};
+    // use minimum feed rate of all three axes
+    float feed_rate= std::min(slow_rates[X_AXIS], std::min(slow_rates[Y_AXIS], slow_rates[Z_AXIS]));
+    // Move back a small distance for all homing axis
     this->status = MOVING_BACK;
-    this->feed_rate[X_AXIS] = slow_rate;
-    STEPPER[X_AXIS]->move(!dirx, retract_steps, 0);
-    this->feed_rate[Y_AXIS] = slow_rate;
-    STEPPER[Y_AXIS]->move(!diry, retract_steps, 0);
-
-    // wait until done
-    while ( STEPPER[X_AXIS]->is_moving() || STEPPER[Y_AXIS]->is_moving()) {
-        THEKERNEL->call_event(ON_IDLE);
-        if(THEKERNEL->is_halted()) return;
-    }
-
-    // Start moving the axes to the origin slowly
-    this->status = MOVING_TO_ENDSTOP_SLOW;
-    this->feed_rate[X_AXIS] = slow_rate;
-    STEPPER[X_AXIS]->move(dirx, 10000000, 0);
-    this->feed_rate[Y_AXIS] = slow_rate;
-    STEPPER[Y_AXIS]->move(diry, 10000000, 0);
-
-    // wait for primary axis
-    if(!this->wait_for_homed_corexy(home_axis)) return;
-}
-
-// this homing works for HBots/CoreXY
-void Endstops::do_homing_corexy(char axes_to_move)
-{
-    // TODO should really make order configurable, and select whether to allow XY to home at the same time, diagonally
-    // To move XY at the same time only one motor needs to turn, determine which motor and which direction based on min or max directions
-    // allow to move until an endstop triggers, then stop that motor. Speed up when moving diagonally to match X or Y speed
-    // continue moving in the direction not yet triggered (which means two motors turning) until endstop hit
-
-    if((axes_to_move & 0x03) == 0x03) { // both X and Y need Homing
-        // determine which motor to turn and which way
-        bool dirx = this->home_direction[X_AXIS];
-        bool diry = this->home_direction[Y_AXIS];
-        int motor;
-        bool dir;
-        if(dirx && diry) { // min/min
-            motor = X_AXIS;
-            dir = true;
-        } else if(dirx && !diry) { // min/max
-            motor = Y_AXIS;
-            dir = true;
-        } else if(!dirx && diry) { // max/min
-            motor = Y_AXIS;
-            dir = false;
-        } else if(!dirx && !diry) { // max/max
-            motor = X_AXIS;
-            dir = false;
-        }
-
-        // then move both X and Y until one hits the endstop
-        this->status = MOVING_TO_ENDSTOP_FAST;
-        // need to allow for more ground covered when moving diagonally
-        this->feed_rate[motor] = this->fast_rates[motor] * 1.4142;
-        STEPPER[motor]->move(dir, 10000000, 0);
-        // wait until either X or Y hits the endstop
-        bool running = true;
-        while (running) {
-            THEKERNEL->call_event(ON_IDLE);
-            if(THEKERNEL->is_halted()) return;
-            for(int m = X_AXIS; m <= Y_AXIS; m++) {
-                if(this->pins[m + (this->home_direction[m] ? 0 : 3)].get()) {
-                    // turn off motor
-                    if(STEPPER[motor]->is_moving()) STEPPER[motor]->move(0, 0);
-                    running = false;
-                    break;
-                }
-            }
+    for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
+        if(axis_to_home[c]) {
+            delta[c]= this->retract_mm[c];
+            if(this->home_direction[c]) delta[c]= -delta[c];
         }
     }
 
-    // move individual axis
-    if (axes_to_move & 0x01) { // Home X, which means both X and Y in same direction
-        bool dir = this->home_direction[X_AXIS];
-        corexy_home(X_AXIS, dir, dir, this->fast_rates[X_AXIS], this->slow_rates[X_AXIS], this->retract_mm[X_AXIS]*STEPS_PER_MM(X_AXIS));
-    }
-
-    if (axes_to_move & 0x02) { // Home Y, which means both X and Y in different directions
-        bool dir = this->home_direction[Y_AXIS];
-        corexy_home(Y_AXIS, dir, !dir, this->fast_rates[Y_AXIS], this->slow_rates[Y_AXIS], this->retract_mm[Y_AXIS]*STEPS_PER_MM(Y_AXIS));
-    }
-
-    if (axes_to_move & 0x04) { // move Z
-        do_homing_cartesian(0x04); // just home normally for Z
-    }
-}
+    THEROBOT->solo_move(delta, feed_rate);
+    // wait until finished
+    THECONVEYOR->wait_for_empty_queue();
 
-void Endstops::home(char axes_to_move)
-{
-    // not a block move so disable the last tick setting
+    // Start moving the axes to the origin slowly
+    this->status = MOVING_TO_ENDSTOP_SLOW;
     for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-        STEPPER[c]->set_moved_last_block(false);
-    }
-
-    if (is_corexy) {
-        // corexy/HBot homing
-        do_homing_corexy(axes_to_move);
-    } else {
-        // cartesian/delta homing
-        do_homing_cartesian(axes_to_move);
+        delta[c]= axis_to_home[c] ? this->retract_mm[c] : 0;
     }
+    THEROBOT->solo_move(delta, feed_rate);
+    // wait until finished
+    THECONVEYOR->wait_for_empty_queue();
 
-    // make sure all steppers are off (especially if aborted)
-    for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-        STEPPER[c]->move(0, 0);
-    }
     this->status = NOT_HOMING;
 }
 
@@ -635,17 +526,17 @@ void Endstops::process_home_command(Gcode* gcode)
 
     } else if(gcode->subcode == 1) { // G28.1 set pre defined position
         // saves current position in absolute machine coordinates
-        THEKERNEL->robot->get_axis_position(saved_position);
+        THEROBOT->get_axis_position(saved_position);
         return;
 
     } else if(gcode->subcode == 3) { // G28.3 is a smoothie special it sets manual homing
         if(gcode->get_num_args() == 0) {
-            THEKERNEL->robot->reset_axis_position(0, 0, 0);
+            THEROBOT->reset_axis_position(0, 0, 0);
         } else {
             // do a manual homing based on given coordinates, no endstops required
-            if(gcode->has_letter('X')) THEKERNEL->robot->reset_axis_position(gcode->get_value('X'), X_AXIS);
-            if(gcode->has_letter('Y')) THEKERNEL->robot->reset_axis_position(gcode->get_value('Y'), Y_AXIS);
-            if(gcode->has_letter('Z')) THEKERNEL->robot->reset_axis_position(gcode->get_value('Z'), Z_AXIS);
+            if(gcode->has_letter('X')) THEROBOT->reset_axis_position(gcode->get_value('X'), X_AXIS);
+            if(gcode->has_letter('Y')) THEROBOT->reset_axis_position(gcode->get_value('Y'), Y_AXIS);
+            if(gcode->has_letter('Z')) THEROBOT->reset_axis_position(gcode->get_value('Z'), Z_AXIS);
         }
         return;
 
@@ -655,7 +546,7 @@ void Endstops::process_home_command(Gcode* gcode)
         if(gcode->has_letter('A')) ac[0] =  gcode->get_value('A');
         if(gcode->has_letter('B')) ac[1] =  gcode->get_value('B');
         if(gcode->has_letter('C')) ac[2] =  gcode->get_value('C');
-        THEKERNEL->robot->reset_actuator_position(ac);
+        THEROBOT->reset_actuator_position(ac);
         return;
 
     } else if(THEKERNEL->is_grbl_mode()) {
@@ -668,53 +559,67 @@ void Endstops::process_home_command(Gcode* gcode)
     // First wait for the queue to be empty
     THEKERNEL->conveyor->wait_for_empty_queue();
 
-    // Do we move select axes or all of them
-    char axes_to_move = 0;
-
     // deltas, scaras always home all axis
     bool home_all = this->is_delta || this->is_rdelta || this->is_scara;
 
     if(!home_all) { // ie not a delta
-        bool axis_speced= ( gcode->has_letter('X') || gcode->has_letter('Y') || gcode->has_letter('Z') );
+        bool axis_speced = ( gcode->has_letter('X') || gcode->has_letter('Y') || gcode->has_letter('Z') );
+        axis_to_home.reset();
         // only enable homing if the endstop is defined,
         for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
             if (this->pins[c + (this->home_direction[c] ? 0 : 3)].connected() && (!axis_speced || gcode->has_letter(c + 'X')) ) {
-                axes_to_move += ( 1 << c );
+                axis_to_home.set(c);
             }
         }
 
-    }else{
+    } else {
         // all axis must move (and presumed defined)
-        axes_to_move= 7;
+        axis_to_home.set();
     }
 
     // save current actuator position so we can report how far we moved
     ActuatorCoordinates start_pos{
-        THEKERNEL->robot->actuators[X_AXIS]->get_current_position(),
-        THEKERNEL->robot->actuators[Y_AXIS]->get_current_position(),
-        THEKERNEL->robot->actuators[Z_AXIS]->get_current_position()
+        THEROBOT->actuators[X_AXIS]->get_current_position(),
+        THEROBOT->actuators[Y_AXIS]->get_current_position(),
+        THEROBOT->actuators[Z_AXIS]->get_current_position()
     };
 
     // Enable the motors
-    THEKERNEL->stepper->turn_enable_pins_on();
+    THEKERNEL->call_event(ON_ENABLE, (void*)1); // turn all enable pins on
 
     // do the actual homing
     if(homing_order != 0) {
+        bitset<3> axis= axis_to_home;
         // if an order has been specified do it in the specified order
         // homing order is 0b00ccbbaa where aa is 0,1,2 to specify the first axis, bb is the second and cc is the third
         // eg 0b00100001 would be Y X Z, 0b00100100 would be X Y Z
         for (uint8_t m = homing_order; m != 0; m >>= 2) {
-            int a = (1 << (m & 0x03)); // axis to move
-            if((a & axes_to_move) != 0) {
-                home(a);
+            int a= (m & 0x03); // axis to home
+            if(axis[a]) { // if axis is selected to home
+                axis_to_home.reset();
+                axis_to_home.set(a);
+                home();
             }
             // check if on_halt (eg kill)
             if(THEKERNEL->is_halted()) break;
         }
+        axis_to_home= axis;
+
+    } else if(is_corexy) {
+        // corexy must home each axis individually
+        bitset<3> axis= axis_to_home;
+        for (int a = X_AXIS; a <= Z_AXIS; ++a) {
+            if(axis[a]) {
+                axis_to_home.reset();
+                axis_to_home.set(a);
+                home();
+            }
+        }
+        axis_to_home= axis;
 
     } else {
-        // they all home at the same time
-        home(axes_to_move);
+        // they could all home at the same time
+        home();
     }
 
     // check if on_halt (eg kill)
@@ -726,11 +631,11 @@ void Endstops::process_home_command(Gcode* gcode)
     }
 
     // set the last probe position to the actuator units moved during this home
-    THEKERNEL->robot->set_last_probe_position(
+    THEROBOT->set_last_probe_position(
         std::make_tuple(
-            start_pos[0] - THEKERNEL->robot->actuators[0]->get_current_position(),
-            start_pos[1] - THEKERNEL->robot->actuators[1]->get_current_position(),
-            start_pos[2] - THEKERNEL->robot->actuators[2]->get_current_position(),
+            start_pos[0] - THEROBOT->actuators[0]->get_current_position(),
+            start_pos[1] - THEROBOT->actuators[1]->get_current_position(),
+            start_pos[2] - THEROBOT->actuators[2]->get_current_position(),
             0));
 
     if(home_all) {
@@ -746,7 +651,7 @@ void Endstops::process_home_command(Gcode* gcode)
         bool has_endstop_trim = this->is_delta || this->is_scara;
         if (has_endstop_trim) {
             ActuatorCoordinates ideal_actuator_position;
-            THEKERNEL->robot->arm_solution->cartesian_to_actuator(ideal_position, ideal_actuator_position);
+            THEROBOT->arm_solution->cartesian_to_actuator(ideal_position, ideal_actuator_position);
 
             // We are actually not at the ideal position, but a trim away
             ActuatorCoordinates real_actuator_position = {
@@ -756,28 +661,28 @@ void Endstops::process_home_command(Gcode* gcode)
             };
 
             float real_position[3];
-            THEKERNEL->robot->arm_solution->actuator_to_cartesian(real_actuator_position, real_position);
+            THEROBOT->arm_solution->actuator_to_cartesian(real_actuator_position, real_position);
             // Reset the actuator positions to correspond our real position
-            THEKERNEL->robot->reset_axis_position(real_position[0], real_position[1], real_position[2]);
+            THEROBOT->reset_axis_position(real_position[0], real_position[1], real_position[2]);
 
         } else {
             // without endstop trim, real_position == ideal_position
             if(is_rdelta) {
                 // with a rotary delta we set the actuators angle then use the FK to calculate the resulting cartesian coordinates
                 ActuatorCoordinates real_actuator_position = {ideal_position[0], ideal_position[1], ideal_position[2]};
-                THEKERNEL->robot->reset_actuator_position(real_actuator_position);
+                THEROBOT->reset_actuator_position(real_actuator_position);
 
             } else {
                 // Reset the actuator positions to correspond our real position
-                THEKERNEL->robot->reset_axis_position(ideal_position[0], ideal_position[1], ideal_position[2]);
+                THEROBOT->reset_axis_position(ideal_position[0], ideal_position[1], ideal_position[2]);
             }
         }
 
     } else {
         // Zero the ax(i/e)s position, add in the home offset
         for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-            if ( (axes_to_move >> c)  & 1 ) {
-                THEKERNEL->robot->reset_axis_position(this->homing_position[c] + this->home_offset[c], c);
+            if (axis_to_home[c]) {
+                THEROBOT->reset_axis_position(this->homing_position[c] + this->home_offset[c], c);
             }
         }
     }
@@ -786,15 +691,15 @@ void Endstops::process_home_command(Gcode* gcode)
     // default is off for cartesian on for deltas
     if(!is_delta) {
         // NOTE a rotary delta usually has optical or hall-effect endstops so it is safe to go past them a little bit
-        if(this->move_to_origin_after_home) move_to_origin(axes_to_move);
+        if(this->move_to_origin_after_home) move_to_origin();
         // if limit switches are enabled we must back off endstop after setting home
-        back_off_home(axes_to_move);
+        back_off_home();
 
     } else if(this->move_to_origin_after_home || this->limit_enable[X_AXIS]) {
         // deltas are not left at 0,0 because of the trim settings, so move to 0,0 if requested, but we need to back off endstops first
         // also need to back off endstops if limits are enabled
-        back_off_home(axes_to_move);
-        if(this->move_to_origin_after_home) move_to_origin(axes_to_move);
+        back_off_home();
+        if(this->move_to_origin_after_home) move_to_origin();
     }
 }
 
@@ -802,18 +707,18 @@ void Endstops::set_homing_offset(Gcode *gcode)
 {
     // Similar to M206 and G92 but sets Homing offsets based on current position
     float cartesian[3];
-    THEKERNEL->robot->get_axis_position(cartesian);    // get actual position from robot
+    THEROBOT->get_axis_position(cartesian);    // get actual position from robot
     if (gcode->has_letter('X')) {
         home_offset[0] -= (cartesian[X_AXIS] - gcode->get_value('X'));
-        THEKERNEL->robot->reset_axis_position(gcode->get_value('X'), X_AXIS);
+        THEROBOT->reset_axis_position(gcode->get_value('X'), X_AXIS);
     }
     if (gcode->has_letter('Y')) {
         home_offset[1] -= (cartesian[Y_AXIS] - gcode->get_value('Y'));
-        THEKERNEL->robot->reset_axis_position(gcode->get_value('Y'), Y_AXIS);
+        THEROBOT->reset_axis_position(gcode->get_value('Y'), Y_AXIS);
     }
     if (gcode->has_letter('Z')) {
         home_offset[2] -= (cartesian[Z_AXIS] - gcode->get_value('Z'));
-        THEKERNEL->robot->reset_axis_position(gcode->get_value('Z'), Z_AXIS);
+        THEROBOT->reset_axis_position(gcode->get_value('Z'), Z_AXIS);
     }
 
     gcode->stream->printf("Homing Offset: X %5.3f Y %5.3f Z %5.3f\n", home_offset[0], home_offset[1], home_offset[2]);
@@ -893,73 +798,8 @@ void Endstops::on_gcode_received(void *argument)
                 }
                 break;
 
-            // NOTE this is to test accuracy of lead screws etc.
-            case 1910: {
-                // M1910.0 - move specific number of raw steps
-                // M1910.1 - stop any moves
-                // M1910.2 - move specific number of actuator units (usually mm but is degrees for a rotary delta)
-                if(gcode->subcode == 0 || gcode->subcode == 2) {
-                    // Enable the motors
-                    THEKERNEL->stepper->turn_enable_pins_on();
-
-                    int32_t x = 0, y = 0, z = 0, f = 200 * 16;
-                    if (gcode->has_letter('F')) f = gcode->get_value('F');
-
-                    if (gcode->has_letter('X')) {
-                        float v = gcode->get_value('X');
-                        if(gcode->subcode == 2) x = lroundf(v * STEPS_PER_MM(X_AXIS));
-                        else x = roundf(v);
-                        STEPPER[X_AXIS]->move(x < 0, abs(x), f);
-                    }
-                    if (gcode->has_letter('Y')) {
-                        float v = gcode->get_value('Y');
-                        if(gcode->subcode == 2) y = lroundf(v * STEPS_PER_MM(Y_AXIS));
-                        else y = roundf(v);
-                        STEPPER[Y_AXIS]->move(y < 0, abs(y), f);
-                    }
-                    if (gcode->has_letter('Z')) {
-                        float v = gcode->get_value('Z');
-                        if(gcode->subcode == 2) z = lroundf(v * STEPS_PER_MM(Z_AXIS));
-                        else z = roundf(v);
-                        STEPPER[Z_AXIS]->move(z < 0, abs(z), f);
-                    }
-                    gcode->stream->printf("Moving X %ld Y %ld Z %ld steps at F %ld steps/sec\n", x, y, z, f);
-
-                } else if(gcode->subcode == 1) {
-                    // stop any that are moving
-                    for (int i = 0; i < 3; ++i) {
-                        if(STEPPER[i]->is_moving()) STEPPER[i]->move(0, 0);
-                    }
-                }
-                break;
-            }
-        }
-    }
-}
-
-// Called periodically to change the speed to match acceleration
-void Endstops::acceleration_tick(void)
-{
-    if(this->status >= NOT_HOMING) return; // nothing to do, only do this when moving for homing sequence
-
-    // foreach stepper that is moving
-    for ( int c = X_AXIS; c <= Z_AXIS; c++ ) {
-        if( !STEPPER[c]->is_moving() ) continue;
-
-        uint32_t current_rate = STEPPER[c]->get_steps_per_second();
-        uint32_t target_rate = floorf(this->feed_rate[c] * STEPS_PER_MM(c));
-        float acc = (c == Z_AXIS) ? THEKERNEL->planner->get_z_acceleration() : THEKERNEL->planner->get_acceleration();
-        if( current_rate < target_rate ) {
-            uint32_t rate_increase = floorf((acc / THEKERNEL->acceleration_ticks_per_second) * STEPS_PER_MM(c));
-            current_rate = min( target_rate, current_rate + rate_increase );
         }
-        if( current_rate > target_rate ) { current_rate = target_rate; }
-
-        // steps per second
-        STEPPER[c]->set_speed(current_rate);
     }
-
-    return;
 }
 
 void Endstops::on_get_public_data(void* argument)
index 96173c4..5586559 100644 (file)
@@ -5,13 +5,13 @@
       You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
 */
 
-#ifndef ENDSTOPS_MODULE_H
-#define ENDSTOPS_MODULE_H
+#pragma once
 
 #include "libs/Module.h"
 #include "libs/Pin.h"
 
 #include <bitset>
+#include <array>
 
 class StepperMotor;
 class Gcode;
@@ -21,31 +21,27 @@ class Endstops : public Module{
         Endstops();
         void on_module_loaded();
         void on_gcode_received(void* argument);
-        void acceleration_tick(void);
 
     private:
         void load_config();
-        void home(char axes_to_move);
-        void do_homing_cartesian(char axes_to_move);
-        void do_homing_corexy(char axes_to_move);
-        bool wait_for_homed(char axes_to_move);
+        void home();
+        bool wait_for_homed();
         bool wait_for_homed_corexy(int axis);
         void corexy_home(int home_axis, bool dirx, bool diry, float fast_rate, float slow_rate, unsigned int retract_steps);
-        void back_off_home(char axes_to_move);
-        void move_to_origin(char);
+        void back_off_home();
+        void move_to_origin();
         void on_get_public_data(void* argument);
         void on_set_public_data(void* argument);
         void on_idle(void *argument);
         bool debounced_get(int pin);
         void process_home_command(Gcode* gcode);
         void set_homing_offset(Gcode* gcode);
+        uint32_t read_endstops(uint32_t dummy);
 
         float homing_position[3];
         float home_offset[3];
-        uint8_t homing_order;
-        std::bitset<3> home_direction;
-        std::bitset<3> limit_enable;
         float saved_position[3]{0}; // save G28 (in grbl mode)
+        float alpha_max, beta_max, gamma_max;
 
         unsigned int  debounce_count;
         float  retract_mm[3];
@@ -53,16 +49,20 @@ class Endstops : public Module{
         float  fast_rates[3];
         float  slow_rates[3];
         Pin    pins[6];
-        volatile float feed_rate[3];
+        std::array<uint16_t, 3> debounce;
+
+        std::bitset<3> home_direction;
+        std::bitset<3> limit_enable;
+        std::bitset<3> axis_to_home;
+
         struct {
+            uint8_t homing_order:6;
+            uint8_t bounce_cnt:4;
+            volatile char status:3;
             bool is_corexy:1;
             bool is_delta:1;
             bool is_rdelta:1;
             bool is_scara:1;
             bool move_to_origin_after_home:1;
-            uint8_t bounce_cnt:4;
-            volatile char status:3;
         };
 };
-
-#endif
index 95e5ebf..63beebb 100644 (file)
@@ -429,10 +429,10 @@ void Extruder::on_gcode_received(void *argument)
                 int n = snprintf(buf, sizeof(buf), "G0 Z%1.4f F%1.4f", -retract_zlift_length, retract_zlift_feedrate);
                 string cmd(buf, n);
                 Gcode gc(cmd, &(StreamOutput::NullStream));
-                THEKERNEL->robot->push_state(); // save state includes feed rates etc
-                THEKERNEL->robot->absolute_mode = false; // needs to be relative mode
-                THEKERNEL->robot->on_gcode_received(&gc); // send to robot directly
-                THEKERNEL->robot->pop_state(); // restore state includes feed rates etc
+                THEROBOT->push_state(); // save state includes feed rates etc
+                THEROBOT->absolute_mode = false; // needs to be relative mode
+                THEROBOT->on_gcode_received(&gc); // send to robot directly
+                THEROBOT->pop_state(); // restore state includes feed rates etc
             }
 
             // This is a solo move, we add an empty block to the queue to prevent subsequent gcodes being executed at the same time
@@ -444,10 +444,10 @@ void Extruder::on_gcode_received(void *argument)
                 int n = snprintf(buf, sizeof(buf), "G0 Z%1.4f F%1.4f", retract_zlift_length, retract_zlift_feedrate);
                 string cmd(buf, n);
                 Gcode gc(cmd, &(StreamOutput::NullStream));
-                THEKERNEL->robot->push_state(); // save state includes feed rates etc
-                THEKERNEL->robot->absolute_mode = false; // needs to be relative mode
-                THEKERNEL->robot->on_gcode_received(&gc); // send to robot directly
-                THEKERNEL->robot->pop_state(); // restore state includes feed rates etc
+                THEROBOT->push_state(); // save state includes feed rates etc
+                THEROBOT->absolute_mode = false; // needs to be relative mode
+                THEROBOT->on_gcode_received(&gc); // send to robot directly
+                THEROBOT->pop_state(); // restore state includes feed rates etc
             }
 
         } else if( this->enabled && this->retracted && (gcode->g == 0 || gcode->g == 1) && gcode->has_letter('Z')) {
@@ -573,7 +573,7 @@ void Extruder::on_gcode_execute(void *argument)
 
             // NOTE this is only used in SOLO mode, but any F on a G0/G1 will set the speed for future retracts that are not firmware retracts
             if (gcode->has_letter('F')) {
-                feed_rate = gcode->get_value('F') / THEKERNEL->robot->get_seconds_per_minute();
+                feed_rate = gcode->get_value('F') / THEROBOT->get_seconds_per_minute();
                 if (stepper_motor->get_max_rate() > 0 && feed_rate > stepper_motor->get_max_rate())
                     feed_rate = stepper_motor->get_max_rate();
             }
index 2df75e4..39ececd 100644 (file)
@@ -64,15 +64,15 @@ void RotaryDeltaCalibration::on_gcode_received(void *argument)
 
                 ActuatorCoordinates current_angle;
                 // get the current angle for each actuator, NOTE we only deal with  ABC so if there are more than 3 actuators this will probably go wonky
-                for (size_t i = 0; i < THEKERNEL->robot->actuators.size(); i++) {
-                    current_angle[i]= THEKERNEL->robot->actuators[i]->get_current_position();
+                for (size_t i = 0; i < THEROBOT->actuators.size(); i++) {
+                    current_angle[i]= THEROBOT->actuators[i]->get_current_position();
                 }
 
                 if (gcode->has_letter('L') && gcode->get_value('L') != 0) {
                     // specifying L1 it will take the last probe position (set by G30 or G38.x ) and set the home offset based on that
                     // this allows the use of G30 to find the angle tool
                     uint8_t ok;
-                    std::tie(current_angle[0], current_angle[1], current_angle[2], ok) = THEKERNEL->robot->get_last_probe_position();
+                    std::tie(current_angle[0], current_angle[1], current_angle[2], ok) = THEROBOT->get_last_probe_position();
                     if(ok == 0) {
                         gcode->stream->printf("error:Nothing set as probe failed or not run\n");
                         return;
@@ -110,7 +110,7 @@ void RotaryDeltaCalibration::on_gcode_received(void *argument)
                 // reset the actuator positions (and machine position accordingly)
                 // But only if all three actuators have been specified at the same time
                 if(cnt == 3 || (gcode->has_letter('R') && gcode->get_value('R') != 0)) {
-                    THEKERNEL->robot->reset_actuator_position(current_angle);
+                    THEROBOT->reset_actuator_position(current_angle);
                     gcode->stream->printf("NOTE: actuator position reset\n");
                 }else{
                     gcode->stream->printf("NOTE: actuator position NOT reset\n");
index b15f8ea..39bdf0c 100644 (file)
@@ -33,7 +33,7 @@
 #define Y_AXIS 1
 #define Z_AXIS 2
 
-#define STEPPER THEKERNEL->robot->actuators
+#define STEPPER THEROBOT->actuators
 #define STEPS_PER_MM(a) (STEPPER[a]->get_steps_per_mm())
 
 void SCARAcal::on_module_loaded()
@@ -136,7 +136,7 @@ bool SCARAcal::translate_trim(StreamOutput *stream)
     this->get_home_offset(home_off[0], home_off[1], home_off[2]);               // get home offsets
     this->get_trim(S_trim[0], S_trim[1], S_trim[2]);                             // get current trim
 
-    THEKERNEL->robot->arm_solution->cartesian_to_actuator( home_off, actuator ); // convert current home offset to actuator angles
+    THEROBOT->arm_solution->cartesian_to_actuator( home_off, actuator ); // convert current home offset to actuator angles
 
     // Subtract trim values from actuators to determine the real home offset actuator position for X and Y.
 
@@ -149,7 +149,7 @@ bool SCARAcal::translate_trim(StreamOutput *stream)
 
     // convert back to get the real cartesian home offsets
 
-    THEKERNEL->robot->arm_solution->actuator_to_cartesian( actuator, home_off );
+    THEROBOT->arm_solution->actuator_to_cartesian( actuator, home_off );
 
     this->set_home_offset(home_off[0], home_off[1], home_off[2],stream);               // get home offsets
                  // Set the correct home offsets;
@@ -171,7 +171,7 @@ void SCARAcal::SCARA_ang_move(float theta, float psi, float z, float feedrate)
     actuator[2] = z;
 
     // Calculate the physical position relating to the arm angles
-    THEKERNEL->robot->arm_solution->actuator_to_cartesian( actuator, cartesian );
+    THEROBOT->arm_solution->actuator_to_cartesian( actuator, cartesian );
 
     // Assemble Gcode to add onto the queue
     snprintf(cmd, sizeof(cmd), "G0 X%1.3f Y%1.3f Z%1.3f F%1.1f", cartesian[0], cartesian[1], cartesian[2], feedrate * 60); // use specified feedrate (mm/sec)
@@ -179,7 +179,7 @@ void SCARAcal::SCARA_ang_move(float theta, float psi, float z, float feedrate)
     //THEKERNEL->streams->printf("DEBUG: move: %s\n", cmd);
 
     Gcode gc(cmd, &(StreamOutput::NullStream));
-    THEKERNEL->robot->on_gcode_received(&gc); // send to robot directly
+    THEROBOT->on_gcode_received(&gc); // send to robot directly
 }
 
 //A GCode has been received
@@ -196,8 +196,8 @@ void SCARAcal::on_gcode_received(void *argument)
                 float cartesian[3];
                 ActuatorCoordinates actuators;
 
-                THEKERNEL->robot->get_axis_position(cartesian);    // get actual position from robot
-                THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators );      // translate to get actuator position
+                THEROBOT->get_axis_position(cartesian);    // get actual position from robot
+                THEROBOT->arm_solution->cartesian_to_actuator( cartesian, actuators );      // translate to get actuator position
 
                 int n = snprintf(buf, sizeof(buf), "  A: Th:%1.3f Ps:%1.3f",
                                  actuators[0],
@@ -219,8 +219,8 @@ void SCARAcal::on_gcode_received(void *argument)
                     float S_delta[2],
                           S_trim[3];
 
-                    THEKERNEL->robot->get_axis_position(cartesian);    // get actual position from robot
-                    THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators );      // translate to get actuator position
+                    THEROBOT->get_axis_position(cartesian);    // get actual position from robot
+                    THEROBOT->arm_solution->cartesian_to_actuator( cartesian, actuators );      // translate to get actuator position
 
                     S_delta[0] = actuators[0] - target[0];
 
@@ -228,7 +228,7 @@ void SCARAcal::on_gcode_received(void *argument)
                 } else {
                     set_trim(0, S_trim[1], S_trim[2], gcode->stream);               // reset trim for calibration move
                     this->home();                                                   // home
-                    THEKERNEL->robot->get_axis_position(cartesian);    // get actual position from robot
+                    THEROBOT->get_axis_position(cartesian);    // get actual position from robot
                     SCARA_ang_move(target[0], target[1], cartesian[2] + this->z_move, slow_rate * 3.0F); // move to target
                 }
             }
@@ -242,14 +242,14 @@ void SCARAcal::on_gcode_received(void *argument)
                     // Program the current position as target
                     ActuatorCoordinates actuators;
 
-                    THEKERNEL->robot->get_axis_position(cartesian);                                // get actual position from robot
-                    THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators ); // translate to get actuator position
+                    THEROBOT->get_axis_position(cartesian);                                // get actual position from robot
+                    THEROBOT->arm_solution->cartesian_to_actuator( cartesian, actuators ); // translate to get actuator position
 
                     STEPPER[0]->change_steps_per_mm(actuators[0] / target[0] * STEPPER[0]->get_steps_per_mm()); // Find angle difference
                     STEPPER[1]->change_steps_per_mm(STEPPER[0]->get_steps_per_mm());  // and change steps_per_mm to ensure correct steps per *angle*
                 } else {
                     this->home();                                                   // home - This time leave trims as adjusted.
-                    THEKERNEL->robot->get_axis_position(cartesian);    // get actual position from robot
+                    THEROBOT->get_axis_position(cartesian);    // get actual position from robot
                     SCARA_ang_move(target[0], target[1], cartesian[2] + this->z_move, slow_rate * 3.0F); // move to target
                 }
 
@@ -268,15 +268,15 @@ void SCARAcal::on_gcode_received(void *argument)
                     ActuatorCoordinates actuators;
                     float S_delta[2];
 
-                    THEKERNEL->robot->get_axis_position(cartesian);                                     // get actual position from robot
-                    THEKERNEL->robot->arm_solution->cartesian_to_actuator( cartesian, actuators );      // translate it to get actual actuator angles
+                    THEROBOT->get_axis_position(cartesian);                                     // get actual position from robot
+                    THEROBOT->arm_solution->cartesian_to_actuator( cartesian, actuators );      // translate it to get actual actuator angles
 
                     S_delta[1] = ( actuators[1] - actuators[0]) - ( target[1] - target[0] );            // Find difference in angle - not actuator difference, and
                     set_trim(S_trim[0], S_delta[1], S_trim[2], gcode->stream);                                  // set trim to reflect the difference
                 } else {
                     set_trim(S_trim[0], 0, S_trim[2], gcode->stream);                                           // reset trim for calibration move
                     this->home();                                                                       // home
-                    THEKERNEL->robot->get_axis_position(cartesian);    // get actual position from robot
+                    THEROBOT->get_axis_position(cartesian);    // get actual position from robot
                     SCARA_ang_move(target[0], target[1], cartesian[2] + this->z_move, slow_rate * 3.0F);                     // move to target
                 }
             }
index be0b197..5f5998d 100644 (file)
@@ -63,7 +63,7 @@ void ToolManager::on_gcode_received(void *argument)
 
                 //send new_tool_offsets to robot
                 const float *new_tool_offset = tools[new_tool]->get_offset();
-                THEKERNEL->robot->setToolOffset(new_tool_offset);
+                THEROBOT->setToolOffset(new_tool_offset);
             }
         }
     }
@@ -119,7 +119,7 @@ void ToolManager::add_tool(Tool* tool_to_add)
         this->current_tool_name = tool_to_add->get_name();
         //send new_tool_offsets to robot
         const float *new_tool_offset = tool_to_add->get_offset();
-        THEKERNEL->robot->setToolOffset(new_tool_offset);
+        THEROBOT->setToolOffset(new_tool_offset);
     } else {
         tool_to_add->disable();
     }
index c7015e4..6b868c9 100644 (file)
@@ -48,7 +48,7 @@ bool DeltaCalibrationStrategy::handleGcode(Gcode *gcode)
             THEKERNEL->conveyor->wait_for_empty_queue();
 
             // turn off any compensation transform as it will be invalidated anyway by this
-            THEKERNEL->robot->compensationTransform= nullptr;
+            THEROBOT->compensationTransform= nullptr;
 
             if(!gcode->has_letter('R')) {
                 if(!calibrate_delta_endstops(gcode)) {
@@ -116,7 +116,7 @@ bool DeltaCalibrationStrategy::probe_delta_points(Gcode *gcode)
     float max_delta= 0;
     float last_z= NAN;
     float start_z;
-    std::tie(std::ignore, std::ignore, start_z)= THEKERNEL->robot->get_axis_position();
+    std::tie(std::ignore, std::ignore, start_z)= THEROBOT->get_axis_position();
 
     for(auto& i : pp) {
         int s;
@@ -125,9 +125,9 @@ bool DeltaCalibrationStrategy::probe_delta_points(Gcode *gcode)
         if(gcode->subcode == 0) {
             gcode->stream->printf("X:%1.4f Y:%1.4f Z:%1.4f (%d) A:%1.4f B:%1.4f C:%1.4f\n",
                 i[0], i[1], z, s,
-                THEKERNEL->robot->actuators[0]->get_current_position()+z,
-                THEKERNEL->robot->actuators[1]->get_current_position()+z,
-                THEKERNEL->robot->actuators[2]->get_current_position()+z);
+                THEROBOT->actuators[0]->get_current_position()+z,
+                THEROBOT->actuators[1]->get_current_position()+z,
+                THEROBOT->actuators[2]->get_current_position()+z);
 
         }else if(gcode->subcode == 1) {
             // format that can be pasted here http://escher3d.com/pages/wizards/wizarddelta.php
@@ -340,7 +340,7 @@ bool DeltaCalibrationStrategy::calibrate_delta_radius(Gcode *gcode)
     // get current delta radius
     float delta_radius = 0.0F;
     BaseSolution::arm_options_t options;
-    if(THEKERNEL->robot->arm_solution->get_optional(options)) {
+    if(THEROBOT->arm_solution->get_optional(options)) {
         delta_radius = options['R'];
     }
     if(delta_radius == 0.0F) {
@@ -377,7 +377,7 @@ bool DeltaCalibrationStrategy::calibrate_delta_radius(Gcode *gcode)
 
         // set the new delta radius
         options['R'] = delta_radius;
-        THEKERNEL->robot->arm_solution->set_optional(options);
+        THEROBOT->arm_solution->set_optional(options);
         gcode->stream->printf("Setting delta radius to: %1.4f\n", delta_radius);
 
         zprobe->home();
index dd9fd79..9b1f4a7 100644 (file)
@@ -379,10 +379,10 @@ void DeltaGridStrategy::setAdjustFunction(bool on)
 {
     if(on) {
         // set the compensationTransform in robot
-        THEKERNEL->robot->compensationTransform = [this](float target[3]) { doCompensation(target); };
+        THEROBOT->compensationTransform = [this](float target[3]) { doCompensation(target); };
     } else {
         // clear it
-        THEKERNEL->robot->compensationTransform = nullptr;
+        THEROBOT->compensationTransform = nullptr;
     }
 }
 
index 9c3ddf9..704c152 100644 (file)
@@ -282,7 +282,7 @@ bool ThreePointStrategy::doProbing(StreamOutput *stream)
     if(!zprobe->run_probe(s)) return false;
 
     // TODO if using probe then we probably need to set Z to 0 at first probe point, but take into account probe offset from head
-    THEKERNEL->robot->reset_axis_position(std::get<Z_AXIS>(this->probe_offsets), Z_AXIS);
+    THEROBOT->reset_axis_position(std::get<Z_AXIS>(this->probe_offsets), Z_AXIS);
 
     // move up to specified probe start position
     zprobe->coordinated_move(NAN, NAN, zprobe->getProbeHeight(), zprobe->getSlowFeedrate()); // move to probe start position
@@ -357,10 +357,10 @@ void ThreePointStrategy::setAdjustFunction(bool on)
 {
     if(on) {
         // set the compensationTransform in robot
-        THEKERNEL->robot->compensationTransform= [this](float target[3]) { target[2] += this->plane->getz(target[0], target[1]); };
+        THEROBOT->compensationTransform= [this](float target[3]) { target[2] += this->plane->getz(target[0], target[1]); };
     }else{
         // clear it
-        THEKERNEL->robot->compensationTransform= nullptr;
+        THEROBOT->compensationTransform= nullptr;
     }
 }
 
index 689ac8e..3bdbeb5 100644 (file)
@@ -293,7 +293,7 @@ bool ZGridStrategy::handleGcode(Gcode *gcode)
                     float cartesian[3];
                     int pindex = 0;
 
-                    THEKERNEL->robot->get_axis_position(cartesian);         // get actual position from robot
+                    THEROBOT->get_axis_position(cartesian);         // get actual position from robot
 
                     pindex = int(cartesian[X_AXIS]/this->bed_div_x + 0.25)*this->numCols + int(cartesian[Y_AXIS]/this->bed_div_y + 0.25);
 
@@ -646,10 +646,10 @@ void ZGridStrategy::setAdjustFunction(bool on)
 {
     if(on) {
         // set the compensationTransform in robot
-        THEKERNEL->robot->compensationTransform= [this](float target[3]) { target[2] += this->getZOffset(target[0], target[1]); };
+        THEROBOT->compensationTransform= [this](float target[3]) { target[2] += this->getZOffset(target[0], target[1]); };
     }else{
         // clear it
-        THEKERNEL->robot->compensationTransform= nullptr;
+        THEROBOT->compensationTransform= nullptr;
     }
 }
 
index 928f366..55b53c2 100644 (file)
@@ -52,7 +52,7 @@
 #define Y_AXIS 1
 #define Z_AXIS 2
 
-#define STEPPER THEKERNEL->robot->actuators
+#define STEPPER THEROBOT->actuators
 #define STEPS_PER_MM(a) (STEPPER[a]->get_steps_per_mm())
 #define Z_STEPS_PER_MM STEPS_PER_MM(Z_AXIS)
 
@@ -312,16 +312,16 @@ void ZProbe::on_gcode_received(void *argument)
                 gcode->stream->printf("Z:%1.4f C:%d\n", zsteps_to_mm(steps), steps);
 
                 // set the last probe position to the current actuator units
-                THEKERNEL->robot->set_last_probe_position(std::make_tuple(
-                    THEKERNEL->robot->actuators[X_AXIS]->get_current_position(),
-                    THEKERNEL->robot->actuators[Y_AXIS]->get_current_position(),
-                    THEKERNEL->robot->actuators[Z_AXIS]->get_current_position(),
+                THEROBOT->set_last_probe_position(std::make_tuple(
+                    THEROBOT->actuators[X_AXIS]->get_current_position(),
+                    THEROBOT->actuators[Y_AXIS]->get_current_position(),
+                    THEROBOT->actuators[Z_AXIS]->get_current_position(),
                     1));
 
                 // move back to where it started, unless a Z is specified (and not a rotary delta)
                 if(gcode->has_letter('Z') && !is_rdelta) {
                     // set Z to the specified value, and leave probe where it is
-                    THEKERNEL->robot->reset_axis_position(gcode->get_value('Z'), Z_AXIS);
+                    THEROBOT->reset_axis_position(gcode->get_value('Z'), Z_AXIS);
 
                 } else {
                     // return to pre probe position
@@ -330,10 +330,10 @@ void ZProbe::on_gcode_received(void *argument)
 
             } else {
                 gcode->stream->printf("ZProbe not triggered\n");
-                THEKERNEL->robot->set_last_probe_position(std::make_tuple(
-                    THEKERNEL->robot->actuators[X_AXIS]->get_current_position(),
-                    THEKERNEL->robot->actuators[Y_AXIS]->get_current_position(),
-                    THEKERNEL->robot->actuators[Z_AXIS]->get_current_position(),
+                THEROBOT->set_last_probe_position(std::make_tuple(
+                    THEROBOT->actuators[X_AXIS]->get_current_position(),
+                    THEROBOT->actuators[Y_AXIS]->get_current_position(),
+                    THEROBOT->actuators[Z_AXIS]->get_current_position(),
                     0));
             }
 
@@ -385,8 +385,8 @@ void ZProbe::on_gcode_received(void *argument)
         THEKERNEL->conveyor->wait_for_empty_queue();
 
         // turn off any compensation transform
-        auto savect= THEKERNEL->robot->compensationTransform;
-        THEKERNEL->robot->compensationTransform= nullptr;
+        auto savect= THEROBOT->compensationTransform;
+        THEROBOT->compensationTransform= nullptr;
 
         if(gcode->has_letter('X')) {
             // probe in the X axis
@@ -405,7 +405,7 @@ void ZProbe::on_gcode_received(void *argument)
         }
 
         // restore compensationTransform
-        THEKERNEL->robot->compensationTransform= savect;
+        THEROBOT->compensationTransform= savect;
 
         return;
 
@@ -456,7 +456,7 @@ uint32_t ZProbe::read_probe(uint32_t dummy)
     if(this->pin.get()) {
         probe_detected= true;
         // now tell all the stepper_motors to stop
-        for(auto &a : THEKERNEL->robot->actuators) a->force_finish_move();
+        for(auto &a : THEROBOT->actuators) a->force_finish_move();
     }
     return 0;
 }
@@ -467,7 +467,7 @@ void ZProbe::probe_XYZ(Gcode *gcode, int axis)
     // enable the probe checking in the timer
     probing= true;
     probe_detected= false;
-    THEKERNEL->robot->disable_segmentation= true; // we must disable segmentation as this won't work with it enabled (beware on deltas probing in X or Y)
+    THEROBOT->disable_segmentation= true; // we must disable segmentation as this won't work with it enabled (beware on deltas probing in X or Y)
 
     // get probe feedrate if specified
     float rate = (gcode->has_letter('F')) ? gcode->get_value('F')*60 : this->slow_feedrate;
@@ -483,26 +483,26 @@ void ZProbe::probe_XYZ(Gcode *gcode, int axis)
 
     // disable probe checking
     probing= false;
-    THEKERNEL->robot->disable_segmentation= false;
+    THEROBOT->disable_segmentation= false;
 
     float pos[3];
     {
         // get the current position
         ActuatorCoordinates current_position{
-            THEKERNEL->robot->actuators[X_AXIS]->get_current_position(),
-            THEKERNEL->robot->actuators[Y_AXIS]->get_current_position(),
-            THEKERNEL->robot->actuators[Z_AXIS]->get_current_position()
+            THEROBOT->actuators[X_AXIS]->get_current_position(),
+            THEROBOT->actuators[Y_AXIS]->get_current_position(),
+            THEROBOT->actuators[Z_AXIS]->get_current_position()
         };
 
         // get machine position from the actuator position using FK
-        THEKERNEL->robot->arm_solution->actuator_to_cartesian(current_position, pos);
+        THEROBOT->arm_solution->actuator_to_cartesian(current_position, pos);
     }
 
     uint8_t probeok= this->probe_detected ? 1 : 0;
 
     // print results using the GRBL format
     gcode->stream->printf("[PRB:%1.3f,%1.3f,%1.3f:%d]\n", pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], probeok);
-    THEKERNEL->robot->set_last_probe_position(std::make_tuple(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], probeok));
+    THEROBOT->set_last_probe_position(std::make_tuple(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], probeok));
 
     if(!probeok && gcode->subcode == 2) {
         // issue error if probe was not triggered and subcode == 2
@@ -511,7 +511,7 @@ void ZProbe::probe_XYZ(Gcode *gcode, int axis)
 
     }else if(probeok){
         // if the probe stopped the move we need to correct the last_milestone as it did not reach where it thought
-        THEKERNEL->robot->reset_position_from_current_actuator_position();
+        THEROBOT->reset_position_from_current_actuator_position();
     }
 }
 
index b9d4efe..3e270fc 100644 (file)
@@ -254,10 +254,10 @@ void MotorDriverControl::on_gcode_received(void *argument)
                     // also reset the steps/mm
                     int a= designator-'A';
                     if(a >= 0 && a <=2) {
-                        float s= THEKERNEL->robot->actuators[a]->get_steps_per_mm()*((float)microsteps/current_microsteps);
-                        THEKERNEL->robot->actuators[a]->change_steps_per_mm(s);
+                        float s= THEROBOT->actuators[a]->get_steps_per_mm()*((float)microsteps/current_microsteps);
+                        THEROBOT->actuators[a]->change_steps_per_mm(s);
                         gcode->stream->printf("steps/mm for %c changed to: %f\n", designator, s);
-                        THEKERNEL->robot->check_max_actuator_speeds();
+                        THEROBOT->check_max_actuator_speeds();
                     }
                 }
                 microstep_override= true;
index 4e95dce..ff3b097 100644 (file)
@@ -896,15 +896,15 @@ void TMC26X::dumpStatus(StreamOutput *stream, bool readable)
 
     } else {
         // TODO hardcoded for X need to select ABC as needed
-        bool moving = THEKERNEL->robot->actuators[0]->is_moving();
+        bool moving = THEROBOT->actuators[0]->is_moving();
         // dump out in the format that the processing script needs
         if (moving) {
-            stream->printf("#sg%d,p%lu,k%u,r,", getCurrentStallGuardReading(), THEKERNEL->robot->actuators[0]->get_current_step(), getCoolstepCurrent());
+            stream->printf("#sg%d,p%lu,k%u,r,", getCurrentStallGuardReading(), THEROBOT->actuators[0]->get_current_step(), getCoolstepCurrent());
         } else {
             readStatus(TMC26X_READOUT_POSITION); // get the status bits
             stream->printf("#s,");
         }
-        stream->printf("d%d,", THEKERNEL->robot->actuators[0]->which_direction() ? 1 : -1);
+        stream->printf("d%d,", THEROBOT->actuators[0]->which_direction() ? 1 : -1);
         stream->printf("c%u,m%d,", getCurrent(), getMicrosteps());
         // stream->printf('S');
         // stream->printf(tmc26XStepper.getSpeed(), DEC);
index 3e8fa71..8c08fdb 100644 (file)
@@ -87,11 +87,11 @@ void PanelScreen::send_command(const char *gcstr)
 
 void PanelScreen::get_current_pos(float *cp)
 {
-    Robot::wcs_t mpos= THEKERNEL->robot->get_axis_position();
-    Robot::wcs_t pos= THEKERNEL->robot->mcs2wcs(mpos);
-    cp[0]= THEKERNEL->robot->from_millimeters(std::get<X_AXIS>(pos));
-    cp[1]= THEKERNEL->robot->from_millimeters(std::get<Y_AXIS>(pos));
-    cp[2]= THEKERNEL->robot->from_millimeters(std::get<Z_AXIS>(pos));
+    Robot::wcs_t mpos= THEROBOT->get_axis_position();
+    Robot::wcs_t pos= THEROBOT->mcs2wcs(mpos);
+    cp[0]= THEROBOT->from_millimeters(std::get<X_AXIS>(pos));
+    cp[1]= THEROBOT->from_millimeters(std::get<Y_AXIS>(pos));
+    cp[2]= THEROBOT->from_millimeters(std::get<Z_AXIS>(pos));
 }
 
 void PanelScreen::on_main_loop()
index 2c4558d..c77f45e 100644 (file)
@@ -59,22 +59,22 @@ void MainMenuScreen::setupConfigureScreen()
 
     // steps/mm
     mvs->addMenuItem("X steps/mm",
-        []() -> float { return THEKERNEL->robot->actuators[0]->get_steps_per_mm(); },
-        [](float v) { THEKERNEL->robot->actuators[0]->change_steps_per_mm(v); },
+        []() -> float { return THEROBOT->actuators[0]->get_steps_per_mm(); },
+        [](float v) { THEROBOT->actuators[0]->change_steps_per_mm(v); },
         0.1F,
         1.0F
         );
 
     mvs->addMenuItem("Y steps/mm",
-        []() -> float { return THEKERNEL->robot->actuators[1]->get_steps_per_mm(); },
-        [](float v) { THEKERNEL->robot->actuators[1]->change_steps_per_mm(v); },
+        []() -> float { return THEROBOT->actuators[1]->get_steps_per_mm(); },
+        [](float v) { THEROBOT->actuators[1]->change_steps_per_mm(v); },
         0.1F,
         1.0F
         );
 
     mvs->addMenuItem("Z steps/mm",
-        []() -> float { return THEKERNEL->robot->actuators[2]->get_steps_per_mm(); },
-        [](float v) { THEKERNEL->robot->actuators[2]->change_steps_per_mm(v); },
+        []() -> float { return THEROBOT->actuators[2]->get_steps_per_mm(); },
+        [](float v) { THEROBOT->actuators[2]->change_steps_per_mm(v); },
         0.1F,
         1.0F
         );
index fb065d0..d3ab782 100644 (file)
@@ -197,7 +197,7 @@ void WatchScreen::get_current_status()
 float WatchScreen::get_current_speed()
 {
     // in percent
-    return 6000.0F / THEKERNEL->robot->get_seconds_per_minute();
+    return 6000.0F / THEROBOT->get_seconds_per_minute();
 }
 
 void WatchScreen::get_sd_play_info()
index ef05ebd..8ae95d8 100644 (file)
@@ -130,10 +130,10 @@ void ControlScreen::set_current_pos(char axis, float p)
     // change pos by issuing a G0 Xnnn in absolute mode
     char buf[32];
     // make sure we are in absolute mode
-    THEKERNEL->robot->push_state();
-    THEKERNEL->robot->absolute_mode= true;
-    int n = snprintf(buf, sizeof(buf), "G0 %c%f F%d", axis, p, (int)round(THEKERNEL->robot->from_millimeters(THEPANEL->get_jogging_speed(axis))));
+    THEROBOT->push_state();
+    THEROBOT->absolute_mode= true;
+    int n = snprintf(buf, sizeof(buf), "G0 %c%f F%d", axis, p, (int)round(THEROBOT->from_millimeters(THEPANEL->get_jogging_speed(axis))));
     string g(buf, n);
     send_gcode(g);
-    THEKERNEL->robot->pop_state();
+    THEROBOT->pop_state();
 }
index 2142ac5..72a2118 100644 (file)
@@ -50,7 +50,7 @@ void DirectJogScreen::on_refresh()
     if ( THEPANEL->click() ) {
         switch(mode) {
             case JOG:
-                THEKERNEL->robot->reset_position_from_current_actuator_position(); // needed as we were changing the actuator only
+                THEROBOT->reset_position_from_current_actuator_position(); // needed as we were changing the actuator only
                 this->enter_menu_control();
                 this->refresh_menu();
                 break;
@@ -136,18 +136,18 @@ void DirectJogScreen::get_actuator_pos()
 {
         // get real time positions
         ActuatorCoordinates current_position{
-            THEKERNEL->robot->actuators[X_AXIS]->get_current_position(),
-            THEKERNEL->robot->actuators[Y_AXIS]->get_current_position(),
-            THEKERNEL->robot->actuators[Z_AXIS]->get_current_position()
+            THEROBOT->actuators[X_AXIS]->get_current_position(),
+            THEROBOT->actuators[Y_AXIS]->get_current_position(),
+            THEROBOT->actuators[Z_AXIS]->get_current_position()
         };
 
         // get machine position from the actuator position using FK
         float mpos[3];
-        THEKERNEL->robot->arm_solution->actuator_to_cartesian(current_position, mpos);
-        Robot::wcs_t wpos= THEKERNEL->robot->mcs2wcs(mpos);
-        this->pos[0]= THEKERNEL->robot->from_millimeters(std::get<X_AXIS>(wpos));
-        this->pos[1]= THEKERNEL->robot->from_millimeters(std::get<Y_AXIS>(wpos));
-        this->pos[2]= THEKERNEL->robot->from_millimeters(std::get<Z_AXIS>(wpos));
+        THEROBOT->arm_solution->actuator_to_cartesian(current_position, mpos);
+        Robot::wcs_t wpos= THEROBOT->mcs2wcs(mpos);
+        this->pos[0]= THEROBOT->from_millimeters(std::get<X_AXIS>(wpos));
+        this->pos[1]= THEROBOT->from_millimeters(std::get<Y_AXIS>(wpos));
+        this->pos[2]= THEROBOT->from_millimeters(std::get<Z_AXIS>(wpos));
 }
 
 // encoder tick, called in an interrupt everytime we get an encoder tick
@@ -156,7 +156,7 @@ void DirectJogScreen::tick(int change)
 {
     for (int i = 0; i < multiplier; ++i) {
         if(i != 0) wait_us(100);
-       THEKERNEL->robot->actuators[axis]->manual_step(change < 0);
+       THEROBOT->actuators[axis]->manual_step(change < 0);
     }
     pos_changed= true;
 }
index b505773..f603ea3 100644 (file)
@@ -59,22 +59,22 @@ void MainMenuScreen::setupConfigureScreen()
 
     // steps/mm
     mvs->addMenuItem("X steps/mm",
-        []() -> float { return THEKERNEL->robot->actuators[0]->get_steps_per_mm(); },
-        [](float v) { THEKERNEL->robot->actuators[0]->change_steps_per_mm(v); },
+        []() -> float { return THEROBOT->actuators[0]->get_steps_per_mm(); },
+        [](float v) { THEROBOT->actuators[0]->change_steps_per_mm(v); },
         0.1F,
         1.0F
         );
 
     mvs->addMenuItem("Y steps/mm",
-        []() -> float { return THEKERNEL->robot->actuators[1]->get_steps_per_mm(); },
-        [](float v) { THEKERNEL->robot->actuators[1]->change_steps_per_mm(v); },
+        []() -> float { return THEROBOT->actuators[1]->get_steps_per_mm(); },
+        [](float v) { THEROBOT->actuators[1]->change_steps_per_mm(v); },
         0.1F,
         1.0F
         );
 
     mvs->addMenuItem("Z steps/mm",
-        []() -> float { return THEKERNEL->robot->actuators[2]->get_steps_per_mm(); },
-        [](float v) { THEKERNEL->robot->actuators[2]->change_steps_per_mm(v); },
+        []() -> float { return THEROBOT->actuators[2]->get_steps_per_mm(); },
+        [](float v) { THEROBOT->actuators[2]->change_steps_per_mm(v); },
         0.1F,
         1.0F
         );
index d32de6e..3ebf922 100644 (file)
@@ -119,23 +119,23 @@ void WatchScreen::get_wpos()
     // get real time positions
     // current actuator position in mm
     ActuatorCoordinates current_position{
-        THEKERNEL->robot->actuators[X_AXIS]->get_current_position(),
-        THEKERNEL->robot->actuators[Y_AXIS]->get_current_position(),
-        THEKERNEL->robot->actuators[Z_AXIS]->get_current_position()
+        THEROBOT->actuators[X_AXIS]->get_current_position(),
+        THEROBOT->actuators[Y_AXIS]->get_current_position(),
+        THEROBOT->actuators[Z_AXIS]->get_current_position()
     };
 
     // get machine position from the actuator position using FK
     float mpos[3];
-    THEKERNEL->robot->arm_solution->actuator_to_cartesian(current_position, mpos);
-    Robot::wcs_t wpos= THEKERNEL->robot->mcs2wcs(mpos);
-    this->wpos[0]= THEKERNEL->robot->from_millimeters(std::get<X_AXIS>(wpos));
-    this->wpos[1]= THEKERNEL->robot->from_millimeters(std::get<Y_AXIS>(wpos));
-    this->wpos[2]= THEKERNEL->robot->from_millimeters(std::get<Z_AXIS>(wpos));
-    this->mpos[0]= THEKERNEL->robot->from_millimeters(mpos[0]);
-    this->mpos[1]= THEKERNEL->robot->from_millimeters(mpos[1]);
-    this->mpos[2]= THEKERNEL->robot->from_millimeters(mpos[2]);
+    THEROBOT->arm_solution->actuator_to_cartesian(current_position, mpos);
+    Robot::wcs_t wpos= THEROBOT->mcs2wcs(mpos);
+    this->wpos[0]= THEROBOT->from_millimeters(std::get<X_AXIS>(wpos));
+    this->wpos[1]= THEROBOT->from_millimeters(std::get<Y_AXIS>(wpos));
+    this->wpos[2]= THEROBOT->from_millimeters(std::get<Z_AXIS>(wpos));
+    this->mpos[0]= THEROBOT->from_millimeters(mpos[0]);
+    this->mpos[1]= THEROBOT->from_millimeters(mpos[1]);
+    this->mpos[2]= THEROBOT->from_millimeters(mpos[2]);
 
-    std::vector<Robot::wcs_t> v= THEKERNEL->robot->get_wcs_state();
+    std::vector<Robot::wcs_t> v= THEROBOT->get_wcs_state();
     char current_wcs= std::get<0>(v[0]);
     this->wcs= wcs2gcode(current_wcs);
 }
@@ -168,7 +168,7 @@ void WatchScreen::get_current_status()
 float WatchScreen::get_current_speed()
 {
     // in percent
-    return 6000.0F / THEKERNEL->robot->get_seconds_per_minute();
+    return 6000.0F / THEROBOT->get_seconds_per_minute();
 }
 
 void WatchScreen::get_sd_play_info()
@@ -191,13 +191,13 @@ void WatchScreen::display_menu_line(uint16_t line)
 {
     // in menu mode
     switch ( line ) {
-        case 0: THEPANEL->lcd->printf("     WCS      MCS %s", THEKERNEL->robot->inch_mode ? "in" : "mm"); break;
+        case 0: THEPANEL->lcd->printf("     WCS      MCS %s", THEROBOT->inch_mode ? "in" : "mm"); break;
         case 1: THEPANEL->lcd->printf("X %8.3f %8.3f", wpos[0], mpos[0]); break;
         case 2: THEPANEL->lcd->printf("Y %8.3f %8.3f", wpos[1], mpos[1]); break;
         case 3: THEPANEL->lcd->printf("Z %8.3f %8.3f", wpos[2], mpos[2]); break;
         case 4: THEPANEL->lcd->printf("%s F%6.1f/%6.1f", this->wcs.c_str(), // display requested feedrate and actual feedrate
-            THEKERNEL->robot->from_millimeters(THEKERNEL->robot->get_feed_rate()),
-            THEKERNEL->robot->from_millimeters(THEKERNEL->conveyor->get_current_feedrate()*60.0F));
+            THEROBOT->from_millimeters(THEROBOT->get_feed_rate()),
+            THEROBOT->from_millimeters(THEKERNEL->conveyor->get_current_feedrate()*60.0F));
             break;
         case 5: THEPANEL->lcd->printf("%3d%% %2lu:%02lu %3u%% sd", this->current_speed, this->elapsed_time / 60, this->elapsed_time % 60, this->sd_pcnt_played); break;
         case 6: THEPANEL->lcd->printf("%19s", this->get_status()); break;
index 89a8623..5424b39 100644 (file)
@@ -214,7 +214,7 @@ void Player::on_gcode_received(void *argument)
             if(this->suspended) {
                 // clean up
                 this->suspended= false;
-                THEKERNEL->robot->pop_state();
+                THEROBOT->pop_state();
                 this->saved_temperatures.clear();
                 this->was_playing_file= false;
                 this->suspend_loops= 0;
@@ -366,7 +366,7 @@ void Player::abort_command( string parameters, StreamOutput *stream )
         THEKERNEL->conveyor->flush_queue();
 
         // now the position will think it is at the last received pos, so we need to do FK to get the actuator position and reset the current position
-        THEKERNEL->robot->reset_position_from_current_actuator_position();
+        THEROBOT->reset_position_from_current_actuator_position();
     }
     stream->printf("Aborted playing or paused file. Please turn any heaters off manually\r\n");
 }
@@ -529,13 +529,13 @@ void Player::suspend_part2()
     THEKERNEL->streams->printf("// Saving current state...\n");
 
     // save current XYZ position
-    THEKERNEL->robot->get_axis_position(this->saved_position);
+    THEROBOT->get_axis_position(this->saved_position);
 
     // save current extruder state
     PublicData::set_value( extruder_checksum, save_state_checksum, nullptr );
 
     // save state use M120
-    THEKERNEL->robot->push_state();
+    THEROBOT->push_state();
 
     // TODO retract by optional amount...
 
@@ -623,7 +623,7 @@ void Player::resume_command(string parameters, StreamOutput *stream )
             if(THEKERNEL->is_halted()) {
                 // abort temp wait and rest of resume
                 THEKERNEL->streams->printf("Resume aborted by kill\n");
-                THEKERNEL->robot->pop_state();
+                THEROBOT->pop_state();
                 this->saved_temperatures.clear();
                 suspended= false;
                 return;
@@ -642,10 +642,10 @@ void Player::resume_command(string parameters, StreamOutput *stream )
 
     // Restore position
     stream->printf("Restoring saved XYZ positions and state...\n");
-    THEKERNEL->robot->pop_state();
-    bool abs_mode= THEKERNEL->robot->absolute_mode; // what mode we were in
+    THEROBOT->pop_state();
+    bool abs_mode= THEROBOT->absolute_mode; // what mode we were in
     // force absolute mode for restoring position, then set to the saved relative/absolute mode
-    THEKERNEL->robot->absolute_mode= true;
+    THEROBOT->absolute_mode= true;
     {
         // NOTE position was saved in MCS so must use G53 to restore position
         char buf[128];
@@ -655,7 +655,7 @@ void Player::resume_command(string parameters, StreamOutput *stream )
         message.stream = &(StreamOutput::NullStream);
         THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message );
     }
-    THEKERNEL->robot->absolute_mode= abs_mode;
+    THEROBOT->absolute_mode= abs_mode;
 
     // restore extruder state
     PublicData::set_value( extruder_checksum, restore_state_checksum, nullptr );
index ba22f24..0ff9fb8 100644 (file)
@@ -669,7 +669,7 @@ void SimpleShell::grblDP_command( string parameters, StreamOutput *stream)
 
     bool verbose = shift_parameter( parameters ).find_first_of("Vv") != string::npos;
 
-    std::vector<Robot::wcs_t> v= THEKERNEL->robot->get_wcs_state();
+    std::vector<Robot::wcs_t> v= THEROBOT->get_wcs_state();
     if(verbose) {
         char current_wcs= std::get<0>(v[0]);
         stream->printf("[current WCS: %s]\n", wcs2gcode(current_wcs).c_str());
@@ -678,39 +678,39 @@ void SimpleShell::grblDP_command( string parameters, StreamOutput *stream)
     int n= std::get<1>(v[0]);
     for (int i = 1; i <= n; ++i) {
         stream->printf("[%s:%1.4f,%1.4f,%1.4f]\n", wcs2gcode(i-1).c_str(),
-            THEKERNEL->robot->from_millimeters(std::get<0>(v[i])),
-            THEKERNEL->robot->from_millimeters(std::get<1>(v[i])),
-            THEKERNEL->robot->from_millimeters(std::get<2>(v[i])));
+            THEROBOT->from_millimeters(std::get<0>(v[i])),
+            THEROBOT->from_millimeters(std::get<1>(v[i])),
+            THEROBOT->from_millimeters(std::get<2>(v[i])));
     }
 
     float *rd;
     PublicData::get_value( endstops_checksum, saved_position_checksum, &rd );
     stream->printf("[G28:%1.4f,%1.4f,%1.4f]\n",
-        THEKERNEL->robot->from_millimeters(rd[0]),
-        THEKERNEL->robot->from_millimeters(rd[1]),
-        THEKERNEL->robot->from_millimeters(rd[2]));
+        THEROBOT->from_millimeters(rd[0]),
+        THEROBOT->from_millimeters(rd[1]),
+        THEROBOT->from_millimeters(rd[2]));
 
     stream->printf("[G30:%1.4f,%1.4f,%1.4f]\n",  0.0F, 0.0F, 0.0F); // not implemented
 
     stream->printf("[G92:%1.4f,%1.4f,%1.4f]\n",
-        THEKERNEL->robot->from_millimeters(std::get<0>(v[n+1])),
-        THEKERNEL->robot->from_millimeters(std::get<1>(v[n+1])),
-        THEKERNEL->robot->from_millimeters(std::get<2>(v[n+1])));
+        THEROBOT->from_millimeters(std::get<0>(v[n+1])),
+        THEROBOT->from_millimeters(std::get<1>(v[n+1])),
+        THEROBOT->from_millimeters(std::get<2>(v[n+1])));
 
     if(verbose) {
         stream->printf("[Tool Offset:%1.4f,%1.4f,%1.4f]\n",
-            THEKERNEL->robot->from_millimeters(std::get<0>(v[n+2])),
-            THEKERNEL->robot->from_millimeters(std::get<1>(v[n+2])),
-            THEKERNEL->robot->from_millimeters(std::get<2>(v[n+2])));
+            THEROBOT->from_millimeters(std::get<0>(v[n+2])),
+            THEROBOT->from_millimeters(std::get<1>(v[n+2])),
+            THEROBOT->from_millimeters(std::get<2>(v[n+2])));
     }else{
-        stream->printf("[TL0:%1.4f]\n", THEKERNEL->robot->from_millimeters(std::get<2>(v[n+2])));
+        stream->printf("[TL0:%1.4f]\n", THEROBOT->from_millimeters(std::get<2>(v[n+2])));
     }
 
     // this is the last probe position, updated when a probe completes, also stores the number of steps moved after a homing cycle
     float px, py, pz;
     uint8_t ps;
-    std::tie(px, py, pz, ps) = THEKERNEL->robot->get_last_probe_position();
-    stream->printf("[PRB:%1.4f,%1.4f,%1.4f:%d]\n", THEKERNEL->robot->from_millimeters(px), THEKERNEL->robot->from_millimeters(py), THEKERNEL->robot->from_millimeters(pz), ps);
+    std::tie(px, py, pz, ps) = THEROBOT->get_last_probe_position();
+    stream->printf("[PRB:%1.4f,%1.4f,%1.4f:%d]\n", THEROBOT->from_millimeters(px), THEROBOT->from_millimeters(py), THEROBOT->from_millimeters(pz), ps);
 }
 
 void SimpleShell::get_command( string parameters, StreamOutput *stream)
@@ -765,12 +765,12 @@ void SimpleShell::get_command( string parameters, StreamOutput *stream)
             // do forward kinematics on the given actuator position and display the cartesian coordinates
             ActuatorCoordinates apos{x, y, z};
             float pos[3];
-            THEKERNEL->robot->arm_solution->actuator_to_cartesian(apos, pos);
+            THEROBOT->arm_solution->actuator_to_cartesian(apos, pos);
             stream->printf("cartesian= X %f, Y %f, Z %f, Steps= A %lu, B %lu, C %lu\n",
                 pos[0], pos[1], pos[2],
-                lroundf(x*THEKERNEL->robot->actuators[0]->get_steps_per_mm()),
-                lroundf(y*THEKERNEL->robot->actuators[1]->get_steps_per_mm()),
-                lroundf(z*THEKERNEL->robot->actuators[2]->get_steps_per_mm()));
+                lroundf(x*THEROBOT->actuators[0]->get_steps_per_mm()),
+                lroundf(y*THEROBOT->actuators[1]->get_steps_per_mm()),
+                lroundf(z*THEROBOT->actuators[2]->get_steps_per_mm()));
             x= pos[0];
             y= pos[1];
             z= pos[2];
@@ -779,7 +779,7 @@ void SimpleShell::get_command( string parameters, StreamOutput *stream)
             // do inverse kinematics on the given cartesian position and display the actuator coordinates
             float pos[3]{x, y, z};
             ActuatorCoordinates apos;
-            THEKERNEL->robot->arm_solution->cartesian_to_actuator(pos, apos);
+            THEROBOT->arm_solution->cartesian_to_actuator(pos, apos);
             stream->printf("actuator= A %f, B %f, C %f\n", apos[0], apos[1], apos[2]);
         }
 
@@ -797,12 +797,12 @@ void SimpleShell::get_command( string parameters, StreamOutput *stream)
    } else if (what == "pos") {
         // convenience to call all the various M114 variants
         char buf[64];
-        THEKERNEL->robot->print_position(0, buf, sizeof buf); stream->printf("last %s\n", buf);
-        THEKERNEL->robot->print_position(1, buf, sizeof buf); stream->printf("realtime %s\n", buf);
-        THEKERNEL->robot->print_position(2, buf, sizeof buf); stream->printf("%s\n", buf);
-        THEKERNEL->robot->print_position(3, buf, sizeof buf); stream->printf("%s\n", buf);
-        THEKERNEL->robot->print_position(4, buf, sizeof buf); stream->printf("%s\n", buf);
-        THEKERNEL->robot->print_position(5, buf, sizeof buf); stream->printf("%s\n", buf);
+        THEROBOT->print_position(0, buf, sizeof buf); stream->printf("last %s\n", buf);
+        THEROBOT->print_position(1, buf, sizeof buf); stream->printf("realtime %s\n", buf);
+        THEROBOT->print_position(2, buf, sizeof buf); stream->printf("%s\n", buf);
+        THEROBOT->print_position(3, buf, sizeof buf); stream->printf("%s\n", buf);
+        THEROBOT->print_position(4, buf, sizeof buf); stream->printf("%s\n", buf);
+        THEROBOT->print_position(5, buf, sizeof buf); stream->printf("%s\n", buf);
 
     } else if (what == "wcs") {
         // print the wcs state
@@ -813,14 +813,14 @@ void SimpleShell::get_command( string parameters, StreamOutput *stream)
         // [G0 G54 G17 G21 G90 G94 M0 M5 M9 T0 F0.]
         stream->printf("[G%d %s G%d G%d G%d G94 M0 M5 M9 T%d F%1.4f]\n",
             THEKERNEL->gcode_dispatch->get_modal_command(),
-            wcs2gcode(THEKERNEL->robot->get_current_wcs()).c_str(),
-            THEKERNEL->robot->plane_axis_0 == X_AXIS && THEKERNEL->robot->plane_axis_1 == Y_AXIS && THEKERNEL->robot->plane_axis_2 == Z_AXIS ? 17 :
-              THEKERNEL->robot->plane_axis_0 == X_AXIS && THEKERNEL->robot->plane_axis_1 == Z_AXIS && THEKERNEL->robot->plane_axis_2 == Y_AXIS ? 18 :
-              THEKERNEL->robot->plane_axis_0 == Y_AXIS && THEKERNEL->robot->plane_axis_1 == Z_AXIS && THEKERNEL->robot->plane_axis_2 == X_AXIS ? 19 : 17,
-            THEKERNEL->robot->inch_mode ? 20 : 21,
-            THEKERNEL->robot->absolute_mode ? 90 : 91,
+            wcs2gcode(THEROBOT->get_current_wcs()).c_str(),
+            THEROBOT->plane_axis_0 == X_AXIS && THEROBOT->plane_axis_1 == Y_AXIS && THEROBOT->plane_axis_2 == Z_AXIS ? 17 :
+              THEROBOT->plane_axis_0 == X_AXIS && THEROBOT->plane_axis_1 == Z_AXIS && THEROBOT->plane_axis_2 == Y_AXIS ? 18 :
+              THEROBOT->plane_axis_0 == Y_AXIS && THEROBOT->plane_axis_1 == Z_AXIS && THEROBOT->plane_axis_2 == X_AXIS ? 19 : 17,
+            THEROBOT->inch_mode ? 20 : 21,
+            THEROBOT->absolute_mode ? 90 : 91,
             get_active_tool(),
-            THEKERNEL->robot->from_millimeters(THEKERNEL->robot->get_feed_rate()));
+            THEROBOT->from_millimeters(THEROBOT->get_feed_rate()));
 
     } else if (what == "status") {
         // also ? on serial and usb
@@ -949,7 +949,7 @@ void SimpleShell::test_command( string parameters, StreamOutput *stream)
             return;
         }
         float d= strtof(dist.c_str(), NULL);
-        float f= speed.empty() ? THEKERNEL->robot->get_feed_rate() : strtof(speed.c_str(), NULL);
+        float f= speed.empty() ? THEROBOT->get_feed_rate() : strtof(speed.c_str(), NULL);
         uint32_t n= strtol(iters.c_str(), NULL, 10);
 
         bool toggle= false;
@@ -977,7 +977,7 @@ void SimpleShell::test_command( string parameters, StreamOutput *stream)
 
         float r= strtof(radius.c_str(), NULL);
         uint32_t n= strtol(iters.c_str(), NULL, 10);
-        float f= speed.empty() ? THEKERNEL->robot->get_feed_rate() : strtof(speed.c_str(), NULL);
+        float f= speed.empty() ? THEROBOT->get_feed_rate() : strtof(speed.c_str(), NULL);
 
         char cmd[64];
         snprintf(cmd, sizeof(cmd), "G0 X%f Y0 F%f", -r, f);
@@ -1005,7 +1005,7 @@ void SimpleShell::test_command( string parameters, StreamOutput *stream)
             return;
         }
         float d= strtof(size.c_str(), NULL);
-        float f= speed.empty() ? THEKERNEL->robot->get_feed_rate() : strtof(speed.c_str(), NULL);
+        float f= speed.empty() ? THEROBOT->get_feed_rate() : strtof(speed.c_str(), NULL);
         uint32_t n= strtol(iters.c_str(), NULL, 10);
 
         for (uint32_t i = 0; i < n; ++i) {