mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-09-02 19:02:35 +02:00
Added solenoid class
This commit is contained in:
@@ -213,6 +213,7 @@
|
||||
#define SPINDLE_TYPE SPINDLE_TYPE_NONE
|
||||
*/
|
||||
|
||||
/*
|
||||
// ======================= SPI 4 axis xxyz ===========================
|
||||
#define MACHINE_NAME "MotorClass Test 4x SPI XXYZ A Servo"
|
||||
#define N_AXIS 4
|
||||
@@ -254,3 +255,35 @@
|
||||
#define A_SERVO_RANGE_MAX 5.0
|
||||
|
||||
#define SPINDLE_TYPE SPINDLE_TYPE_NONE
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define MACHINE_NAME "Solenoid test using TMC2130 pen"
|
||||
|
||||
#define X_STEP_PIN GPIO_NUM_12
|
||||
#define X_DIRECTION_PIN GPIO_NUM_26
|
||||
#define X_TRINAMIC_DRIVER 2130 // Which Driver Type?
|
||||
#define X_CS_PIN GPIO_NUM_17 //chip select
|
||||
#define X_RSENSE TMC2130_RSENSE_DEFAULT
|
||||
|
||||
#define Y_STEP_PIN GPIO_NUM_14
|
||||
#define Y_DIRECTION_PIN GPIO_NUM_25
|
||||
#define Y_TRINAMIC_DRIVER 2130 // Which Driver Type?
|
||||
#define Y_CS_PIN GPIO_NUM_16 //chip select
|
||||
#define Y_RSENSE TMC2130_RSENSE_DEFAULT
|
||||
|
||||
// OK to comment out to use pin for other features
|
||||
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
|
||||
|
||||
#define Z_SOLENOID_PIN GPIO_NUM_27 // comment this out if PWM spindle/laser control.
|
||||
#define Z_SOLENOID_MAX 5.0
|
||||
#define SOLENOID_ALLOW_DISABLE true // solenoid will turn off when motors diable
|
||||
|
||||
#define X_LIMIT_PIN GPIO_NUM_32
|
||||
#define Y_LIMIT_PIN GPIO_NUM_4
|
||||
#define LIMIT_MASK B11
|
||||
|
||||
// defaults
|
||||
#define DEFAULT_Z_STEPS_PER_MM 100.0 // This is used as the servo calibration
|
||||
#define DEFAULT_Z_MAX_TRAVEL 300.0 // This is used as the servo calibration
|
@@ -30,7 +30,6 @@
|
||||
#endif
|
||||
#define N_AXIS 3 // can be 3 or 4. (if 3 install bypass jumper next to the A driver)
|
||||
|
||||
#define USE_TRINAMIC
|
||||
#define TRINAMIC_DAISY_CHAIN
|
||||
|
||||
// Use SPI enable instead of the enable pin
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#endif
|
||||
#define N_AXIS 3
|
||||
|
||||
#define USE_TRINAMIC
|
||||
#define TRINAMIC_DAISY_CHAIN
|
||||
|
||||
// Use SPI enable instead of the enable pin
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#endif
|
||||
#define N_AXIS 4 // can be 3 or 4. (if 3 install bypass jumper next to the A driver)
|
||||
|
||||
#define USE_TRINAMIC
|
||||
#define TRINAMIC_DAISY_CHAIN
|
||||
|
||||
// Use SPI enable instead of the enable pin
|
||||
|
@@ -35,8 +35,6 @@
|
||||
#define X_LIMIT_PIN GPIO_NUM_32
|
||||
#endif
|
||||
|
||||
#define USE_TRINAMIC // Using at least 1 trinamic driver
|
||||
|
||||
#define X_STEP_PIN GPIO_NUM_12
|
||||
#define X_DIRECTION_PIN GPIO_NUM_26
|
||||
#define X_TRINAMIC_DRIVER 2130 // Which Driver Type?
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#include "StandardStepperClass.cpp"
|
||||
#include "UnipolarMotorClass.cpp"
|
||||
#include "RcServoClass.cpp"
|
||||
#include "SolenoidClass.cpp"
|
||||
|
||||
Motor* myMotor[6][2]; // number of axes (normal and ganged)
|
||||
static TaskHandle_t readSgTaskHandle = 0; // for realtime stallguard data diaplay
|
||||
@@ -121,6 +122,8 @@ void init_motors() {
|
||||
myMotor[Z_AXIS][0] = new UnipolarMotor(Z_AXIS, Z_PIN_PHASE_0, Z_PIN_PHASE_1, Z_PIN_PHASE_2, Z_PIN_PHASE_3);
|
||||
#elif defined(Z_STEP_PIN)
|
||||
myMotor[Z_AXIS][0] = new StandardStepper(Z_AXIS, Z_STEP_PIN, Z_DIRECTION_PIN);
|
||||
#elif defined(Z_SOLENOID_PIN)
|
||||
myMotor[Z_AXIS][0] = new Solenoid(Z_AXIS, Z_SOLENOID_PIN, Z_SOLENOID_MAX);
|
||||
#else
|
||||
myMotor[Z_AXIS][0] = new Nullmotor();
|
||||
#endif
|
||||
@@ -244,8 +247,11 @@ void init_motors() {
|
||||
// certain motors need features to be turned on. Check them here
|
||||
for (uint8_t axis = X_AXIS; axis < N_AXIS; axis++) {
|
||||
for (uint8_t gang_index = 0; gang_index < 2; gang_index++) {
|
||||
if (myMotor[axis][gang_index]->type_id == RC_SERVO_MOTOR) need_servo_task = true;
|
||||
if (myMotor[axis][gang_index]->type_id == UNIPOLAR_MOTOR) motor_class_steps = true;
|
||||
if (myMotor[axis][gang_index]->type_id == RC_SERVO_MOTOR || myMotor[axis][gang_index]->type_id == SOLENOID)
|
||||
need_servo_task = true;
|
||||
|
||||
if (myMotor[axis][gang_index]->type_id == UNIPOLAR_MOTOR)
|
||||
motor_class_steps = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -55,6 +55,7 @@
|
||||
#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];
|
||||
@@ -66,7 +67,8 @@ typedef enum {
|
||||
STANDARD_MOTOR,
|
||||
TRINAMIC_SPI_MOTOR,
|
||||
UNIPOLAR_MOTOR,
|
||||
RC_SERVO_MOTOR
|
||||
RC_SERVO_MOTOR,
|
||||
SOLENOID
|
||||
} motor_class_id_t;
|
||||
|
||||
// ========== global functions ===================
|
||||
@@ -108,7 +110,7 @@ class Motor {
|
||||
protected:
|
||||
uint8_t axis_index; // X_AXIS, etc
|
||||
uint8_t dual_axis_index; // 0 = primary 1=ganged
|
||||
|
||||
|
||||
bool _showError;
|
||||
bool _use_mpos = true;
|
||||
bool _is_homing;
|
||||
@@ -187,27 +189,41 @@ class RcServo : public Motor {
|
||||
public:
|
||||
RcServo();
|
||||
RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max);
|
||||
void config_message();
|
||||
void init();
|
||||
virtual void config_message();
|
||||
virtual void init();
|
||||
void _write_pwm(uint32_t duty);
|
||||
void set_disable(bool disable);
|
||||
void update();
|
||||
virtual void set_disable(bool disable);
|
||||
virtual void update();
|
||||
void read_settings();
|
||||
|
||||
private:
|
||||
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 servo_pulse_min;
|
||||
float servo_pulse_max;
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -56,11 +56,8 @@ RcServo :: RcServo(uint8_t axis_index, uint8_t pwm_pin, float min, float max) {
|
||||
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;
|
||||
set_axis_name();
|
||||
init();
|
||||
config_message();
|
||||
is_active = true; // as opposed to NullMotors, this is a real motor
|
||||
_position_max = max;
|
||||
init();
|
||||
}
|
||||
|
||||
void RcServo :: init() {
|
||||
@@ -69,6 +66,9 @@ void RcServo :: init() {
|
||||
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() {
|
||||
@@ -94,11 +94,15 @@ void RcServo::_write_pwm(uint32_t duty) {
|
||||
|
||||
// sets the PWM to zero. This allows most servos to be manually moved
|
||||
void RcServo::set_disable(bool disable) {
|
||||
if (disable)
|
||||
_disabled = disable;
|
||||
if (_disabled)
|
||||
_write_pwm(0);
|
||||
}
|
||||
|
||||
void RcServo::update() {
|
||||
if (_disabled)
|
||||
return;
|
||||
|
||||
set_location();
|
||||
}
|
||||
|
||||
@@ -128,7 +132,7 @@ void RcServo::set_location() {
|
||||
}
|
||||
|
||||
// determine the pulse length
|
||||
servo_pulse_len = (uint32_t)mapConstrain(servo_pos, _position_min, _position_max, servo_pulse_min, servo_pulse_max);
|
||||
servo_pulse_len = (uint32_t)mapConstrain(servo_pos, _position_min, _position_max, _pwm_pulse_min, _pwm_pulse_max);
|
||||
_write_pwm(servo_pulse_len);
|
||||
|
||||
}
|
||||
@@ -163,14 +167,14 @@ void RcServo::_get_calibration() {
|
||||
write_global_settings(); // they were changed, so write them
|
||||
}
|
||||
|
||||
servo_pulse_min = SERVO_MIN_PULSE;
|
||||
servo_pulse_max = SERVO_MAX_PULSE;
|
||||
_pwm_pulse_min = SERVO_MIN_PULSE;
|
||||
_pwm_pulse_max = SERVO_MAX_PULSE;
|
||||
|
||||
// apply inverts and store them in local variable
|
||||
if (bit_istrue(settings.dir_invert_mask, bit(axis_index))) { // normal direction
|
||||
_cal_min = 2.0 - (settings.steps_per_mm[axis_index] / 100.0);
|
||||
_cal_max = 2.0 - (settings.max_travel[axis_index] / -100.0);
|
||||
swap(servo_pulse_min, servo_pulse_max);
|
||||
swap(_pwm_pulse_min, _pwm_pulse_max);
|
||||
} else { // inverted direction
|
||||
_cal_min = (settings.steps_per_mm[axis_index] / 100.0);
|
||||
//_cal_max = 2.0 - (settings.max_travel[axis_index] / -100.0);
|
||||
@@ -179,7 +183,7 @@ void RcServo::_get_calibration() {
|
||||
|
||||
//grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Servo calibration min%1.2f max %1.2f", _cal_min, _cal_max );
|
||||
|
||||
servo_pulse_min *= _cal_min;
|
||||
servo_pulse_max *= _cal_max;
|
||||
_pwm_pulse_min *= _cal_min;
|
||||
_pwm_pulse_max *= _cal_max;
|
||||
}
|
||||
|
||||
|
119
Grbl_Esp32/Motors/SolenoidClass.cpp
Normal file
119
Grbl_Esp32/Motors/SolenoidClass.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
The solenoid monitors the current position of the Axis
|
||||
it is assigned to. It uses a max and max position value and a max and min pulse
|
||||
length.
|
||||
|
||||
The solenoid turns on when it is equal to or greater than _position_max
|
||||
|
||||
Tests
|
||||
- Does it turn on at the transition point?
|
||||
- Doess hold duration an reduction work?
|
||||
- Does $3 reverse the direction?
|
||||
- Do homing work to move axis and set pulse currectly
|
||||
- Does diable work?
|
||||
|
||||
|
||||
*/
|
||||
|
||||
Solenoid :: Solenoid(uint8_t axis_index, gpio_num_t pwm_pin, float transition_poiont) {
|
||||
type_id = SOLENOID;
|
||||
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;
|
||||
_transition_poiont = transition_poiont;
|
||||
init();
|
||||
}
|
||||
|
||||
void Solenoid :: init() {
|
||||
//read_settings();
|
||||
_channel_num = sys_get_next_PWM_chan_num();
|
||||
ledcSetup(_channel_num, SOLENOID_PULSE_FREQ, SOLENOID_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 Solenoid :: config_message() {
|
||||
grbl_msg_sendf(CLIENT_SERIAL,
|
||||
MSG_LEVEL_INFO,
|
||||
"%s Axis Solenoid Output:%d Max:%5.3fmm",
|
||||
_axis_name,
|
||||
_pwm_pin,
|
||||
_transition_poiont);
|
||||
}
|
||||
|
||||
void Solenoid::set_disable(bool disable) {
|
||||
if (disable && SOLENOID_ALLOW_DISABLE)
|
||||
_write_pwm(0);
|
||||
|
||||
_disabled = disable;
|
||||
}
|
||||
|
||||
void Solenoid::update() {
|
||||
set_location();
|
||||
}
|
||||
|
||||
void Solenoid::set_location() {
|
||||
float solenoid_pos, mpos, offset;
|
||||
uint32_t duty;
|
||||
static uint8_t hold_counter;
|
||||
static uint32_t last_duty = 0;
|
||||
|
||||
if (_disabled && SOLENOID_ALLOW_DISABLE)
|
||||
return;
|
||||
|
||||
_pwm_pulse_min = SOLENOID_MIN_PULSE;
|
||||
_pwm_pulse_max = SOLENOID_MAX_PULSE;
|
||||
|
||||
// Is direction reversed via the $3 command?
|
||||
if (bit_istrue(settings.dir_invert_mask, bit(axis_index))) // normal direction
|
||||
swap(_pwm_pulse_min, _pwm_pulse_max);
|
||||
|
||||
// $23 sets homing direction bit_true homes in positive direction
|
||||
if (sys.state == STATE_HOMING) {
|
||||
bool home_positive;
|
||||
home_positive = bit_isfalse(settings.homing_dir_mask, bit(axis_index)); // no bit = home positive
|
||||
|
||||
if (bit_istrue(settings.dir_invert_mask, bit(axis_index)))
|
||||
home_positive = ! home_positive;
|
||||
|
||||
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Solenoid Home Pos2:%d", _axis_name, home_positive);
|
||||
|
||||
if (home_positive)
|
||||
duty = _pwm_pulse_max;
|
||||
else
|
||||
duty = _pwm_pulse_min;
|
||||
|
||||
} else {
|
||||
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
|
||||
solenoid_pos = mpos - offset; // determine the current work position
|
||||
|
||||
if (solenoid_pos >= _position_max)
|
||||
duty = _pwm_pulse_max;
|
||||
else
|
||||
duty = _pwm_pulse_min;
|
||||
}
|
||||
|
||||
|
||||
if (duty != last_duty) {
|
||||
hold_counter = 0; // reset the hold counter
|
||||
last_duty = duty; // remember the duty
|
||||
} else {
|
||||
if (duty != SOLENOID_MIN_PULSE) {
|
||||
if (hold_counter >= SOLENOID_HOLD_DELAY) {
|
||||
duty *= (SOLENOID_HOLD_PERCENTAGE / 100.0); // apply the hold current
|
||||
} else
|
||||
hold_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
//grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "%s Solenoid Pwm %d", _axis_name, duty);
|
||||
|
||||
_write_pwm(duty);
|
||||
|
||||
|
||||
}
|
||||
|
25
Grbl_Esp32/Motors/SolenoidClass.h
Normal file
25
Grbl_Esp32/Motors/SolenoidClass.h
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
|
||||
#define SOLENOID_PULSE_FREQ 5000 // 50Hz ...This is a standard analog servo value. Digital ones can repeat faster
|
||||
|
||||
#define SOLENOID_PULSE_RES_BITS 10 // bits of resolution of PWM (16 is max)
|
||||
|
||||
#ifndef SOLENOID_MIN_PULSE
|
||||
#define SOLENOID_MIN_PULSE 0
|
||||
#endif
|
||||
|
||||
#ifndef SOLENOID_MAX_PULSE
|
||||
#define SOLENOID_MAX_PULSE 1024
|
||||
#endif
|
||||
|
||||
#ifndef SOLENOID_HOLD_DELAY
|
||||
#define SOLENOID_HOLD_DELAY 10 // task counts
|
||||
#endif
|
||||
|
||||
#ifndef SOLENOID_HOLD_PERCENTAGE
|
||||
#define SOLENOID_HOLD_PERCENTAGE 60.0 // percent of SOLENOID_MAX_PULSE
|
||||
#endif
|
||||
|
||||
#ifndef SOLENOID_ALLOW_DISABLE
|
||||
#define SOLENOID_ALLOW_DISABLE false
|
||||
#endif
|
Reference in New Issue
Block a user