mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-08-19 12:51:47 +02:00
Split motor files into separate files and introduced namespace Motors (#522)
* Renamed some files to match the class name. * Split out motor class into different files. * Fixed last newline in cpp/h files Co-authored-by: Stefan de Bruijn <stefan@nubilosoft.com>
This commit is contained in:
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
insert_final_newline = true
|
53
Grbl_Esp32/src/Motors/Motor.cpp
Normal file
53
Grbl_Esp32/src/Motors/Motor.cpp
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
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; }
|
||||
}
|
65
Grbl_Esp32/src/Motors/Motor.h
Normal file
65
Grbl_Esp32/src/Motors/Motor.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Motors.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
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"
|
||||
};
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../grbl.h"
|
||||
#include <TMCStepper.h> // 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;
|
||||
};
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
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;
|
||||
}
|
53
Grbl_Esp32/src/Motors/Motors.h
Normal file
53
Grbl_Esp32/src/Motors/Motors.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../grbl.h"
|
||||
#include <TMCStepper.h> // 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
|
7
Grbl_Esp32/src/Motors/NullMotor.h
Normal file
7
Grbl_Esp32/src/Motors/NullMotor.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Motor.h"
|
||||
|
||||
namespace Motors {
|
||||
class Nullmotor : public Motor {};
|
||||
}
|
189
Grbl_Esp32/src/Motors/RcServo.cpp
Normal file
189
Grbl_Esp32/src/Motors/RcServo.cpp
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
55
Grbl_Esp32/src/Motors/RcServo.h
Normal file
55
Grbl_Esp32/src/Motors/RcServo.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
};
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// 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
|
18
Grbl_Esp32/src/Motors/Solenoid.h
Normal file
18
Grbl_Esp32/src/Motors/Solenoid.h
Normal file
@@ -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;
|
||||
};
|
||||
}
|
103
Grbl_Esp32/src/Motors/StandardStepper.cpp
Normal file
103
Grbl_Esp32/src/Motors/StandardStepper.cpp
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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); }
|
||||
}
|
23
Grbl_Esp32/src/Motors/StandardStepper.h
Normal file
23
Grbl_Esp32/src/Motors/StandardStepper.h
Normal file
@@ -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;
|
||||
};
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
235
Grbl_Esp32/src/Motors/TrinamicDriver.cpp
Normal file
235
Grbl_Esp32/src/Motors/TrinamicDriver.cpp
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "TrinamicDriver.h"
|
||||
|
||||
#include <TMCStepper.h>
|
||||
|
||||
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.
|
||||
}
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
TrinamicDriverClass.h
|
||||
TrinamicDriver.h
|
||||
|
||||
Part of Grbl_ESP32
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Motor.h"
|
||||
#include "StandardStepper.h"
|
||||
#include <TMCStepper.h> // 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 <TMCStepper.h> // 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;
|
||||
};
|
||||
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "MotorClass.h"
|
||||
#include <TMCStepper.h>
|
||||
#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.
|
||||
}
|
139
Grbl_Esp32/src/Motors/UnipolarMotor.cpp
Normal file
139
Grbl_Esp32/src/Motors/UnipolarMotor.cpp
Normal file
@@ -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]);
|
||||
}
|
||||
}
|
24
Grbl_Esp32/src/Motors/UnipolarMotor.h
Normal file
24
Grbl_Esp32/src/Motors/UnipolarMotor.h
Normal file
@@ -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;
|
||||
};
|
||||
}
|
@@ -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]);
|
||||
}
|
@@ -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"
|
||||
|
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "grbl.h"
|
||||
|
||||
#include "servo_axis.h"
|
||||
|
||||
#ifdef USE_SERVO_AXES
|
||||
|
||||
static TaskHandle_t servosSyncTaskHandle = 0;
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user