1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-02 10:53:01 +02:00

Merge pull request #356 from bdring/Devt

Auto assigned PWM channels
This commit is contained in:
bdring
2020-03-22 20:41:01 +01:00
committed by GitHub
16 changed files with 354 additions and 414 deletions

View File

@@ -35,24 +35,21 @@
static TaskHandle_t solenoidSyncTaskHandle = 0;
static TaskHandle_t atariHomingTaskHandle = 0;
int8_t solenoid_pwm_chan_num;
uint16_t solenoid_pull_count;
bool atari_homing = false;
uint8_t homing_phase = HOMING_PHASE_FULL_APPROACH;
uint8_t current_tool;
void machine_init()
{
void machine_init() {
solenoid_pull_count = 0; // initialize
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Atari 1020 Solenoid");
// setup PWM channel
ledcSetup(SOLENOID_CHANNEL_NUM, SOLENOID_PWM_FREQ, SOLENOID_PWM_RES_BITS);
ledcAttachPin(SOLENOID_PEN_PIN, SOLENOID_CHANNEL_NUM);
solenoid_pwm_chan_num = sys_get_next_PWM_chan_num();
ledcSetup(solenoid_pwm_chan_num, SOLENOID_PWM_FREQ, SOLENOID_PWM_RES_BITS);
ledcAttachPin(SOLENOID_PEN_PIN, solenoid_pwm_chan_num);
pinMode(SOLENOID_DIRECTION_PIN, OUTPUT); // this sets the direction of the solenoid current
pinMode(REED_SW_PIN, INPUT_PULLUP); // external pullup required
// setup a task that will calculate solenoid position
xTaskCreatePinnedToCore(solenoidSyncTask, // task
"solenoidSyncTask", // name for task
@@ -74,21 +71,17 @@ void machine_init()
}
// this task tracks the Z position and sets the solenoid
void solenoidSyncTask(void *pvParameters)
{
void solenoidSyncTask(void* pvParameters) {
int32_t current_position[N_AXIS]; // copy of current location
float m_pos[N_AXIS]; // machine position in mm
TickType_t xLastWakeTime;
const TickType_t xSolenoidFrequency = SOLENOID_TASK_FREQ; // in ticks (typically ms)
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
while (true)
{ // don't ever return from this or the task dies
while (true) {
// don't ever return from this or the task dies
memcpy(current_position, sys_position, sizeof(sys_position)); // get current position in step
system_convert_array_steps_to_mpos(m_pos, current_position); // convert to millimeters
calc_solenoid(m_pos[Z_AXIS]); // calculate kinematics and move the servos
vTaskDelayUntil(&xLastWakeTime, xSolenoidFrequency);
}
}
@@ -97,8 +90,7 @@ void solenoidSyncTask(void *pvParameters)
// continue with regular homing after setup
// return true if this completes homing
bool user_defined_homing()
{
bool user_defined_homing() {
// create and start a task to do the special homing
homing_phase = HOMING_PHASE_FULL_APPROACH;
atari_homing = true;
@@ -120,23 +112,17 @@ bool user_defined_homing()
TODO can the retract, move back be 1 phase rather than 2?
*/
void atari_home_task(void *pvParameters)
{
void atari_home_task(void* pvParameters) {
uint8_t homing_attempt = 0; // how many times have we tried to home
TickType_t xLastWakeTime;
const TickType_t xHomingTaskFrequency = 100; // in ticks (typically ms) .... need to make sure there is enough time to get out of idle
char gcode_line[20];
while (true)
{ // this task will only last as long as it is homing
if (atari_homing)
{
while (true) {
// this task will only last as long as it is homing
if (atari_homing) {
// must be in idle or alarm state
if (sys.state == STATE_IDLE)
{
switch (homing_phase)
{
if (sys.state == STATE_IDLE) {
switch (homing_phase) {
case HOMING_PHASE_FULL_APPROACH: // a full width move to insure it hits left end
inputBuffer.push("G90G0Z1\r"); // lift the pen
sprintf(gcode_line, "G91G0X%3.2f\r", -ATARI_PAPER_WIDTH + ATARI_HOME_POS - 3.0); // plus a little extra
@@ -145,26 +131,20 @@ void atari_home_task(void *pvParameters)
homing_phase = HOMING_PHASE_CHECK;
break;
case HOMING_PHASE_CHECK: // check the limits switch
if (digitalRead(REED_SW_PIN) == 0)
{ // see if reed switch is grounded
if (digitalRead(REED_SW_PIN) == 0) {
// see if reed switch is grounded
inputBuffer.push("G4P0.1\n"); // dramtic pause
sys_position[X_AXIS] = ATARI_HOME_POS * settings.steps_per_mm[X_AXIS];
sys_position[Y_AXIS] = 0.0;
sys_position[Z_AXIS] = 1.0 * settings.steps_per_mm[Y_AXIS];
gc_sync_position();
plan_sync_position();
sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls
inputBuffer.push(gcode_line);
current_tool = 1; // local copy for reference...until actual M6 change
gc_state.tool = current_tool;
atari_homing = false; // done with homing sequence
}
else
{
} else {
homing_phase = HOMING_PHASE_RETRACT;
homing_attempt++;
}
@@ -182,9 +162,8 @@ void atari_home_task(void *pvParameters)
; // kills task
break;
}
if (homing_attempt > ATARI_HOMING_ATTEMPTS)
{ // try all positions plus 1
if (homing_attempt > ATARI_HOMING_ATTEMPTS) {
// try all positions plus 1
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Atari homing failed");
inputBuffer.push("G90\r");
atari_homing = false;
@@ -197,46 +176,35 @@ void atari_home_task(void *pvParameters)
}
// calculate and set the PWM value for the servo
void calc_solenoid(float penZ)
{
void calc_solenoid(float penZ) {
bool isPenUp;
static bool previousPenState = false;
uint32_t solenoid_pen_pulse_len; // duty cycle of solenoid
isPenUp = ((penZ > 0) || (sys.state == STATE_ALARM)); // is pen above Z0 or is there an alarm
// if the state has not change, we only count down to the pull time
if (previousPenState == isPenUp)
{ // if state is unchanged
if (solenoid_pull_count > 0)
{
if (previousPenState == isPenUp) {
// if state is unchanged
if (solenoid_pull_count > 0) {
solenoid_pull_count--;
solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_PULL; // stay at full power while counting down
}
else
{
} else {
solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_HOLD; // pull in delay has expired so lower duty cycle
}
}
else
{ // pen direction has changed
} else {
// pen direction has changed
solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_PULL; // go to full power
solenoid_pull_count = SOLENOID_PULL_DURATION; // set the time to count down
}
previousPenState = isPenUp; // save the prev state
digitalWrite(SOLENOID_DIRECTION_PIN, isPenUp);
// skip setting value if it is unchanged
if (ledcRead(SOLENOID_CHANNEL_NUM) == solenoid_pen_pulse_len)
if (ledcRead(solenoid_pwm_chan_num) == solenoid_pen_pulse_len)
return;
// update the PWM value
// ledcWrite appears to have issues with interrupts, so make this a critical section
portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&myMutex);
ledcWrite(SOLENOID_CHANNEL_NUM, solenoid_pen_pulse_len);
ledcWrite(solenoid_pwm_chan_num, solenoid_pen_pulse_len);
portEXIT_CRITICAL(&myMutex);
}
@@ -244,72 +212,50 @@ void calc_solenoid(float penZ)
A tool (pen) change is done by bumping the carriage against the right edge 3 times per
position change. Pen 1-4 is valid range.
*/
void user_tool_change(uint8_t new_tool)
{
void user_tool_change(uint8_t new_tool) {
uint8_t move_count;
char gcode_line[20];
protocol_buffer_synchronize(); // wait for all previous moves to complete
if ((new_tool < 1) || (new_tool > MAX_PEN_NUMBER))
{
if ((new_tool < 1) || (new_tool > MAX_PEN_NUMBER)) {
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Requested Pen#%d is out of 1-4 range", new_tool);
return;
}
if (new_tool == current_tool)
return;
if (new_tool > current_tool)
{
move_count = BUMPS_PER_PEN_CHANGE * (new_tool - current_tool);
}
else
{
move_count = BUMPS_PER_PEN_CHANGE * ((MAX_PEN_NUMBER - current_tool) + new_tool);
}
sprintf(gcode_line, "G0Z%3.2f\r", ATARI_TOOL_CHANGE_Z); // go to tool change height
inputBuffer.push(gcode_line);
for (uint8_t i = 0; i < move_count; i++)
{
for (uint8_t i = 0; i < move_count; i++) {
sprintf(gcode_line, "G0X%3.2f\r", ATARI_HOME_POS); //
inputBuffer.push(gcode_line);
inputBuffer.push("G0X0\r");
}
current_tool = new_tool;
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Change to Pen#%d", current_tool);
}
// move from current tool to next tool....
void atari_next_pen()
{
void atari_next_pen() {
if (current_tool < MAX_PEN_NUMBER)
{
gc_state.tool = current_tool + 1;
}
else
{
gc_state.tool = 1;
}
user_tool_change(gc_state.tool);
}
// Polar coaster has macro buttons, this handles those button pushes.
void user_defined_macro(uint8_t index)
{
void user_defined_macro(uint8_t index) {
char gcode_line[20];
switch (index)
{
switch (index) {
#ifdef MACRO_BUTTON_0_PIN
case CONTROL_PIN_INDEX_MACRO_0:
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Pen switch");
inputBuffer.push("$H\r");
break;
#endif
#ifdef MACRO_BUTTON_1_PIN
case CONTROL_PIN_INDEX_MACRO_1:
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Color switch");
@@ -318,7 +264,6 @@ void user_defined_macro(uint8_t index)
inputBuffer.push(gcode_line);
break;
#endif
#ifdef MACRO_BUTTON_2_PIN
case CONTROL_PIN_INDEX_MACRO_2:
// feed out some paper and reset the Y 0
@@ -330,15 +275,13 @@ void user_defined_macro(uint8_t index)
plan_sync_position();
break;
#endif
default:
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Unknown Switch %d", index);
break;
}
}
void user_m30()
{
void user_m30() {
char gcode_line[20];
sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); //
inputBuffer.push(gcode_line);

View File

@@ -33,7 +33,7 @@
#define CUSTOM_CODE_FILENAME "Custom/atari_1020.cpp"
#ifdef USE_RMT_STEPS
#undef USE_RMT_STEPS
#undef USE_RMT_STEPS
#endif
#define USE_UNIPOLAR
@@ -52,32 +52,31 @@
#define SOLENOID_DIRECTION_PIN GPIO_NUM_4
#define SOLENOID_PEN_PIN GPIO_NUM_2
#define SOLENOID_CHANNEL_NUM 6
#ifdef HOMING_CYCLE_0
#undef HOMING_CYCLE_0
#undef HOMING_CYCLE_0
#endif
#define HOMING_CYCLE_0 (1 << X_AXIS) // this 'bot only homes the X axis
#ifdef HOMING_CYCLE_1
#undef HOMING_CYCLE_1
#undef HOMING_CYCLE_1
#endif
#ifdef HOMING_CYCLE_2
#undef HOMING_CYCLE_2
#undef HOMING_CYCLE_2
#endif
#define REED_SW_PIN GPIO_NUM_17
#define LIMIT_MASK 0
#ifdef IGNORE_CONTROL_PINS // maybe set in config.h
#undef IGNORE_CONTROL_PINS
#undef IGNORE_CONTROL_PINS
#endif
#ifndef ENABLE_CONTROL_SW_DEBOUNCE
#define ENABLE_CONTROL_SW_DEBOUNCE
#define ENABLE_CONTROL_SW_DEBOUNCE
#endif
#ifdef INVERT_CONTROL_PIN_MASK
#undef INVERT_CONTROL_PIN_MASK
#undef INVERT_CONTROL_PIN_MASK
#endif
#define INVERT_CONTROL_PIN_MASK B01110000
@@ -86,7 +85,7 @@
#define MACRO_BUTTON_2_PIN GPIO_NUM_36 // Paper Switch
#ifdef DEFAULTS_GENERIC
#undef DEFAULTS_GENERIC // undefine generic then define each default below
#undef DEFAULTS_GENERIC // undefine generic then define each default below
#endif
#define DEFAULT_STEP_PULSE_MICROSECONDS 3
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 200 // 200ms
@@ -160,11 +159,11 @@
#define USE_M30 // use the user defined end of program
#ifndef atari_h
#define atari_h
#define atari_h
void solenoid_disable();
void solenoidSyncTask(void *pvParameters);
void calc_solenoid(float penZ);
void atari_home_task(void *pvParameters);
void atari_next_pen();
void solenoid_disable();
void solenoidSyncTask(void* pvParameters);
void calc_solenoid(float penZ);
void atari_home_task(void* pvParameters);
void atari_next_pen();
#endif

View File

@@ -24,9 +24,8 @@
#define MACHINE_NAME "MACHINE_FOO_6X"
// Be sure to change to N_AXIS 6 in nuts_bolts.h
#ifdef N_AXIS
#undef N_AXIS
#undef N_AXIS
#endif
#define N_AXIS 6
@@ -50,7 +49,6 @@
// servos
#define USE_SERVO_AXES
#define SERVO_Z_PIN GPIO_NUM_22
#define SERVO_Z_CHANNEL_NUM 6
#define SERVO_Z_RANGE_MIN 0.0
#define SERVO_Z_RANGE_MAX 5.0
#define SERVO_Z_HOMING_TYPE SERVO_HOMING_TARGET // during homing it will instantly move to a target value
@@ -58,7 +56,6 @@
#define SERVO_Z_MPOS false // will not use mpos, uses work coordinates
#define SERVO_C_PIN GPIO_NUM_2
#define SERVO_C_CHANNEL_NUM 7
#define SERVO_C_RANGE_MIN 0.0
#define SERVO_C_RANGE_MAX 5.0
#define SERVO_C_HOMING_TYPE SERVO_HOMING_TARGET // during homing it will instantly move to a target value

View File

@@ -31,7 +31,7 @@
#define Y_DIRECTION_PIN GPIO_NUM_25
#ifndef COREXY // maybe set in config.h
#define COREXY
#define COREXY
#endif
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
@@ -41,11 +41,10 @@
#define LIMIT_MASK B11
#ifndef USE_SERVO_AXES // maybe set in config.h
#define USE_SERVO_AXES
#define USE_SERVO_AXES
#endif
#define SERVO_Z_PIN GPIO_NUM_27
#define SERVO_Z_CHANNEL_NUM 5
#define SERVO_Z_RANGE_MIN 0.0
#define SERVO_Z_RANGE_MAX 5.0
#define SERVO_Z_HOMING_TYPE SERVO_HOMING_TARGET // during homing it will instantly move to a target value
@@ -58,19 +57,19 @@
// redefine some stuff from config.h
#ifdef HOMING_CYCLE_0
#undef HOMING_CYCLE_0
#undef HOMING_CYCLE_0
#endif
#define HOMING_CYCLE_0 (1<<Y_AXIS)
#ifdef HOMING_CYCLE_1
#undef HOMING_CYCLE_1
#undef HOMING_CYCLE_1
#endif
#define HOMING_CYCLE_1 (1<<X_AXIS)
#ifdef HOMING_CYCLE_2
#undef HOMING_CYCLE_2
#undef HOMING_CYCLE_2
#endif
#define SERVO_PEN_PIN GPIO_NUM_27

View File

@@ -59,7 +59,6 @@
#ifdef USING_SERVO
#define USE_SERVO_AXES
#define SERVO_Z_PIN GPIO_NUM_27
#define SERVO_Z_CHANNEL_NUM 3
#define SERVO_Z_RANGE_MIN 0
#define SERVO_Z_RANGE_MAX 10
#endif
@@ -67,7 +66,6 @@
#ifdef USING_SOLENOID
#define USE_PEN_SOLENOID
#define SOLENOID_PEN_PIN GPIO_NUM_16
#define SOLENOID_CHANNEL_NUM 6
#endif
// defaults

View File

@@ -48,7 +48,6 @@
#endif
#define SERVO_Z_PIN GPIO_NUM_16
#define SERVO_Z_CHANNEL_NUM 5
#define SERVO_Z_RANGE_MIN 0.0
#define SERVO_Z_RANGE_MAX 5.0
#define SERVO_Z_HOMING_TYPE SERVO_HOMING_TARGET // during homing it will instantly move to a target value

View File

@@ -39,11 +39,11 @@
#define STEPPERS_DISABLE_PIN GPIO_NUM_13
#ifdef PEN_LASER_V1
#define X_LIMIT_PIN GPIO_NUM_2
#define X_LIMIT_PIN GPIO_NUM_2
#endif
#ifdef PEN_LASER_V2
#define X_LIMIT_PIN GPIO_NUM_15
#define X_LIMIT_PIN GPIO_NUM_15
#endif
#define Y_LIMIT_PIN GPIO_NUM_4
@@ -61,16 +61,14 @@
#define SPINDLE_PWM_OFF_VALUE 0
#ifndef SPINDLE_PWM_MIN_VALUE
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#define SPINDLE_PWM_MIN_VALUE 1 // Must be greater than zero.
#endif
#define SERVO_Y_PIN GPIO_NUM_14
#define SERVO_Y_CHANNEL_NUM 6
#define SERVO_Y_RANGE_MIN 0.0
#define SERVO_Y_RANGE_MAX 30.0
#define SERVO_Z_PIN GPIO_NUM_27
#define SERVO_Z_CHANNEL_NUM 5
#define SERVO_Z_RANGE_MIN 0.0
#define SERVO_Z_RANGE_MAX 20.0

View File

@@ -135,7 +135,6 @@
// #define USE_SERVO_AXES
// #define SERVO_Z_PIN GPIO_NUM_22
// #define SERVO_Z_CHANNEL_NUM 6
// #define SERVO_Z_RANGE_MIN 0.0
// #define SERVO_Z_RANGE_MAX 5.0
// #define SERVO_Z_HOMING_TYPE SERVO_HOMING_TARGET // during homing it will instantly move to a target value

View File

@@ -59,7 +59,6 @@
#endif
#define SERVO_Z_PIN GPIO_NUM_27 // comment this out if PWM spindle/laser control.
#define SERVO_Z_CHANNEL_NUM 5
#define SERVO_Z_RANGE_MIN 0.0
#define SERVO_Z_RANGE_MAX 5.0
#define SERVO_Z_HOMING_TYPE SERVO_HOMING_TARGET // during homing it will instantly move to a target value

View File

@@ -6,7 +6,6 @@
#endif
#define SPINDLE_PWM_MAX_VALUE ((1<<SPINDLE_PWM_BIT_PRECISION) - 1)
#define SPINDLE_PWM_CHANNEL 0
// Grbl setting that are common to all machines
// It should not be necessary to change anything herein

View File

@@ -29,122 +29,116 @@
static TaskHandle_t servosSyncTaskHandle = 0;
#ifdef SERVO_X_PIN
ServoAxis X_Servo_Axis(X_AXIS, SERVO_X_PIN, SERVO_X_CHANNEL_NUM);
ServoAxis X_Servo_Axis(X_AXIS, SERVO_X_PIN);
#endif
#ifdef SERVO_Y_PIN
ServoAxis Y_Servo_Axis(Y_AXIS, SERVO_Y_PIN, SERVO_Y_CHANNEL_NUM);
ServoAxis Y_Servo_Axis(Y_AXIS, SERVO_Y_PIN);
#endif
#ifdef SERVO_Z_PIN
ServoAxis Z_Servo_Axis(Z_AXIS, SERVO_Z_PIN, SERVO_Z_CHANNEL_NUM);
ServoAxis Z_Servo_Axis(Z_AXIS, SERVO_Z_PIN);
#endif
#ifdef SERVO_A_PIN
ServoAxis A_Servo_Axis(A_AXIS, SERVO_A_PIN, SERVO_A_CHANNEL_NUM);
ServoAxis A_Servo_Axis(A_AXIS, SERVO_A_PIN);
#endif
#ifdef SERVO_B_PIN
ServoAxis B_Servo_Axis(B_AXIS, SERVO_B_PIN, SERVO_B_CHANNEL_NUM);
ServoAxis B_Servo_Axis(B_AXIS, SERVO_B_PIN);
#endif
#ifdef SERVO_C_PIN
ServoAxis C_Servo_Axis(C_AXIS, SERVO_C_PIN, SERVO_C_CHANNEL_NUM);
ServoAxis C_Servo_Axis(C_AXIS, SERVO_C_PIN);
#endif
void init_servos() {
// ======================== X Axis ===========================
#ifdef SERVO_X_PIN
#ifdef SERVO_X_PIN
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "X Servo range %4.3f to %4.3f", SERVO_X_RANGE_MIN, SERVO_X_RANGE_MAX);
X_Servo_Axis.init();
X_Servo_Axis.set_range(SERVO_X_RANGE_MIN, SERVO_X_RANGE_MAX);
#ifdef SERVO_X_HOMING_TYPE
#ifdef SERVO_X_HOMING_TYPE
X_Servo_Axis.set_homing_type(SERVO_X_HOMING_TYPE);
#endif
#ifdef SERVO_X_HOME_POS
#endif
#ifdef SERVO_X_HOME_POS
X_Servo_Axis.set_homing_position(SERVO_X_HOME_POS);
#endif
#ifdef SERVO_X_MPOS // value should be true or false
#endif
#ifdef SERVO_X_MPOS // value should be true or false
X_Servo_Axis.set_use_mpos(SERVO_X_MPOS);
#endif
#endif
#endif
#endif
// ======================== Y Axis ===========================
#ifdef SERVO_Y_PIN
#ifdef SERVO_Y_PIN
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Y Servo range %4.3f to %4.3f", SERVO_Y_RANGE_MIN, SERVO_Y_RANGE_MAX);
Y_Servo_Axis.init();
Y_Servo_Axis.set_range(SERVO_Y_RANGE_MIN, SERVO_Y_RANGE_MAX);
#ifdef SERVO_Y_HOMING_TYPE
#ifdef SERVO_Y_HOMING_TYPE
Y_Servo_Axis.set_homing_type(SERVO_Y_HOMING_TYPE);
#endif
#ifdef SERVO_Y_HOME_POS
#endif
#ifdef SERVO_Y_HOME_POS
Y_Servo_Axis.set_homing_position(SERVO_Y_HOME_POS);
#endif
#ifdef SERVO_Y_MPOS // value should be true or false
#endif
#ifdef SERVO_Y_MPOS // value should be true or false
Y_Servo_Axis.set_use_mpos(SERVO_Y_MPOS);
#endif
#endif
#endif
#endif
// ======================== Z Axis ===========================
#ifdef SERVO_Z_PIN
#ifdef SERVO_Z_PIN
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "Z Servo range %4.3f to %4.3f", SERVO_Z_RANGE_MIN, SERVO_Z_RANGE_MAX);
Z_Servo_Axis.init();
Z_Servo_Axis.set_range(SERVO_Z_RANGE_MIN, SERVO_Z_RANGE_MAX);
#ifdef SERVO_Z_HOMING_TYPE
#ifdef SERVO_Z_HOMING_TYPE
Z_Servo_Axis.set_homing_type(SERVO_Z_HOMING_TYPE);
#endif
#ifdef SERVO_Z_HOME_POS
#endif
#ifdef SERVO_Z_HOME_POS
Z_Servo_Axis.set_homing_position(SERVO_Z_HOME_POS);
#endif
#ifdef SERVO_Z_MPOS // value should be true or false
#endif
#ifdef SERVO_Z_MPOS // value should be true or false
Z_Servo_Axis.set_use_mpos(SERVO_Z_MPOS);
#endif
#endif
#endif
#endif
// ======================== A Axis ===========================
#ifdef SERVO_A_PIN
#ifdef SERVO_A_PIN
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "A Servo range %4.3f to %4.3f", SERVO_A_RANGE_MIN, SERVO_A_RANGE_MAX);
A_Servo_Axis.init();
A_Servo_Axis.set_range(SERVO_A_RANGE_MIN, SERVO_A_RANGE_MAX);
#ifdef SERVO_A_HOMING_TYPE
#ifdef SERVO_A_HOMING_TYPE
A_Servo_Axis.set_homing_type(SERVO_A_HOMING_TYPE);
#endif
#ifdef SERVO_A_HOME_POS
#endif
#ifdef SERVO_A_HOME_POS
A_Servo_Axis.set_homing_position(SERVO_A_HOME_POS);
#endif
#ifdef SERVO_A_MPOS // value should be true or false
#endif
#ifdef SERVO_A_MPOS // value should be true or false
A_Servo_Axis.set_use_mpos(SERVO_A_MPOS);
#endif
#endif
#endif
#endif
// ======================== B Axis ===========================
#ifdef SERVO_B_PIN
#ifdef SERVO_B_PIN
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "B Servo range %4.3f to %4.3f", SERVO_B_RANGE_MIN, SERVO_B_RANGE_MAX);
B_Servo_Axis.init();
B_Servo_Axis.set_range(SERVO_B_RANGE_MIN, SERVO_B_RANGE_MAX);
#ifdef SERVO_B_HOMING_TYPE
#ifdef SERVO_B_HOMING_TYPE
B_Servo_Axis.set_homing_type(SERVO_B_HOMING_TYPE);
#endif
#ifdef SERVO_B_HOME_POS
#endif
#ifdef SERVO_B_HOME_POS
B_Servo_Axis.set_homing_position(SERVO_B_HOME_POS);
#endif
#ifdef SERVO_B_MPOS // value should be true or false
#endif
#ifdef SERVO_B_MPOS // value should be true or false
B_Servo_Axis.set_use_mpos(SERVO_B_MPOS);
#endif
#endif
#endif
#endif
// ======================== C Axis ===========================
#ifdef SERVO_C_PIN
#ifdef SERVO_C_PIN
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_INFO, "C Servo range %4.3f to %4.3f", SERVO_C_RANGE_MIN, SERVO_C_RANGE_MAX);
C_Servo_Axis.init();
C_Servo_Axis.set_range(SERVO_C_RANGE_MIN, SERVO_C_RANGE_MAX);
#ifdef SERVO_C_HOMING_TYPE
#ifdef SERVO_C_HOMING_TYPE
C_Servo_Axis.set_homing_type(SERVO_C_HOMING_TYPE);
#endif
#ifdef SERVO_C_HOME_POS
#endif
#ifdef SERVO_C_HOME_POS
C_Servo_Axis.set_homing_position(SERVO_C_HOME_POS);
#endif
#ifdef SERVO_C_MPOS // value should be true or false
#endif
#ifdef SERVO_C_MPOS // value should be true or false
C_Servo_Axis.set_use_mpos(SERVO_C_MPOS);
#endif
#endif
#endif
#endif
// setup a task that will calculate the determine and set the servo positions
xTaskCreatePinnedToCore(servosSyncTask, // task
"servosSyncTask", // name for task
@@ -163,34 +157,34 @@ void servosSyncTask(void* pvParameters) {
const TickType_t xServoFrequency = SERVO_TIMER_INT_FREQ; // in ticks (typically ms)
xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time.
while (true) { // don't ever return from this or the task dies
#ifdef SERVO_X_PIN
#ifdef SERVO_X_PIN
X_Servo_Axis.set_location();
#endif
#ifdef SERVO_Y_PIN
#endif
#ifdef SERVO_Y_PIN
Y_Servo_Axis.set_location();
#endif
#ifdef SERVO_Z_PIN
#endif
#ifdef SERVO_Z_PIN
Z_Servo_Axis.set_location();
#endif
#ifdef SERVO_A_PIN
#endif
#ifdef SERVO_A_PIN
A_Servo_Axis.set_location();
#endif
#ifdef SERVO_B_PIN
#endif
#ifdef SERVO_B_PIN
B_Servo_Axis.set_location();
#endif
#ifdef SERVO_C_PIN
#endif
#ifdef SERVO_C_PIN
C_Servo_Axis.set_location();
#endif
#endif
vTaskDelayUntil(&xLastWakeTime, xServoFrequency);
}
}
// =============================== Class Stuff ================================= //
ServoAxis::ServoAxis(uint8_t axis, uint8_t pin_num, uint8_t channel_num) { // constructor
ServoAxis::ServoAxis(uint8_t axis, uint8_t pin_num) { // constructor
_axis = axis;
_pin_num = pin_num;
_channel_num = channel_num;
_channel_num = sys_get_next_PWM_chan_num();
_showError = true; // this will be used to show calibration error only once
_use_mpos = true; // default is to use the machine position rather than work position
}

View File

@@ -36,7 +36,6 @@
2. In the machine definition file in Machines/, define servo pins and PWM channels like this ....
#define SERVO_Y_PIN GPIO_NUM_14
#define SERVO_Y_CHANNEL_NUM 6
undefine any step and direction pins associated with that axis
@@ -93,7 +92,7 @@ void servosSyncTask(void* pvParameters);
class ServoAxis {
public:
ServoAxis(uint8_t axis, uint8_t pin_num, uint8_t channel_num); // constructor
ServoAxis(uint8_t axis, uint8_t pin_num); // constructor
void init();
void set_location();
void disable(); // sets PWM to 0% duty cycle. Most servos can be manually moved in this state

View File

@@ -23,6 +23,8 @@
#ifdef USE_PEN_SOLENOID
int8_t solenoid_pwm_chan_num;
static TaskHandle_t solenoidSyncTaskHandle = 0;
// used to delay turn on
@@ -35,8 +37,9 @@ void solenoid_init() {
solenoid_pen_enable = false; // start delay has not completed yet.
solenoide_hold_count = 0; // initialize
// setup PWM channel
ledcSetup(SOLENOID_CHANNEL_NUM, SOLENOID_PWM_FREQ, SOLENOID_PWM_RES_BITS);
ledcAttachPin(SOLENOID_PEN_PIN, SOLENOID_CHANNEL_NUM);
solenoid_pwm_chan_num = sys_get_next_PWM_chan_num();
ledcSetup(solenoid_pwm_chan_num, SOLENOID_PWM_FREQ, SOLENOID_PWM_RES_BITS);
ledcAttachPin(SOLENOID_PEN_PIN, solenoid_pwm_chan_num);
solenoid_disable(); // start it it off
// setup a task that will calculate the determine and set the servo position
xTaskCreatePinnedToCore(solenoidSyncTask, // task
@@ -51,7 +54,7 @@ void solenoid_init() {
// turn off the PWM (0 duty)
void solenoid_disable() {
ledcWrite(SOLENOID_CHANNEL_NUM, 0);
ledcWrite(solenoid_pwm_chan_num, 0);
}
// this is the task
@@ -91,13 +94,13 @@ void calc_solenoid(float penZ) {
solenoid_pen_pulse_len = SOLENOID_PULSE_LEN_HOLD;
}
// skip setting value if it is unchanged
if (ledcRead(SOLENOID_CHANNEL_NUM) == solenoid_pen_pulse_len)
if (ledcRead(solenoid_pwm_chan_num) == solenoid_pen_pulse_len)
return;
// update the PWM value
// ledcWrite appears to have issues with interrupts, so make this a critical section
portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&myMutex);
ledcWrite(SOLENOID_CHANNEL_NUM, solenoid_pen_pulse_len);
ledcWrite(solenoid_pwm_chan_num, solenoid_pen_pulse_len);
portEXIT_CRITICAL(&myMutex);
}

View File

@@ -20,6 +20,8 @@
#include "grbl.h"
int8_t spindle_pwm_chan_num;
#ifdef SPINDLE_PWM_PIN
static float pwm_gradient; // Precalulated value to speed up rpm to PWM conversions.
uint32_t spindle_pwm_period; // how many counts in 1 period
@@ -54,8 +56,9 @@ void spindle_init() {
pinMode(SPINDLE_DIR_PIN, OUTPUT);
#endif
// use the LED control feature to setup PWM https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html
ledcSetup(SPINDLE_PWM_CHANNEL, (double)settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel
ledcAttachPin(SPINDLE_PWM_PIN, SPINDLE_PWM_CHANNEL); // attach the PWM to the pin
spindle_pwm_chan_num - sys_get_next_PWM_chan_num();
ledcSetup(spindle_pwm_chan_num, (double)settings.spindle_pwm_freq, SPINDLE_PWM_BIT_PRECISION); // setup the channel
ledcAttachPin(SPINDLE_PWM_PIN, spindle_pwm_chan_num); // attach the PWM to the pin
// Start with spindle off off
spindle_stop();
#endif
@@ -65,9 +68,9 @@ void spindle_stop() {
spindle_set_enable(false);
#ifdef SPINDLE_PWM_PIN
#ifndef INVERT_SPINDLE_PWM
grbl_analogWrite(SPINDLE_PWM_CHANNEL, spindle_pwm_off_value);
grbl_analogWrite(spindle_pwm_chan_num, spindle_pwm_off_value);
#else
grbl_analogWrite(SPINDLE_PWM_CHANNEL, (1 << SPINDLE_PWM_BIT_PRECISION)); // TO DO...wrong for min_pwm
grbl_analogWrite(spindle_pwm_chan_num, (1 << SPINDLE_PWM_BIT_PRECISION)); // TO DO...wrong for min_pwm
#endif
#endif
}
@@ -77,7 +80,7 @@ uint8_t spindle_get_state() { // returns SPINDLE_STATE_DISABLE, SPINDLE_STATE_CW
#ifndef SPINDLE_PWM_PIN
return (SPINDLE_STATE_DISABLE);
#else
if (ledcRead(SPINDLE_PWM_CHANNEL) == 0) // Check the PWM value
if (ledcRead(spindle_pwm_chan_num) == 0) // Check the PWM value
return (SPINDLE_STATE_DISABLE);
else {
#ifdef SPINDLE_DIR_PIN
@@ -103,9 +106,9 @@ void spindle_set_speed(uint32_t pwm_value) {
spindle_set_enable(pwm_value != 0);
#endif
#ifndef INVERT_SPINDLE_PWM
grbl_analogWrite(SPINDLE_PWM_CHANNEL, pwm_value);
grbl_analogWrite(spindle_pwm_chan_num, pwm_value);
#else
grbl_analogWrite(SPINDLE_PWM_CHANNEL, (1 << SPINDLE_PWM_BIT_PRECISION) - pwm_value);
grbl_analogWrite(spindle_pwm_chan_num, (1 << SPINDLE_PWM_BIT_PRECISION) - pwm_value);
#endif
#endif
}

View File

@@ -588,3 +588,13 @@ int8_t sys_get_next_RMT_chan_num() {
return -1;
}
}
int8_t sys_get_next_PWM_chan_num() {
static uint8_t next_PWM_chan_num = 0; // channels 0-7 are valid
if (next_PWM_chan_num < 8) // 7 is the max PWM channel number
return next_PWM_chan_num++;
else {
grbl_msg_sendf(CLIENT_SERIAL, MSG_LEVEL_ERROR, "Error: out of PWM channels");
return -1;
}
}

View File

@@ -229,5 +229,6 @@ void sys_io_control(uint8_t io_num_mask, bool turnOn);
//
int8_t sys_get_next_RMT_chan_num();
int8_t sys_get_next_PWM_chan_num();
#endif