diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..6553990d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,4 @@
+root = true
+
+[*]
+insert_final_newline = true
\ No newline at end of file
diff --git a/Grbl_Esp32/src/Motors/Motor.cpp b/Grbl_Esp32/src/Motors/Motor.cpp
new file mode 100644
index 00000000..e3ba33fe
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/Motor.cpp
@@ -0,0 +1,53 @@
+/*
+ MotorClass.cpp
+ Part of Grbl_ESP32
+ 2020 - Bart Dring
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+ TODO
+ Make sure public/private/protected is cleaned up.
+ Only a few Unipolar axes have been setup in init()
+ Get rid of Z_SERVO, just reply on Z_SERVO_PIN
+ Deal with custom machine ... machine_trinamic_setup();
+ Class is ready to deal with non SPI pins, but they have not been needed yet.
+ It would be nice in the config message though
+ Testing
+ Done (success)
+ 3 Axis (3 Standard Steppers)
+ MPCNC (ganged with shared direction pin)
+ TMC2130 Pen Laser (trinamics, stallguard tuning)
+ Unipolar
+ TODO
+ 4 Axis SPI (Daisy Chain, Ganged with unique direction pins)
+ Reference
+ TMC2130 Datasheet https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf
+*/
+
+#include "Motor.h"
+
+namespace Motors {
+ Motor::Motor() { type_id = MOTOR; }
+
+ void Motor::init() { _homing_mask = 0; }
+
+ void Motor::config_message() {}
+ void Motor::debug_message() {}
+ void Motor::read_settings() {}
+ void Motor::set_disable(bool disable) {}
+ void Motor::set_direction_pins(uint8_t onMask) {}
+ void Motor::step(uint8_t step_mask, uint8_t dir_mask) {}
+ bool Motor::test() { return true; }; // true = OK
+ void Motor::update() {}
+
+ void Motor::set_axis_name() { sprintf(_axis_name, "%c%s", report_get_axis_letter(axis_index), dual_axis_index ? "2" : ""); }
+
+ void Motor::set_homing_mode(uint8_t homing_mask, bool isHoming) { _homing_mask = homing_mask; }
+}
diff --git a/Grbl_Esp32/src/Motors/Motor.h b/Grbl_Esp32/src/Motors/Motor.h
new file mode 100644
index 00000000..f3bf3629
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/Motor.h
@@ -0,0 +1,65 @@
+#pragma once
+
+/*
+ Motor.h
+ Header file for Motor Classes
+ Here is the hierarchy
+ Motor
+ Nullmotor
+ StandardStepper
+ TrinamicDriver
+ Unipolar
+ RC Servo
+
+ These are for motors coordinated by Grbl_ESP32
+ See motorClass.cpp for more details
+
+ Part of Grbl_ESP32
+ 2020 - Bart Dring
+
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+*/
+
+#include "Motors.h"
+
+#include
+
+namespace Motors {
+ class Motor {
+ public:
+ Motor();
+
+ virtual void init(); // not in constructor because this also gets called when $$ settings change
+ virtual void config_message();
+ virtual void debug_message();
+ virtual void read_settings();
+ virtual void set_homing_mode(uint8_t homing_mask, bool isHoming);
+ virtual void set_disable(bool disable);
+ virtual void set_direction_pins(uint8_t onMask);
+ virtual void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now
+ virtual bool test();
+ virtual void set_axis_name();
+ virtual void update();
+
+ motor_class_id_t type_id;
+ uint8_t is_active = false;
+
+ protected:
+ uint8_t axis_index; // X_AXIS, etc
+ uint8_t dual_axis_index; // 0 = primary 1=ganged
+
+ bool _showError;
+ bool _use_mpos = true;
+ uint8_t _homing_mask;
+ char _axis_name[10]; // this the name to use when reporting like "X" or "X2"
+ };
+}
diff --git a/Grbl_Esp32/src/Motors/MotorClass.h b/Grbl_Esp32/src/Motors/MotorClass.h
deleted file mode 100644
index a7d93b63..00000000
--- a/Grbl_Esp32/src/Motors/MotorClass.h
+++ /dev/null
@@ -1,205 +0,0 @@
-#pragma once
-
-/*
- MotorClass.h
- Header file for Motor Classes
- Here is the hierarchy
- Motor
- Nullmotor
- StandardStepper
- TrinamicDriver
- Unipolar
- RC Servo
-
- These are for motors coordinated by Grbl_ESP32
- See motorClass.cpp for more details
-
- Part of Grbl_ESP32
- 2020 - Bart Dring
-
- Grbl is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Grbl is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Grbl. If not, see .
-*/
-
-#include "../grbl.h"
-#include // https://github.com/teemuatlut/TMCStepper
-#include "TrinamicDriverClass.h"
-#include "RcServoClass.h"
-//#include "SolenoidClass.h"
-
-extern uint8_t rmt_chan_num[MAX_AXES][2];
-extern rmt_item32_t rmtItem[2];
-extern rmt_config_t rmtConfig;
-
-typedef enum { MOTOR, NULL_MOTOR, STANDARD_MOTOR, TRINAMIC_SPI_MOTOR, UNIPOLAR_MOTOR, RC_SERVO_MOTOR, SOLENOID } motor_class_id_t;
-
-// These are used for setup and to talk to the motors as a group.
-void init_motors();
-uint8_t get_next_trinamic_driver_index();
-bool motors_have_type_id(motor_class_id_t id);
-void readSgTask(void* pvParameters);
-void motors_read_settings();
-void motors_set_homing_mode(uint8_t homing_mask, bool isHoming);
-void motors_set_disable(bool disable);
-void motors_set_direction_pins(uint8_t onMask);
-void motors_step(uint8_t step_mask, uint8_t dir_mask);
-void servoUpdateTask(void* pvParameters);
-
-extern bool motor_class_steps; // true if at least one motor class is handling steps
-
-// ==================== Motor Classes ====================
-
-class Motor {
-public:
- Motor();
-
- virtual void init(); // not in constructor because this also gets called when $$ settings change
- virtual void config_message();
- virtual void debug_message();
- virtual void read_settings();
- virtual void set_homing_mode(uint8_t homing_mask, bool isHoming);
- virtual void set_disable(bool disable);
- virtual void set_direction_pins(uint8_t onMask);
- virtual void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now
- virtual bool test();
- virtual void set_axis_name();
- virtual void update();
-
- motor_class_id_t type_id;
- uint8_t is_active = false;
-
-protected:
- uint8_t axis_index; // X_AXIS, etc
- uint8_t dual_axis_index; // 0 = primary 1=ganged
-
- bool _showError;
- bool _use_mpos = true;
- uint8_t _homing_mask;
- char _axis_name[10]; // this the name to use when reporting like "X" or "X2"
-};
-
-class Nullmotor : public Motor {};
-
-class StandardStepper : public Motor {
-public:
- StandardStepper();
- StandardStepper(uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin);
-
- virtual void config_message();
- virtual void init();
- virtual void set_direction_pins(uint8_t onMask);
- void init_step_dir_pins();
- virtual void set_disable(bool disable);
- uint8_t step_pin;
-
-protected:
- bool _invert_step_pin;
- uint8_t dir_pin;
- uint8_t disable_pin;
-};
-
-class TrinamicDriver : public StandardStepper {
-public:
- TrinamicDriver(uint8_t axis_index,
- uint8_t step_pin,
- uint8_t dir_pin,
- uint8_t disable_pin,
- uint8_t cs_pin,
- uint16_t driver_part_number,
- float r_sense,
- int8_t spi_index);
-
- void config_message();
- void init();
- void set_mode(bool isHoming);
- void read_settings();
- void trinamic_test_response();
- void trinamic_stepper_enable(bool enable);
- void debug_message();
- void set_homing_mode(uint8_t homing_mask, bool ishoming);
- void set_disable(bool disable);
- bool test();
-
-private:
- uint32_t calc_tstep(float speed, float percent);
-
- TMC2130Stepper* tmcstepper; // all other driver types are subclasses of this one
- uint8_t _homing_mode;
- uint8_t cs_pin = UNDEFINED_PIN; // The chip select pin (can be the same for daisy chain)
- uint16_t _driver_part_number; // example: use 2130 for TMC2130
- float _r_sense;
- int8_t spi_index;
-
-protected:
- uint8_t _mode;
- uint8_t _lastMode = 255;
-};
-
-class UnipolarMotor : public Motor {
-public:
- UnipolarMotor();
- UnipolarMotor(uint8_t axis_index, uint8_t pin_phase0, uint8_t pin_phase1, uint8_t pin_phase2, uint8_t pin_phase3);
- void init();
- void config_message();
- void set_disable(bool disable);
- void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now
-
-private:
- uint8_t _pin_phase0;
- uint8_t _pin_phase1;
- uint8_t _pin_phase2;
- uint8_t _pin_phase3;
- uint8_t _current_phase;
- bool _half_step;
- bool _enabled;
-};
-
-class RcServo : public Motor {
-public:
- RcServo();
- RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max);
- virtual void config_message();
- virtual void init();
- void _write_pwm(uint32_t duty);
- virtual void set_disable(bool disable);
- virtual void update();
- void read_settings();
- void set_homing_mode(bool is_homing, bool isHoming);
-
-protected:
- void set_location();
- void _get_calibration();
-
- uint8_t _pwm_pin;
- uint8_t _channel_num;
- uint32_t _current_pwm_duty;
- bool _disabled;
-
- float _position_min;
- float _position_max; // position in millimeters
- float _homing_position;
-
- float _pwm_pulse_min;
- float _pwm_pulse_max;
-};
-
-class Solenoid : public RcServo {
-public:
- Solenoid();
- Solenoid(uint8_t axis_index, gpio_num_t pwm_pin, float transition_poiont);
- void config_message();
- void set_location();
- void update();
- void init();
- void set_disable(bool disable);
-
- float _transition_poiont;
-};
diff --git a/Grbl_Esp32/src/Motors/MotorClass.cpp b/Grbl_Esp32/src/Motors/Motors.cpp
similarity index 87%
rename from Grbl_Esp32/src/Motors/MotorClass.cpp
rename to Grbl_Esp32/src/Motors/Motors.cpp
index b5d1dfe6..2a54e455 100644
--- a/Grbl_Esp32/src/Motors/MotorClass.cpp
+++ b/Grbl_Esp32/src/Motors/Motors.cpp
@@ -1,40 +1,48 @@
/*
- MotorClass.cpp
- Part of Grbl_ESP32
- 2020 - Bart Dring
- Grbl is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Grbl is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Grbl. If not, see .
- TODO
- Make sure public/private/protected is cleaned up.
- Only a few Unipolar axes have been setup in init()
- Get rid of Z_SERVO, just reply on Z_SERVO_PIN
- Deal with custom machine ... machine_trinamic_setup();
- Class is ready to deal with non SPI pins, but they have not been needed yet.
- It would be nice in the config message though
- Testing
- Done (success)
- 3 Axis (3 Standard Steppers)
- MPCNC (ganged with shared direction pin)
- TMC2130 Pen Laser (trinamics, stallguard tuning)
- Unipolar
- TODO
- 4 Axis SPI (Daisy Chain, Ganged with unique direction pins)
- Reference
- TMC2130 Datasheet https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf
+ MotorClass.cpp
+ Part of Grbl_ESP32
+ 2020 - Bart Dring
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+ TODO
+ Make sure public/private/protected is cleaned up.
+ Only a few Unipolar axes have been setup in init()
+ Get rid of Z_SERVO, just reply on Z_SERVO_PIN
+ Deal with custom machine ... machine_trinamic_setup();
+ Class is ready to deal with non SPI pins, but they have not been needed yet.
+ It would be nice in the config message though
+ Testing
+ Done (success)
+ 3 Axis (3 Standard Steppers)
+ MPCNC (ganged with shared direction pin)
+ TMC2130 Pen Laser (trinamics, stallguard tuning)
+ Unipolar
+ TODO
+ 4 Axis SPI (Daisy Chain, Ganged with unique direction pins)
+ Reference
+ TMC2130 Datasheet https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf
*/
-#include "../grbl.h"
-#include "MotorClass.h"
+#include "Motors.h"
-Motor* myMotor[MAX_AXES][MAX_GANGED]; // number of axes (normal and ganged)
+#include "Motor.h"
+#include "../grbl.h"
+
+#include "NullMotor.h"
+#include "StandardStepper.h"
+#include "UnipolarMotor.h"
+#include "RcServo.h"
+#include "TrinamicDriver.h"
+
+Motors::Motor* myMotor[MAX_AXES][MAX_GANGED]; // number of axes (normal and ganged)
static TaskHandle_t readSgTaskHandle = 0; // for realtime stallguard data diaplay
static TaskHandle_t servoUpdateTaskHandle = 0;
@@ -45,6 +53,8 @@ rmt_config_t rmtConfig;
bool motor_class_steps; // true if at least one motor class is handling steps
void init_motors() {
+ using namespace Motors;
+
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Init Motors");
#ifdef X_TRINAMIC_DRIVER
@@ -402,7 +412,7 @@ void motors_step(uint8_t step_mask, uint8_t dir_mask) {
}
/*
- This will print StallGuard data that is useful for tuning.
+ This will print StallGuard data that is useful for tuning.
*/
void readSgTask(void* pvParameters) {
TickType_t xLastWakeTime;
@@ -439,32 +449,3 @@ void TMC2130Stepper::switchCSpin(bool state) {
i2s_out_delay();
}
#endif
-
-// ============================== Class Methods ================================================
-
-Motor ::Motor() {
- type_id = MOTOR;
-}
-
-void Motor ::init() {
- _homing_mask = 0;
-}
-
-void Motor ::config_message() {}
-void Motor ::debug_message() {}
-void Motor ::read_settings() {}
-void Motor ::set_disable(bool disable) {}
-void Motor ::set_direction_pins(uint8_t onMask) {}
-void Motor ::step(uint8_t step_mask, uint8_t dir_mask) {}
-bool Motor ::test() {
- return true;
-}; // true = OK
-void Motor ::update() {}
-
-void Motor ::set_axis_name() {
- sprintf(_axis_name, "%c%s", report_get_axis_letter(axis_index), dual_axis_index ? "2" : "");
-}
-
-void Motor ::set_homing_mode(uint8_t homing_mask, bool isHoming) {
- _homing_mask = homing_mask;
-}
diff --git a/Grbl_Esp32/src/Motors/Motors.h b/Grbl_Esp32/src/Motors/Motors.h
new file mode 100644
index 00000000..dafcf6a1
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/Motors.h
@@ -0,0 +1,53 @@
+#pragma once
+
+/*
+ Motor.h
+ Header file for Motor Classes
+ Here is the hierarchy
+ Motor
+ Nullmotor
+ StandardStepper
+ TrinamicDriver
+ Unipolar
+ RC Servo
+
+ These are for motors coordinated by Grbl_ESP32
+ See motorClass.cpp for more details
+
+ Part of Grbl_ESP32
+ 2020 - Bart Dring
+
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+*/
+
+#include "../grbl.h"
+#include // https://github.com/teemuatlut/TMCStepper
+
+extern uint8_t rmt_chan_num[MAX_AXES][2];
+extern rmt_item32_t rmtItem[2];
+extern rmt_config_t rmtConfig;
+
+typedef enum { MOTOR, NULL_MOTOR, STANDARD_MOTOR, TRINAMIC_SPI_MOTOR, UNIPOLAR_MOTOR, RC_SERVO_MOTOR, SOLENOID } motor_class_id_t;
+
+// These are used for setup and to talk to the motors as a group.
+void init_motors();
+uint8_t get_next_trinamic_driver_index();
+bool motors_have_type_id(motor_class_id_t id);
+void readSgTask(void* pvParameters);
+void motors_read_settings();
+void motors_set_homing_mode(uint8_t homing_mask, bool isHoming);
+void motors_set_disable(bool disable);
+void motors_set_direction_pins(uint8_t onMask);
+void motors_step(uint8_t step_mask, uint8_t dir_mask);
+void servoUpdateTask(void* pvParameters);
+
+extern bool motor_class_steps; // true if at least one motor class is handling steps
diff --git a/Grbl_Esp32/src/Motors/NullMotor.h b/Grbl_Esp32/src/Motors/NullMotor.h
new file mode 100644
index 00000000..e360392d
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/NullMotor.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "Motor.h"
+
+namespace Motors {
+ class Nullmotor : public Motor {};
+}
diff --git a/Grbl_Esp32/src/Motors/RcServo.cpp b/Grbl_Esp32/src/Motors/RcServo.cpp
new file mode 100644
index 00000000..719eaf1b
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/RcServo.cpp
@@ -0,0 +1,189 @@
+/*
+ RcServoServoClass.cpp
+
+ This allows an RcServo to be used like any other motor. Serrvos
+ do have limitation in travel and speed, so you do need to respect that.
+
+ Part of Grbl_ESP32
+
+ 2020 - Bart Dring
+
+ Servos have a limited travel, so they map the travel across a range in
+ the current work coordinatee system. The servo can only travel as far
+ as the range, but the internal axis value can keep going.
+
+ Range: The range is specified in the machine definition file with...
+ #define X_SERVO_RANGE_MIN 0.0
+ #define X_SERVO_RANGE_MAX 5.0
+
+ Direction: The direction can be changed using the $3 setting for the axis
+
+ Homing: During homing, the servo will move to one of the endpoints. The
+ endpoint is determined by the $23 or $HomingDirInvertMask setting for the axis.
+ Do not define a homing cycle for the axis with the servo.
+ You do need at least 1 homing cycle. TODO: Fix this
+
+ Calibration. You can tweak the endpoints using the $10n or nStepsPerMm and
+ $13n or $xMaxTravel setting, where n is the axis.
+ The value is a percent. If you secify a percent outside the
+ the range specified by the values below, it will be reset to 100.0 (100% ... no change)
+ The calibration adjusts in direction of positive momement, so a value above 100% moves
+ towards the higher axis value.
+
+ #define SERVO_CAL_MIN
+ #define SERVO_CAL_MAX
+
+ Grbl_ESP32 is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+*/
+
+#include "RcServo.h"
+
+namespace Motors {
+ RcServo::RcServo() {}
+
+ RcServo::RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max) {
+ type_id = RC_SERVO_MOTOR;
+ this->axis_index = axis_index % MAX_AXES;
+ this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged
+ this->_pwm_pin = pwm_pin;
+ _position_min = min;
+ _position_max = max;
+ init();
+ }
+
+ void RcServo::init() {
+ read_settings();
+ _channel_num = sys_get_next_PWM_chan_num();
+ ledcSetup(_channel_num, SERVO_PULSE_FREQ, SERVO_PULSE_RES_BITS);
+ ledcAttachPin(_pwm_pin, _channel_num);
+ _current_pwm_duty = 0;
+ is_active = true; // as opposed to NullMotors, this is a real motor
+ set_axis_name();
+ config_message();
+ }
+
+ void RcServo::config_message() {
+ grbl_msg_sendf(CLIENT_SERIAL,
+ MSG_LEVEL_INFO,
+ "%s Axis RC Servo motor Output:%d Min:%5.3fmm Max:%5.3fmm",
+ _axis_name,
+ _pwm_pin,
+ _position_min,
+ _position_max);
+ }
+
+ void RcServo::_write_pwm(uint32_t duty) {
+ // to prevent excessive calls to ledcWrite, make sure duty hass changed
+ if (duty == _current_pwm_duty)
+ return;
+
+ _current_pwm_duty = duty;
+
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Servo Pwm %d", _axis_name, duty);
+ ledcWrite(_channel_num, duty);
+ }
+
+ // sets the PWM to zero. This allows most servos to be manually moved
+ void RcServo::set_disable(bool disable) {
+ return;
+ _disabled = disable;
+ if (_disabled)
+ _write_pwm(0);
+ }
+
+ void RcServo::set_homing_mode(bool is_homing, bool isHoming) {
+ float home_pos = 0.0;
+
+ if (!is_homing)
+ return;
+
+ if (bit_istrue(homing_dir_mask->get(), bit(axis_index)))
+ home_pos = _position_min;
+ else
+ home_pos = _position_max;
+
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo set home %d %3.2f", is_homing, home_pos);
+ sys_position[axis_index] = home_pos * axis_settings[axis_index]->steps_per_mm->get(); // convert to steps
+ }
+
+ void RcServo::update() { set_location(); }
+
+ void RcServo::set_location() {
+ uint32_t servo_pulse_len;
+ float servo_pos, mpos, offset;
+ // skip location if we are in alarm mode
+
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "locate");
+ _get_calibration();
+
+ if (sys.state == STATE_ALARM) {
+ set_disable(true);
+ return;
+ }
+
+ mpos = system_convert_axis_steps_to_mpos(sys_position, axis_index); // get the axis machine position in mm
+ offset = gc_state.coord_system[axis_index] + gc_state.coord_offset[axis_index]; // get the current axis work offset
+ servo_pos = mpos - offset; // determine the current work position
+
+ // determine the pulse length
+ servo_pulse_len = (uint32_t)mapConstrain(servo_pos, _position_min, _position_max, _pwm_pulse_min, _pwm_pulse_max);
+
+ _write_pwm(servo_pulse_len);
+ }
+
+ void RcServo::read_settings() { _get_calibration(); }
+
+ // this should change to use its own settings.
+ void RcServo::_get_calibration() {
+ float _cal_min = 1.0;
+ float _cal_max = 1.0;
+
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Read settings");
+
+ // make sure the min is in range
+ if ((axis_settings[axis_index]->steps_per_mm->get() < SERVO_CAL_MIN) ||
+ (axis_settings[axis_index]->steps_per_mm->get() > SERVO_CAL_MAX)) {
+ grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration ($10%d) value error. Reset to 100", axis_index);
+ char reset_val[] = "100";
+ axis_settings[axis_index]->steps_per_mm->setStringValue(reset_val);
+ }
+
+ // make sure the max is in range
+ // Note: Max travel is set positive via $$, but stored as a negative number
+ if ((axis_settings[axis_index]->max_travel->get() < SERVO_CAL_MIN) || (axis_settings[axis_index]->max_travel->get() > SERVO_CAL_MAX)) {
+ grbl_msg_sendf(CLIENT_SERIAL,
+ MSG_LEVEL_INFO,
+ "Servo calibration ($13%d) value error. %3.2f Reset to 100",
+ axis_index,
+ axis_settings[axis_index]->max_travel->get());
+ char reset_val[] = "100";
+ axis_settings[axis_index]->max_travel->setStringValue(reset_val);
+ }
+
+ _pwm_pulse_min = SERVO_MIN_PULSE;
+ _pwm_pulse_max = SERVO_MAX_PULSE;
+
+ if (bit_istrue(dir_invert_mask->get(), bit(axis_index))) { // normal direction
+ _cal_min = 2.0 - (axis_settings[axis_index]->steps_per_mm->get() / 100.0);
+ _cal_max = 2.0 - (axis_settings[axis_index]->max_travel->get() / 100.0);
+ swap(_pwm_pulse_min, _pwm_pulse_max);
+ } else { // inverted direction
+ _cal_min = (axis_settings[axis_index]->steps_per_mm->get() / 100.0);
+ _cal_max = (axis_settings[axis_index]->max_travel->get() / 100.0);
+ }
+
+ _pwm_pulse_min *= _cal_min;
+ _pwm_pulse_max *= _cal_max;
+
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration min:%1.2f max %1.2f", _pwm_pulse_min, _pwm_pulse_max);
+ }
+}
diff --git a/Grbl_Esp32/src/Motors/RcServo.h b/Grbl_Esp32/src/Motors/RcServo.h
new file mode 100644
index 00000000..94b767d2
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/RcServo.h
@@ -0,0 +1,55 @@
+#pragma once
+
+/*
+ RcServo.h
+
+ Part of Grbl_ESP32
+
+ 2020 - Bart Dring
+
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+*/
+
+#include "Motor.h"
+
+#include "RcServoSettings.h"
+
+namespace Motors {
+ class RcServo : public Motor {
+ public:
+ RcServo();
+ RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max);
+ virtual void config_message();
+ virtual void init();
+ void _write_pwm(uint32_t duty);
+ virtual void set_disable(bool disable);
+ virtual void update();
+ void read_settings();
+ void set_homing_mode(bool is_homing, bool isHoming);
+
+ protected:
+ void set_location();
+ void _get_calibration();
+
+ uint8_t _pwm_pin;
+ uint8_t _channel_num;
+ uint32_t _current_pwm_duty;
+ bool _disabled;
+
+ float _position_min;
+ float _position_max; // position in millimeters
+ float _homing_position;
+
+ float _pwm_pulse_min;
+ float _pwm_pulse_max;
+ };
+}
diff --git a/Grbl_Esp32/src/Motors/RcServoClass.cpp b/Grbl_Esp32/src/Motors/RcServoClass.cpp
deleted file mode 100644
index 49ae4341..00000000
--- a/Grbl_Esp32/src/Motors/RcServoClass.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- RcServoServoClass.cpp
-
- This allows an RcServo to be used like any other motor. Serrvos
- do have limitation in travel and speed, so you do need to respect that.
-
- Part of Grbl_ESP32
-
- 2020 - Bart Dring
-
- Servos have a limited travel, so they map the travel across a range in
- the current work coordinatee system. The servo can only travel as far
- as the range, but the internal axis value can keep going.
-
- Range: The range is specified in the machine definition file with...
- #define X_SERVO_RANGE_MIN 0.0
- #define X_SERVO_RANGE_MAX 5.0
-
- Direction: The direction can be changed using the $3 setting for the axis
-
- Homing: During homing, the servo will move to one of the endpoints. The
- endpoint is determined by the $23 or $HomingDirInvertMask setting for the axis.
- Do not define a homing cycle for the axis with the servo.
- You do need at least 1 homing cycle. TODO: Fix this
-
- Calibration. You can tweak the endpoints using the $10n or nStepsPerMm and
- $13n or $xMaxTravel setting, where n is the axis.
- The value is a percent. If you secify a percent outside the
- the range specified by the values below, it will be reset to 100.0 (100% ... no change)
- The calibration adjusts in direction of positive momement, so a value above 100% moves
- towards the higher axis value.
-
- #define SERVO_CAL_MIN
- #define SERVO_CAL_MAX
-
- Grbl_ESP32 is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Grbl is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Grbl. If not, see .
-*/
-
-#include "MotorClass.h"
-
-RcServo ::RcServo() {}
-
-RcServo ::RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max) {
- type_id = RC_SERVO_MOTOR;
- this->axis_index = axis_index % MAX_AXES;
- this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged
- this->_pwm_pin = pwm_pin;
- _position_min = min;
- _position_max = max;
- init();
-}
-
-void RcServo ::init() {
- read_settings();
- _channel_num = sys_get_next_PWM_chan_num();
- ledcSetup(_channel_num, SERVO_PULSE_FREQ, SERVO_PULSE_RES_BITS);
- ledcAttachPin(_pwm_pin, _channel_num);
- _current_pwm_duty = 0;
- is_active = true; // as opposed to NullMotors, this is a real motor
- set_axis_name();
- config_message();
-}
-
-void RcServo ::config_message() {
- grbl_msg_sendf(CLIENT_SERIAL,
- MSG_LEVEL_INFO,
- "%s Axis RC Servo motor Output:%d Min:%5.3fmm Max:%5.3fmm",
- _axis_name,
- _pwm_pin,
- _position_min,
- _position_max);
-}
-
-void RcServo::_write_pwm(uint32_t duty) {
- // to prevent excessive calls to ledcWrite, make sure duty hass changed
- if (duty == _current_pwm_duty)
- return;
-
- _current_pwm_duty = duty;
-
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Servo Pwm %d", _axis_name, duty);
- ledcWrite(_channel_num, duty);
-}
-
-// sets the PWM to zero. This allows most servos to be manually moved
-void RcServo::set_disable(bool disable) {
- return;
- _disabled = disable;
- if (_disabled)
- _write_pwm(0);
-}
-
-void RcServo::set_homing_mode(bool is_homing, bool isHoming) {
- float home_pos = 0.0;
-
- if (!is_homing)
- return;
-
- if (bit_istrue(homing_dir_mask->get(), bit(axis_index)))
- home_pos = _position_min;
- else
- home_pos = _position_max;
-
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo set home %d %3.2f", is_homing, home_pos);
- sys_position[axis_index] = home_pos * axis_settings[axis_index]->steps_per_mm->get(); // convert to steps
-}
-
-void RcServo::update() {
- set_location();
-}
-
-void RcServo::set_location() {
- uint32_t servo_pulse_len;
- float servo_pos, mpos, offset;
- // skip location if we are in alarm mode
-
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "locate");
- _get_calibration();
-
- if (sys.state == STATE_ALARM) {
- set_disable(true);
- return;
- }
-
- mpos = system_convert_axis_steps_to_mpos(sys_position, axis_index); // get the axis machine position in mm
- offset = gc_state.coord_system[axis_index] + gc_state.coord_offset[axis_index]; // get the current axis work offset
- servo_pos = mpos - offset; // determine the current work position
-
- // determine the pulse length
- servo_pulse_len = (uint32_t)mapConstrain(servo_pos, _position_min, _position_max, _pwm_pulse_min, _pwm_pulse_max);
-
- _write_pwm(servo_pulse_len);
-}
-
-void RcServo::read_settings() {
- _get_calibration();
-}
-
-// this should change to use its own settings.
-void RcServo::_get_calibration() {
- float _cal_min = 1.0;
- float _cal_max = 1.0;
-
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Read settings");
-
- // make sure the min is in range
- if ((axis_settings[axis_index]->steps_per_mm->get() < SERVO_CAL_MIN) || (axis_settings[axis_index]->steps_per_mm->get() > SERVO_CAL_MAX)) {
- grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration ($10%d) value error. Reset to 100", axis_index);
- char reset_val[] = "100";
- axis_settings[axis_index]->steps_per_mm->setStringValue(reset_val);
- }
-
- // make sure the max is in range
- // Note: Max travel is set positive via $$, but stored as a negative number
- if ((axis_settings[axis_index]->max_travel->get() < SERVO_CAL_MIN) || (axis_settings[axis_index]->max_travel->get() > SERVO_CAL_MAX)) {
- grbl_msg_sendf(CLIENT_SERIAL,
- MSG_LEVEL_INFO,
- "Servo calibration ($13%d) value error. %3.2f Reset to 100",
- axis_index,
- axis_settings[axis_index]->max_travel->get());
- char reset_val[] = "100";
- axis_settings[axis_index]->max_travel->setStringValue(reset_val);
- }
-
- _pwm_pulse_min = SERVO_MIN_PULSE;
- _pwm_pulse_max = SERVO_MAX_PULSE;
-
- if (bit_istrue(dir_invert_mask->get(), bit(axis_index))) { // normal direction
- _cal_min = 2.0 - (axis_settings[axis_index]->steps_per_mm->get() / 100.0);
- _cal_max = 2.0 - (axis_settings[axis_index]->max_travel->get() / 100.0);
- swap(_pwm_pulse_min, _pwm_pulse_max);
- } else { // inverted direction
- _cal_min = (axis_settings[axis_index]->steps_per_mm->get() / 100.0);
- _cal_max = (axis_settings[axis_index]->max_travel->get() / 100.0);
- }
-
- _pwm_pulse_min *= _cal_min;
- _pwm_pulse_max *= _cal_max;
-
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration min:%1.2f max %1.2f", _pwm_pulse_min, _pwm_pulse_max);
-}
\ No newline at end of file
diff --git a/Grbl_Esp32/src/Motors/RcServoClass.h b/Grbl_Esp32/src/Motors/RcServoSettings.h
similarity index 64%
rename from Grbl_Esp32/src/Motors/RcServoClass.h
rename to Grbl_Esp32/src/Motors/RcServoSettings.h
index 84dafbc5..c07655ce 100644
--- a/Grbl_Esp32/src/Motors/RcServoClass.h
+++ b/Grbl_Esp32/src/Motors/RcServoSettings.h
@@ -1,24 +1,5 @@
#pragma once
-/*
- RcServoClass.h
-
- Part of Grbl_ESP32
-
- 2020 - Bart Dring
-
- Grbl is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Grbl is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Grbl. If not, see .
-*/
-
// this is the pulse range of a the servo. Typical servos are 0.001 to 0.002 seconds
// some servos have a wider range. You can adjust this here or in the calibration feature
#define SERVO_MIN_PULSE_SEC 0.001 // min pulse in seconds
diff --git a/Grbl_Esp32/src/Motors/Solenoid.h b/Grbl_Esp32/src/Motors/Solenoid.h
new file mode 100644
index 00000000..fb973083
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/Solenoid.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "RcServo.h"
+
+namespace Motors {
+ class Solenoid : public RcServo {
+ public:
+ Solenoid();
+ Solenoid(uint8_t axis_index, gpio_num_t pwm_pin, float transition_poiont);
+ void config_message();
+ void set_location();
+ void update();
+ void init();
+ void set_disable(bool disable);
+
+ float _transition_poiont;
+ };
+}
diff --git a/Grbl_Esp32/src/Motors/StandardStepper.cpp b/Grbl_Esp32/src/Motors/StandardStepper.cpp
new file mode 100644
index 00000000..e181fa56
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/StandardStepper.cpp
@@ -0,0 +1,103 @@
+/*
+ StandardStepperClass.cpp
+
+ This is used for a stepper motor that just requires step and direction
+ pins.
+ TODO: Add an enable pin
+
+ Part of Grbl_ESP32
+
+ 2020 - Bart Dring
+
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+*/
+
+#include "StandardStepper.h"
+
+namespace Motors {
+ StandardStepper::StandardStepper() {}
+
+ StandardStepper::StandardStepper(uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin) {
+ type_id = STANDARD_MOTOR;
+ this->axis_index = axis_index % MAX_AXES;
+ this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged
+ this->step_pin = step_pin;
+ this->dir_pin = dir_pin;
+ this->disable_pin = disable_pin;
+ init();
+ }
+
+ void StandardStepper::init() {
+ _homing_mask = 0;
+ is_active = true; // as opposed to NullMotors, this is a real motor
+ set_axis_name();
+ init_step_dir_pins();
+ config_message();
+ }
+
+ void StandardStepper::init_step_dir_pins() {
+ // TODO Step pin, but RMT complicates things
+ _invert_step_pin = bit_istrue(step_invert_mask->get(), bit(axis_index));
+ pinMode(dir_pin, OUTPUT);
+
+#ifdef USE_RMT_STEPS
+ rmtConfig.rmt_mode = RMT_MODE_TX;
+ rmtConfig.clk_div = 20;
+ rmtConfig.mem_block_num = 2;
+ rmtConfig.tx_config.loop_en = false;
+ rmtConfig.tx_config.carrier_en = false;
+ rmtConfig.tx_config.carrier_freq_hz = 0;
+ rmtConfig.tx_config.carrier_duty_percent = 50;
+ rmtConfig.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
+ rmtConfig.tx_config.idle_output_en = true;
+
+# ifdef STEP_PULSE_DELAY
+ rmtItem[0].duration0 = STEP_PULSE_DELAY * 4;
+# else
+ rmtItem[0].duration0 = 1;
+# endif
+
+ rmtItem[0].duration1 = 4 * pulse_microseconds->get();
+ rmtItem[1].duration0 = 0;
+ rmtItem[1].duration1 = 0;
+
+ rmt_chan_num[axis_index][dual_axis_index] = sys_get_next_RMT_chan_num();
+ rmt_set_source_clk((rmt_channel_t)rmt_chan_num[axis_index][dual_axis_index], RMT_BASECLK_APB);
+ rmtConfig.channel = (rmt_channel_t)rmt_chan_num[axis_index][dual_axis_index];
+ rmtConfig.tx_config.idle_level = _invert_step_pin ? RMT_IDLE_LEVEL_HIGH : RMT_IDLE_LEVEL_LOW;
+ rmtConfig.gpio_num = gpio_num_t(step_pin); // c is a wacky lang
+ rmtItem[0].level0 = rmtConfig.tx_config.idle_level;
+ rmtItem[0].level1 = !rmtConfig.tx_config.idle_level;
+ rmt_config(&rmtConfig);
+ rmt_fill_tx_items(rmtConfig.channel, &rmtItem[0], rmtConfig.mem_block_num, 0);
+
+#else
+ pinMode(step_pin, OUTPUT);
+
+#endif // USE_RMT_STEPS
+ pinMode(disable_pin, OUTPUT);
+ }
+
+ void StandardStepper::config_message() {
+ grbl_msg_sendf(CLIENT_SERIAL,
+ MSG_LEVEL_INFO,
+ "%s Axis standard stepper motor Step:%s Dir:%s Disable:%s",
+ _axis_name,
+ pinName(step_pin).c_str(),
+ pinName(dir_pin).c_str(),
+ pinName(disable_pin).c_str());
+ }
+
+ void StandardStepper::set_direction_pins(uint8_t onMask) { digitalWrite(dir_pin, (onMask & bit(axis_index))); }
+
+ void StandardStepper::set_disable(bool disable) { digitalWrite(disable_pin, disable); }
+}
diff --git a/Grbl_Esp32/src/Motors/StandardStepper.h b/Grbl_Esp32/src/Motors/StandardStepper.h
new file mode 100644
index 00000000..8a4d7e8c
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/StandardStepper.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "Motor.h"
+
+namespace Motors {
+ class StandardStepper : public Motor {
+ public:
+ StandardStepper();
+ StandardStepper(uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin);
+
+ virtual void config_message();
+ virtual void init();
+ virtual void set_direction_pins(uint8_t onMask);
+ void init_step_dir_pins();
+ virtual void set_disable(bool disable);
+ uint8_t step_pin;
+
+ protected:
+ bool _invert_step_pin;
+ uint8_t dir_pin;
+ uint8_t disable_pin;
+ };
+}
diff --git a/Grbl_Esp32/src/Motors/StandardStepperClass.cpp b/Grbl_Esp32/src/Motors/StandardStepperClass.cpp
deleted file mode 100644
index 2374d094..00000000
--- a/Grbl_Esp32/src/Motors/StandardStepperClass.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- StandardStepperClass.cpp
-
- This is used for a stepper motor that just requires step and direction
- pins.
- TODO: Add an enable pin
-
- Part of Grbl_ESP32
-
- 2020 - Bart Dring
-
- Grbl is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Grbl is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Grbl. If not, see .
-*/
-
-#include "MotorClass.h"
-
-StandardStepper ::StandardStepper() {}
-
-StandardStepper ::StandardStepper(uint8_t axis_index, uint8_t step_pin, uint8_t dir_pin, uint8_t disable_pin) {
- type_id = STANDARD_MOTOR;
- this->axis_index = axis_index % MAX_AXES;
- this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged
- this->step_pin = step_pin;
- this->dir_pin = dir_pin;
- this->disable_pin = disable_pin;
- init();
-}
-
-void StandardStepper ::init() {
- _homing_mask = 0;
- is_active = true; // as opposed to NullMotors, this is a real motor
- set_axis_name();
- init_step_dir_pins();
- config_message();
-}
-
-void StandardStepper ::init_step_dir_pins() {
- // TODO Step pin, but RMT complicates things
- _invert_step_pin = bit_istrue(step_invert_mask->get(), bit(axis_index));
- pinMode(dir_pin, OUTPUT);
-
-#ifdef USE_RMT_STEPS
- rmtConfig.rmt_mode = RMT_MODE_TX;
- rmtConfig.clk_div = 20;
- rmtConfig.mem_block_num = 2;
- rmtConfig.tx_config.loop_en = false;
- rmtConfig.tx_config.carrier_en = false;
- rmtConfig.tx_config.carrier_freq_hz = 0;
- rmtConfig.tx_config.carrier_duty_percent = 50;
- rmtConfig.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
- rmtConfig.tx_config.idle_output_en = true;
-
-# ifdef STEP_PULSE_DELAY
- rmtItem[0].duration0 = STEP_PULSE_DELAY * 4;
-# else
- rmtItem[0].duration0 = 1;
-# endif
-
- rmtItem[0].duration1 = 4 * pulse_microseconds->get();
- rmtItem[1].duration0 = 0;
- rmtItem[1].duration1 = 0;
-
- rmt_chan_num[axis_index][dual_axis_index] = sys_get_next_RMT_chan_num();
- rmt_set_source_clk((rmt_channel_t)rmt_chan_num[axis_index][dual_axis_index], RMT_BASECLK_APB);
- rmtConfig.channel = (rmt_channel_t)rmt_chan_num[axis_index][dual_axis_index];
- rmtConfig.tx_config.idle_level = _invert_step_pin ? RMT_IDLE_LEVEL_HIGH : RMT_IDLE_LEVEL_LOW;
- rmtConfig.gpio_num = gpio_num_t(step_pin); // c is a wacky lang
- rmtItem[0].level0 = rmtConfig.tx_config.idle_level;
- rmtItem[0].level1 = !rmtConfig.tx_config.idle_level;
- rmt_config(&rmtConfig);
- rmt_fill_tx_items(rmtConfig.channel, &rmtItem[0], rmtConfig.mem_block_num, 0);
-
-#else
- pinMode(step_pin, OUTPUT);
-
-#endif // USE_RMT_STEPS
- pinMode(disable_pin, OUTPUT);
-}
-
-void StandardStepper ::config_message() {
- grbl_msg_sendf(CLIENT_SERIAL,
- MSG_LEVEL_INFO,
- "%s Axis standard stepper motor Step:%s Dir:%s Disable:%s",
- _axis_name,
- pinName(step_pin).c_str(),
- pinName(dir_pin).c_str(),
- pinName(disable_pin).c_str());
-}
-
-void StandardStepper ::set_direction_pins(uint8_t onMask) {
- digitalWrite(dir_pin, (onMask & bit(axis_index)));
-}
-
-void StandardStepper ::set_disable(bool disable) {
- digitalWrite(disable_pin, disable);
-}
diff --git a/Grbl_Esp32/src/Motors/TrinamicDriver.cpp b/Grbl_Esp32/src/Motors/TrinamicDriver.cpp
new file mode 100644
index 00000000..3e3613d9
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/TrinamicDriver.cpp
@@ -0,0 +1,235 @@
+/*
+ TrinamicDriverClass.cpp
+ This is used for Trinamic SPI controlled stepper motor drivers.
+
+ Part of Grbl_ESP32
+ 2020 - Bart Dring
+
+ Grbl is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Grbl is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Grbl. If not, see .
+
+*/
+#include "TrinamicDriver.h"
+
+#include
+
+namespace Motors {
+ TrinamicDriver::TrinamicDriver(uint8_t axis_index,
+ uint8_t step_pin,
+ uint8_t dir_pin,
+ uint8_t disable_pin,
+ uint8_t cs_pin,
+ uint16_t driver_part_number,
+ float r_sense,
+ int8_t spi_index) {
+ type_id = TRINAMIC_SPI_MOTOR;
+ this->axis_index = axis_index % MAX_AXES;
+ this->dual_axis_index = axis_index < 6 ? 0 : 1; // 0 = primary 1 = ganged
+ _driver_part_number = driver_part_number;
+ _r_sense = r_sense;
+ this->step_pin = step_pin;
+ this->dir_pin = dir_pin;
+ this->disable_pin = disable_pin;
+ this->cs_pin = cs_pin;
+ this->spi_index = spi_index;
+
+ _homing_mode = TRINAMIC_HOMING_MODE;
+ _homing_mask = 0; // no axes homing
+
+ if (_driver_part_number == 2130)
+ tmcstepper = new TMC2130Stepper(cs_pin, _r_sense, spi_index);
+ else if (_driver_part_number == 5160)
+ tmcstepper = new TMC5160Stepper(cs_pin, _r_sense, spi_index);
+ else {
+ grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Trinamic unsupported p/n:%d", _driver_part_number);
+ return;
+ }
+
+ set_axis_name();
+
+ init_step_dir_pins(); // from StandardStepper
+
+ digitalWrite(cs_pin, HIGH);
+ pinMode(cs_pin, OUTPUT);
+
+ // use slower speed if I2S
+ if (cs_pin >= I2S_OUT_PIN_BASE)
+ tmcstepper->setSPISpeed(TRINAMIC_SPI_FREQ);
+
+ config_message();
+
+ // init() must be called later, after all TMC drivers have CS pins setup.
+ }
+
+ void TrinamicDriver::init() {
+ SPI.begin(); // this will get called for each motor, but does not seem to hurt anything
+
+ tmcstepper->begin();
+ test(); // Try communicating with motor. Prints an error if there is a problem.
+ read_settings(); // pull info from settings
+ set_mode(false);
+
+ _homing_mask = 0;
+ is_active = true; // as opposed to NullMotors, this is a real motor
+ }
+
+ /*
+ This is the startup message showing the basic definition
+*/
+ void TrinamicDriver::config_message() {
+ grbl_msg_sendf(CLIENT_SERIAL,
+ MSG_LEVEL_INFO,
+ "%s Axis Trinamic TMC%d Step:%s Dir:%s CS:%s Disable:%s Index:%d",
+ _axis_name,
+ _driver_part_number,
+ pinName(step_pin).c_str(),
+ pinName(dir_pin).c_str(),
+ pinName(cs_pin).c_str(),
+ pinName(disable_pin).c_str(),
+ spi_index);
+ }
+
+ bool TrinamicDriver::test() {
+ switch (tmcstepper->test_connection()) {
+ case 1:
+ grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check connection", _axis_name);
+ return false;
+ case 2:
+ grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check motor power", _axis_name);
+ return false;
+ default: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test passed", _axis_name); return true;
+ }
+ }
+
+ /*
+ Read setting and send them to the driver. Called at init() and whenever related settings change
+ both are stored as float Amps, but TMCStepper library expects...
+ uint16_t run (mA)
+ float hold (as a percentage of run)
+*/
+ void TrinamicDriver::read_settings() {
+ uint16_t run_i_ma = (uint16_t)(axis_settings[axis_index]->run_current->get() * 1000.0);
+ float hold_i_percent;
+
+ if (axis_settings[axis_index]->run_current->get() == 0)
+ hold_i_percent = 0;
+ else {
+ hold_i_percent = axis_settings[axis_index]->hold_current->get() / axis_settings[axis_index]->run_current->get();
+ if (hold_i_percent > 1.0)
+ hold_i_percent = 1.0;
+ }
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Current run %d hold %f", _axis_name, run_i_ma, hold_i_percent);
+
+ tmcstepper->microsteps(axis_settings[axis_index]->microsteps->get());
+ tmcstepper->rms_current(run_i_ma, hold_i_percent);
+ }
+
+ void TrinamicDriver::set_homing_mode(uint8_t homing_mask, bool isHoming) {
+ _homing_mask = homing_mask;
+ set_mode(isHoming);
+ }
+
+ /*
+ There are ton of settings. I'll start by grouping then into modes for now.
+ Many people will want quiet and stallgaurd homing. Stallguard only run in
+ Coolstep mode, so it will need to switch to Coolstep when homing
+*/
+ void TrinamicDriver::set_mode(bool isHoming) {
+ if (isHoming)
+ _mode = TRINAMIC_HOMING_MODE;
+ else
+ _mode = TRINAMIC_RUN_MODE;
+
+ if (_lastMode == _mode)
+ return;
+ _lastMode = _mode;
+
+ switch (_mode) {
+ case TRINAMIC_MODE_STEALTHCHOP:
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STEALTHCHOP");
+ tmcstepper->en_pwm_mode(true);
+ tmcstepper->pwm_autoscale(true);
+ tmcstepper->diag1_stall(false);
+ break;
+ case TRINAMIC_MODE_COOLSTEP:
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_COOLSTEP");
+ tmcstepper->en_pwm_mode(false);
+ tmcstepper->pwm_autoscale(false);
+ tmcstepper->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep
+ tmcstepper->THIGH(NORMAL_THIGH);
+ break;
+ case TRINAMIC_MODE_STALLGUARD:
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STALLGUARD");
+ tmcstepper->en_pwm_mode(false);
+ tmcstepper->pwm_autoscale(false);
+ tmcstepper->TCOOLTHRS(calc_tstep(homing_feed_rate->get(), 150.0));
+ tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0));
+ tmcstepper->sfilt(1);
+ tmcstepper->diag1_stall(true); // stallguard i/o is on diag1
+ tmcstepper->sgt(axis_settings[axis_index]->stallguard->get());
+ break;
+ default: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_UNDEFINED");
+ }
+ }
+
+ /*
+ This is the stallguard tuning info. It is call debug, so it could be generic across all classes.
+*/
+ void TrinamicDriver::debug_message() {
+ uint32_t tstep = tmcstepper->TSTEP();
+
+ if (tstep == 0xFFFFF || tstep < 1) // if axis is not moving return
+ return;
+ float feedrate = st_get_realtime_rate(); //* settings.microsteps[axis_index] / 60.0 ; // convert mm/min to Hz
+
+ grbl_msg_sendf(CLIENT_SERIAL,
+ MSG_LEVEL_INFO,
+ "%s Stallguard %d SG_Val: %04d Rate: %05.0f mm/min SG_Setting:%d",
+ _axis_name,
+ tmcstepper->stallguard(),
+ tmcstepper->sg_result(),
+ feedrate,
+ axis_settings[axis_index]->stallguard->get());
+ }
+
+ // calculate a tstep from a rate
+ // tstep = TRINAMIC_FCLK / (time between 1/256 steps)
+ // This is used to set the stallguard window from the homing speed.
+ // The percent is the offset on the window
+ uint32_t TrinamicDriver::calc_tstep(float speed, float percent) {
+ float tstep =
+ speed / 60.0 * axis_settings[axis_index]->steps_per_mm->get() * (float)(256 / axis_settings[axis_index]->microsteps->get());
+ tstep = TRINAMIC_FCLK / tstep * percent / 100.0;
+
+ return (uint32_t)tstep;
+ }
+
+ // this can use the enable feature over SPI. The dedicated pin must be in the enable mode,
+ // but that can be hardwired that way.
+ void TrinamicDriver::set_disable(bool disable) {
+ //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Axis disable %d", _axis_name, disable);
+
+ digitalWrite(disable_pin, disable);
+
+#ifdef USE_TRINAMIC_ENABLE
+ if (disable)
+ tmcstepper->toff(TRINAMIC_TOFF_DISABLE);
+ else {
+ if (_mode == TRINAMIC_MODE_STEALTHCHOP)
+ tmcstepper->toff(TRINAMIC_TOFF_STEALTHCHOP);
+ else
+ tmcstepper->toff(TRINAMIC_TOFF_COOLSTEP);
+ }
+#endif
+ // the pin based enable could be added here.
+ // This would be for individual motors, not the single pin for all motors.
+ }
+}
diff --git a/Grbl_Esp32/src/Motors/TrinamicDriverClass.h b/Grbl_Esp32/src/Motors/TrinamicDriver.h
similarity index 55%
rename from Grbl_Esp32/src/Motors/TrinamicDriverClass.h
rename to Grbl_Esp32/src/Motors/TrinamicDriver.h
index b1ab8040..d6aa863b 100644
--- a/Grbl_Esp32/src/Motors/TrinamicDriverClass.h
+++ b/Grbl_Esp32/src/Motors/TrinamicDriver.h
@@ -1,7 +1,7 @@
#pragma once
/*
- TrinamicDriverClass.h
+ TrinamicDriver.h
Part of Grbl_ESP32
@@ -19,6 +19,10 @@
along with Grbl. If not, see .
*/
+#include "Motor.h"
+#include "StandardStepper.h"
+#include // https://github.com/teemuatlut/TMCStepper
+
#define TRINAMIC_MODE_STEALTHCHOP 0 // very quiet
#define TRINAMIC_MODE_COOLSTEP 1 // everything runs cooler so higher current possible
#define TRINAMIC_MODE_STALLGUARD 2 // coolstep plus generates stall indication
@@ -54,5 +58,41 @@
# define TRINAMIC_TOFF_COOLSTEP 3
#endif
-#include "MotorClass.h"
-#include // https://github.com/teemuatlut/TMCStepper
+namespace Motors {
+ class TrinamicDriver : public StandardStepper {
+ public:
+ TrinamicDriver(uint8_t axis_index,
+ uint8_t step_pin,
+ uint8_t dir_pin,
+ uint8_t disable_pin,
+ uint8_t cs_pin,
+ uint16_t driver_part_number,
+ float r_sense,
+ int8_t spi_index);
+
+ void config_message();
+ void init();
+ void set_mode(bool isHoming);
+ void read_settings();
+ void trinamic_test_response();
+ void trinamic_stepper_enable(bool enable);
+ void debug_message();
+ void set_homing_mode(uint8_t homing_mask, bool ishoming);
+ void set_disable(bool disable);
+ bool test();
+
+ private:
+ uint32_t calc_tstep(float speed, float percent);
+
+ TMC2130Stepper* tmcstepper; // all other driver types are subclasses of this one
+ uint8_t _homing_mode;
+ uint8_t cs_pin = UNDEFINED_PIN; // The chip select pin (can be the same for daisy chain)
+ uint16_t _driver_part_number; // example: use 2130 for TMC2130
+ float _r_sense;
+ int8_t spi_index;
+
+ protected:
+ uint8_t _mode;
+ uint8_t _lastMode = 255;
+ };
+}
diff --git a/Grbl_Esp32/src/Motors/TrinamicDriverClass.cpp b/Grbl_Esp32/src/Motors/TrinamicDriverClass.cpp
deleted file mode 100644
index f36a4abf..00000000
--- a/Grbl_Esp32/src/Motors/TrinamicDriverClass.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- TrinamicDriverClass.cpp
- This is used for Trinamic SPI controlled stepper motor drivers.
-
- Part of Grbl_ESP32
- 2020 - Bart Dring
-
- Grbl is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Grbl is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Grbl. If not, see .
-
-*/
-#include "MotorClass.h"
-#include
-#include "TrinamicDriverClass.h"
-
-TrinamicDriver ::TrinamicDriver(uint8_t axis_index,
- uint8_t step_pin,
- uint8_t dir_pin,
- uint8_t disable_pin,
- uint8_t cs_pin,
- uint16_t driver_part_number,
- float r_sense,
- int8_t spi_index) {
- type_id = TRINAMIC_SPI_MOTOR;
- this->axis_index = axis_index % MAX_AXES;
- this->dual_axis_index = axis_index < 6 ? 0 : 1; // 0 = primary 1 = ganged
- _driver_part_number = driver_part_number;
- _r_sense = r_sense;
- this->step_pin = step_pin;
- this->dir_pin = dir_pin;
- this->disable_pin = disable_pin;
- this->cs_pin = cs_pin;
- this->spi_index = spi_index;
-
- _homing_mode = TRINAMIC_HOMING_MODE;
- _homing_mask = 0; // no axes homing
-
- if (_driver_part_number == 2130)
- tmcstepper = new TMC2130Stepper(cs_pin, _r_sense, spi_index);
- else if (_driver_part_number == 5160)
- tmcstepper = new TMC5160Stepper(cs_pin, _r_sense, spi_index);
- else {
- grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Trinamic unsupported p/n:%d", _driver_part_number);
- return;
- }
-
- set_axis_name();
-
- init_step_dir_pins(); // from StandardStepper
-
- digitalWrite(cs_pin, HIGH);
- pinMode(cs_pin, OUTPUT);
-
- // use slower speed if I2S
- if (cs_pin >= I2S_OUT_PIN_BASE)
- tmcstepper->setSPISpeed(TRINAMIC_SPI_FREQ);
-
- config_message();
-
- // init() must be called later, after all TMC drivers have CS pins setup.
-}
-
-void TrinamicDriver ::init() {
- SPI.begin(); // this will get called for each motor, but does not seem to hurt anything
-
- tmcstepper->begin();
- test(); // Try communicating with motor. Prints an error if there is a problem.
- read_settings(); // pull info from settings
- set_mode(false);
-
- _homing_mask = 0;
- is_active = true; // as opposed to NullMotors, this is a real motor
-}
-
-/*
- This is the startup message showing the basic definition
-*/
-void TrinamicDriver ::config_message() {
- grbl_msg_sendf(CLIENT_SERIAL,
- MSG_LEVEL_INFO,
- "%s Axis Trinamic TMC%d Step:%s Dir:%s CS:%s Disable:%s Index:%d",
- _axis_name,
- _driver_part_number,
- pinName(step_pin).c_str(),
- pinName(dir_pin).c_str(),
- pinName(cs_pin).c_str(),
- pinName(disable_pin).c_str(),
- spi_index);
-}
-
-bool TrinamicDriver ::test() {
- switch (tmcstepper->test_connection()) {
- case 1: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check connection", _axis_name); return false;
- case 2:
- grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test failed. Check motor power", _axis_name);
- return false;
- default: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Trinamic driver test passed", _axis_name); return true;
- }
-}
-
-/*
- Read setting and send them to the driver. Called at init() and whenever related settings change
- both are stored as float Amps, but TMCStepper library expects...
- uint16_t run (mA)
- float hold (as a percentage of run)
-*/
-void TrinamicDriver ::read_settings() {
- uint16_t run_i_ma = (uint16_t)(axis_settings[axis_index]->run_current->get() * 1000.0);
- float hold_i_percent;
-
- if (axis_settings[axis_index]->run_current->get() == 0)
- hold_i_percent = 0;
- else {
- hold_i_percent = axis_settings[axis_index]->hold_current->get() / axis_settings[axis_index]->run_current->get();
- if (hold_i_percent > 1.0)
- hold_i_percent = 1.0;
- }
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Current run %d hold %f", _axis_name, run_i_ma, hold_i_percent);
-
- tmcstepper->microsteps(axis_settings[axis_index]->microsteps->get());
- tmcstepper->rms_current(run_i_ma, hold_i_percent);
-}
-
-void TrinamicDriver ::set_homing_mode(uint8_t homing_mask, bool isHoming) {
- _homing_mask = homing_mask;
- set_mode(isHoming);
-}
-
-/*
- There are ton of settings. I'll start by grouping then into modes for now.
- Many people will want quiet and stallgaurd homing. Stallguard only run in
- Coolstep mode, so it will need to switch to Coolstep when homing
-*/
-void TrinamicDriver ::set_mode(bool isHoming) {
- if (isHoming)
- _mode = TRINAMIC_HOMING_MODE;
- else
- _mode = TRINAMIC_RUN_MODE;
-
- if (_lastMode == _mode)
- return;
- _lastMode = _mode;
-
- switch (_mode) {
- case TRINAMIC_MODE_STEALTHCHOP:
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STEALTHCHOP");
- tmcstepper->en_pwm_mode(true);
- tmcstepper->pwm_autoscale(true);
- tmcstepper->diag1_stall(false);
- break;
- case TRINAMIC_MODE_COOLSTEP:
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_COOLSTEP");
- tmcstepper->en_pwm_mode(false);
- tmcstepper->pwm_autoscale(false);
- tmcstepper->TCOOLTHRS(NORMAL_TCOOLTHRS); // when to turn on coolstep
- tmcstepper->THIGH(NORMAL_THIGH);
- break;
- case TRINAMIC_MODE_STALLGUARD:
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_STALLGUARD");
- tmcstepper->en_pwm_mode(false);
- tmcstepper->pwm_autoscale(false);
- tmcstepper->TCOOLTHRS(calc_tstep(homing_feed_rate->get(), 150.0));
- tmcstepper->THIGH(calc_tstep(homing_feed_rate->get(), 60.0));
- tmcstepper->sfilt(1);
- tmcstepper->diag1_stall(true); // stallguard i/o is on diag1
- tmcstepper->sgt(axis_settings[axis_index]->stallguard->get());
- break;
- default: grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "TRINAMIC_MODE_UNDEFINED");
- }
-}
-
-/*
- This is the stallguard tuning info. It is call debug, so it could be generic across all classes.
-*/
-void TrinamicDriver ::debug_message() {
- uint32_t tstep = tmcstepper->TSTEP();
-
- if (tstep == 0xFFFFF || tstep < 1) // if axis is not moving return
- return;
- float feedrate = st_get_realtime_rate(); //* settings.microsteps[axis_index] / 60.0 ; // convert mm/min to Hz
-
- grbl_msg_sendf(CLIENT_SERIAL,
- MSG_LEVEL_INFO,
- "%s Stallguard %d SG_Val: %04d Rate: %05.0f mm/min SG_Setting:%d",
- _axis_name,
- tmcstepper->stallguard(),
- tmcstepper->sg_result(),
- feedrate,
- axis_settings[axis_index]->stallguard->get());
-}
-
-// calculate a tstep from a rate
-// tstep = TRINAMIC_FCLK / (time between 1/256 steps)
-// This is used to set the stallguard window from the homing speed.
-// The percent is the offset on the window
-uint32_t TrinamicDriver ::calc_tstep(float speed, float percent) {
- float tstep = speed / 60.0 * axis_settings[axis_index]->steps_per_mm->get() * (float)(256 / axis_settings[axis_index]->microsteps->get());
- tstep = TRINAMIC_FCLK / tstep * percent / 100.0;
-
- return (uint32_t)tstep;
-}
-
-// this can use the enable feature over SPI. The dedicated pin must be in the enable mode,
-// but that can be hardwired that way.
-void TrinamicDriver ::set_disable(bool disable) {
- //grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Axis disable %d", _axis_name, disable);
-
- digitalWrite(disable_pin, disable);
-
-#ifdef USE_TRINAMIC_ENABLE
- if (disable)
- tmcstepper->toff(TRINAMIC_TOFF_DISABLE);
- else {
- if (_mode == TRINAMIC_MODE_STEALTHCHOP)
- tmcstepper->toff(TRINAMIC_TOFF_STEALTHCHOP);
- else
- tmcstepper->toff(TRINAMIC_TOFF_COOLSTEP);
- }
-#endif
- // the pin based enable could be added here.
- // This would be for individual motors, not the single pin for all motors.
-}
diff --git a/Grbl_Esp32/src/Motors/UnipolarMotor.cpp b/Grbl_Esp32/src/Motors/UnipolarMotor.cpp
new file mode 100644
index 00000000..a2918ee1
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/UnipolarMotor.cpp
@@ -0,0 +1,139 @@
+#include "UnipolarMotor.h"
+
+namespace Motors {
+ UnipolarMotor::UnipolarMotor() {}
+
+ UnipolarMotor::UnipolarMotor(uint8_t axis_index, uint8_t pin_phase0, uint8_t pin_phase1, uint8_t pin_phase2, uint8_t pin_phase3) {
+ type_id = UNIPOLAR_MOTOR;
+ this->axis_index = axis_index % MAX_AXES;
+ this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged
+ _pin_phase0 = pin_phase0;
+ _pin_phase1 = pin_phase1;
+ _pin_phase2 = pin_phase2;
+ _pin_phase3 = pin_phase3;
+
+ _half_step = true; // TODO read from settings ... microstep > 1 = half step
+
+ set_axis_name();
+ init();
+ config_message();
+ }
+
+ void UnipolarMotor::init() {
+ pinMode(_pin_phase0, OUTPUT);
+ pinMode(_pin_phase1, OUTPUT);
+ pinMode(_pin_phase2, OUTPUT);
+ pinMode(_pin_phase3, OUTPUT);
+ _current_phase = 0;
+ }
+
+ void UnipolarMotor::config_message() {
+ grbl_msg_sendf(CLIENT_SERIAL,
+ MSG_LEVEL_INFO,
+ "%s Axis unipolar stepper motor Ph0:%s Ph1:%s Ph2:%s Ph3:%s",
+ _axis_name,
+ pinName(_pin_phase0).c_str(),
+ pinName(_pin_phase1).c_str(),
+ pinName(_pin_phase2).c_str(),
+ pinName(_pin_phase3).c_str());
+ }
+
+ void UnipolarMotor::set_disable(bool disable) {
+ if (disable) {
+ digitalWrite(_pin_phase0, 0);
+ digitalWrite(_pin_phase1, 0);
+ digitalWrite(_pin_phase2, 0);
+ digitalWrite(_pin_phase3, 0);
+ }
+ _enabled = !disable;
+ }
+
+ void UnipolarMotor::step(uint8_t step_mask, uint8_t dir_mask) {
+ uint8_t _phase[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; // temporary phase values...all start as off
+ uint8_t phase_max;
+
+ if (!(step_mask & bit(axis_index)))
+ return; // a step is not required on this interrupt
+
+ if (!_enabled)
+ return; // don't do anything, phase is not changed or lost
+
+ if (_half_step)
+ phase_max = 7;
+ else
+ phase_max = 3;
+
+ if (dir_mask & bit(axis_index)) { // count up
+ if (_current_phase == phase_max)
+ _current_phase = 0;
+ else
+ _current_phase++;
+ } else { // count down
+ if (_current_phase == 0)
+ _current_phase = phase_max;
+ else
+ _current_phase--;
+ }
+ /*
+ 8 Step : A – AB – B – BC – C – CD – D – DA
+ 4 Step : AB – BC – CD – DA
+
+ Step IN4 IN3 IN2 IN1
+ A 0 0 0 1
+ AB 0 0 1 1
+ B 0 0 1 0
+ BC 0 1 1 0
+ C 0 1 0 0
+ CD 1 1 0 0
+ D 1 0 0 0
+ DA 1 0 0 1
+ */
+ if (_half_step) {
+ switch (_current_phase) {
+ case 0: _phase[0] = 1; break;
+ case 1:
+ _phase[0] = 1;
+ _phase[1] = 1;
+ break;
+ case 2: _phase[1] = 1; break;
+ case 3:
+ _phase[1] = 1;
+ _phase[2] = 1;
+ break;
+ case 4: _phase[2] = 1; break;
+ case 5:
+ _phase[2] = 1;
+ _phase[3] = 1;
+ break;
+ case 6: _phase[3] = 1; break;
+ case 7:
+ _phase[3] = 1;
+ _phase[0] = 1;
+ break;
+ }
+ } else {
+ switch (_current_phase) {
+ case 0:
+ _phase[0] = 1;
+ _phase[1] = 1;
+ break;
+ case 1:
+ _phase[1] = 1;
+ _phase[2] = 1;
+ break;
+ case 2:
+ _phase[2] = 1;
+ _phase[3] = 1;
+ break;
+ case 3:
+ _phase[3] = 1;
+ _phase[0] = 1;
+ break;
+ }
+ }
+ digitalWrite(_pin_phase0, _phase[0]);
+ digitalWrite(_pin_phase1, _phase[1]);
+ digitalWrite(_pin_phase2, _phase[2]);
+ digitalWrite(_pin_phase3, _phase[3]);
+ }
+}
diff --git a/Grbl_Esp32/src/Motors/UnipolarMotor.h b/Grbl_Esp32/src/Motors/UnipolarMotor.h
new file mode 100644
index 00000000..d9594815
--- /dev/null
+++ b/Grbl_Esp32/src/Motors/UnipolarMotor.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "Motor.h"
+
+namespace Motors {
+ class UnipolarMotor : public Motor {
+ public:
+ UnipolarMotor();
+ UnipolarMotor(uint8_t axis_index, uint8_t pin_phase0, uint8_t pin_phase1, uint8_t pin_phase2, uint8_t pin_phase3);
+ void init();
+ void config_message();
+ void set_disable(bool disable);
+ void step(uint8_t step_mask, uint8_t dir_mask); // only used on Unipolar right now
+
+ private:
+ uint8_t _pin_phase0;
+ uint8_t _pin_phase1;
+ uint8_t _pin_phase2;
+ uint8_t _pin_phase3;
+ uint8_t _current_phase;
+ bool _half_step;
+ bool _enabled;
+ };
+}
diff --git a/Grbl_Esp32/src/Motors/UnipolarMotorClass.cpp b/Grbl_Esp32/src/Motors/UnipolarMotorClass.cpp
deleted file mode 100644
index 3c8aed36..00000000
--- a/Grbl_Esp32/src/Motors/UnipolarMotorClass.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-#include "MotorClass.h"
-
-UnipolarMotor ::UnipolarMotor() {}
-
-UnipolarMotor ::UnipolarMotor(uint8_t axis_index, uint8_t pin_phase0, uint8_t pin_phase1, uint8_t pin_phase2, uint8_t pin_phase3) {
- type_id = UNIPOLAR_MOTOR;
- this->axis_index = axis_index % MAX_AXES;
- this->dual_axis_index = axis_index < MAX_AXES ? 0 : 1; // 0 = primary 1 = ganged
- _pin_phase0 = pin_phase0;
- _pin_phase1 = pin_phase1;
- _pin_phase2 = pin_phase2;
- _pin_phase3 = pin_phase3;
-
- _half_step = true; // TODO read from settings ... microstep > 1 = half step
-
- set_axis_name();
- init();
- config_message();
-}
-
-void UnipolarMotor ::init() {
- pinMode(_pin_phase0, OUTPUT);
- pinMode(_pin_phase1, OUTPUT);
- pinMode(_pin_phase2, OUTPUT);
- pinMode(_pin_phase3, OUTPUT);
- _current_phase = 0;
-}
-
-void UnipolarMotor ::config_message() {
- grbl_msg_sendf(CLIENT_SERIAL,
- MSG_LEVEL_INFO,
- "%s Axis unipolar stepper motor Ph0:%s Ph1:%s Ph2:%s Ph3:%s",
- _axis_name,
- pinName(_pin_phase0).c_str(),
- pinName(_pin_phase1).c_str(),
- pinName(_pin_phase2).c_str(),
- pinName(_pin_phase3).c_str());
-}
-
-void UnipolarMotor ::set_disable(bool disable) {
- if (disable) {
- digitalWrite(_pin_phase0, 0);
- digitalWrite(_pin_phase1, 0);
- digitalWrite(_pin_phase2, 0);
- digitalWrite(_pin_phase3, 0);
- }
- _enabled = !disable;
-}
-
-void UnipolarMotor::step(uint8_t step_mask, uint8_t dir_mask) {
- uint8_t _phase[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; // temporary phase values...all start as off
- uint8_t phase_max;
-
- if (!(step_mask & bit(axis_index)))
- return; // a step is not required on this interrupt
-
- if (!_enabled)
- return; // don't do anything, phase is not changed or lost
-
- if (_half_step)
- phase_max = 7;
- else
- phase_max = 3;
-
- if (dir_mask & bit(axis_index)) { // count up
- if (_current_phase == phase_max)
- _current_phase = 0;
- else
- _current_phase++;
- } else { // count down
- if (_current_phase == 0)
- _current_phase = phase_max;
- else
- _current_phase--;
- }
- /*
- 8 Step : A – AB – B – BC – C – CD – D – DA
- 4 Step : AB – BC – CD – DA
-
- Step IN4 IN3 IN2 IN1
- A 0 0 0 1
- AB 0 0 1 1
- B 0 0 1 0
- BC 0 1 1 0
- C 0 1 0 0
- CD 1 1 0 0
- D 1 0 0 0
- DA 1 0 0 1
- */
- if (_half_step) {
- switch (_current_phase) {
- case 0: _phase[0] = 1; break;
- case 1:
- _phase[0] = 1;
- _phase[1] = 1;
- break;
- case 2: _phase[1] = 1; break;
- case 3:
- _phase[1] = 1;
- _phase[2] = 1;
- break;
- case 4: _phase[2] = 1; break;
- case 5:
- _phase[2] = 1;
- _phase[3] = 1;
- break;
- case 6: _phase[3] = 1; break;
- case 7:
- _phase[3] = 1;
- _phase[0] = 1;
- break;
- }
- } else {
- switch (_current_phase) {
- case 0:
- _phase[0] = 1;
- _phase[1] = 1;
- break;
- case 1:
- _phase[1] = 1;
- _phase[2] = 1;
- break;
- case 2:
- _phase[2] = 1;
- _phase[3] = 1;
- break;
- case 3:
- _phase[3] = 1;
- _phase[0] = 1;
- break;
- }
- }
- digitalWrite(_pin_phase0, _phase[0]);
- digitalWrite(_pin_phase1, _phase[1]);
- digitalWrite(_pin_phase2, _phase[2]);
- digitalWrite(_pin_phase3, _phase[3]);
-}
diff --git a/Grbl_Esp32/src/grbl.h b/Grbl_Esp32/src/grbl.h
index 56bdd0b4..42965b95 100644
--- a/Grbl_Esp32/src/grbl.h
+++ b/Grbl_Esp32/src/grbl.h
@@ -57,7 +57,7 @@
#include "serial.h"
#include "Pins.h"
#include "Spindles/SpindleClass.h"
-#include "Motors/MotorClass.h"
+#include "Motors/Motors.h"
#include "stepper.h"
#include "jog.h"
#include "inputbuffer.h"
diff --git a/Grbl_Esp32/src/servo_axis.cpp b/Grbl_Esp32/src/servo_axis.cpp
index fec865c4..85589e35 100644
--- a/Grbl_Esp32/src/servo_axis.cpp
+++ b/Grbl_Esp32/src/servo_axis.cpp
@@ -24,6 +24,8 @@
#include "grbl.h"
+#include "servo_axis.h"
+
#ifdef USE_SERVO_AXES
static TaskHandle_t servosSyncTaskHandle = 0;
diff --git a/Grbl_Esp32/src/servo_axis.h b/Grbl_Esp32/src/servo_axis.h
index fe9399ac..031ea15c 100644
--- a/Grbl_Esp32/src/servo_axis.h
+++ b/Grbl_Esp32/src/servo_axis.h
@@ -53,7 +53,7 @@
*/
-#include "Motors/RcServoClass.h"
+#include "Motors/RcServoSettings.h"
#define SERVO_HOMING_OFF 0 // servo is off during homing
#define SERVO_HOMING_TARGET 1 // servo is send to a location during homing