Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -4436,6 +4436,20 @@
#define FREEZE_STATE LOW // State of pin indicating freeze
#endif

/**
* Adds realtime speed control using an external potentiometer and a free thermistor port
*/
//#define SPEED_DIAL_FEATURE
#if ENABLED(SPEED_DIAL_FEATURE)
#define SPEED_DIAL_PIN TEMP_BED_PIN
#define SPEED_DIAL_MIN_SPEED 10
#define SPEED_DIAL_MAX_SPEED 100
#define SPEED_DIAL_BOARD_RESISTOR 4700
#define SPEED_DIAL_POT_RESISTOR 50000
#define SPEED_DIAL_INVERT true
#define SPEED_DIAL_DIAL_SENSITIVITY -2
#endif

/**
* MAX7219 Debug Matrix
*
Expand Down
100 changes: 100 additions & 0 deletions Marlin/src/feature/speed_dial.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

/**
* speed_dial.cpp - speed dial feature
*/

#include "../MarlinCore.h"
#include "../HAL/shared/Delay.h"
#include "../lcd/marlinui.h"
#include "../gcode/gcode.h"
#include "../module/stepper.h"
#include "speed_dial.h"

#if ENABLED(SPEED_DIAL_FEATURE)

raw_adc_t SpeedDial::current_speed_dial_raw = HAL_ADC_RANGE;
uint8_t SpeedDial::current_speed_dial = 100;
uint8_t SpeedDial::next_value_change = SPEED_DIAL_DIAL_SENSITIVITY;

SpeedDial speedDial;

void SpeedDial::set(raw_adc_t value) {
current_speed_dial_raw = value;

#define SPEED_DIAL_MULTIPLIER (SQRT(0x7FFFFFFF / SPEED_DIAL_BOARD_RESISTOR) / 100)
#define SPEED_DIAL_MULTIPLIER_FINAL (SPEED_DIAL_MULTIPLIER * 100)
#define SPEED_DIAL_SMOOTH_VALUE_TOTAL (SPEED_DIAL_SMOOTH_VALUE + 1)

//get adc percentage
int32_t speed_dial_adc_percent = current_speed_dial_raw * SPEED_DIAL_MULTIPLIER_FINAL / HAL_ADC_RANGE;
if(speed_dial_adc_percent > SPEED_DIAL_MULTIPLIER_FINAL) speed_dial_adc_percent = SPEED_DIAL_MULTIPLIER_FINAL;
if(speed_dial_adc_percent < 0) speed_dial_adc_percent = 0;

#if SPEED_DIAL_INVERT
speed_dial_adc_percent = SPEED_DIAL_MULTIPLIER_FINAL - speed_dial_adc_percent;
#endif

//dial position percentage
int32_t speed_dial_percent = (speed_dial_adc_percent > 0 ?
((SPEED_DIAL_BOARD_RESISTOR * SPEED_DIAL_MULTIPLIER_FINAL / speed_dial_adc_percent) - SPEED_DIAL_BOARD_RESISTOR) * SPEED_DIAL_MULTIPLIER_FINAL / SPEED_DIAL_POT_RESISTOR :
SPEED_DIAL_MULTIPLIER_FINAL);
if(speed_dial_percent > SPEED_DIAL_MULTIPLIER_FINAL) speed_dial_percent = SPEED_DIAL_MULTIPLIER_FINAL;
if(speed_dial_percent < 0) speed_dial_percent = 0;

#if SPEED_DIAL_INVERT
speed_dial_percent = SPEED_DIAL_MULTIPLIER_FINAL - speed_dial_percent;
#endif

//get actual speed value
int32_t speed_dial_value = (speed_dial_percent + (SPEED_DIAL_MULTIPLIER / 2)) * (SPEED_DIAL_MAX_SPEED - SPEED_DIAL_MIN_SPEED) / SPEED_DIAL_MULTIPLIER_FINAL + SPEED_DIAL_MIN_SPEED;

//clamp speed value
if(speed_dial_value > SPEED_DIAL_MAX_SPEED) speed_dial_value = SPEED_DIAL_MAX_SPEED;
if(speed_dial_value < SPEED_DIAL_MIN_SPEED) speed_dial_value = SPEED_DIAL_MIN_SPEED;

//store derived value
current_speed_dial = speed_dial_value;

//update stepper speed as per dial sensitivity
if(SPEED_DIAL_DIAL_SENSITIVITY > 0) {
for(uint8_t i=0; i < SPEED_DIAL_DIAL_SENSITIVITY; i++) {
updateStepper();
}
} else {
if(next_value_change) {
next_value_change--;
} else {
updateStepper();

next_value_change = SPEED_DIAL_DIAL_SENSITIVITY;
}
}
}

void SpeedDial::updateStepper() {
if(current_speed_dial > stepper.current_speed_dial()) stepper.set_speed_dial(stepper.current_speed_dial() + 1);
if(current_speed_dial < stepper.current_speed_dial()) stepper.set_speed_dial(stepper.current_speed_dial() - 1);
}

#endif
48 changes: 48 additions & 0 deletions Marlin/src/feature/speed_dial.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once

/**
* speed_dial.h - speed dial feature
*/

#include "../inc/MarlinConfig.h"

#if ENABLED(SPEED_DIAL_FEATURE)

class SpeedDial {
public:
static inline uint8_t current() { return current_speed_dial; }
static inline raw_adc_t raw() { return current_speed_dial_raw; }
static void set(raw_adc_t value);

private:
static void updateStepper();

static raw_adc_t current_speed_dial_raw;
static uint8_t current_speed_dial;
static uint8_t next_value_change;
};

extern SpeedDial speedDial;

#endif
9 changes: 9 additions & 0 deletions Marlin/src/gcode/temp/M105.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#include "../gcode.h"
#include "../../module/temperature.h"

#if ENABLED(SPEED_DIAL_FEATURE)
#include "../../feature/speed_dial.h"
#endif

/**
* M105: Read hot end and bed temperature
*/
Expand All @@ -41,7 +45,12 @@ void GcodeSuite::M105() {

#else

#if ENABLED(SPEED_DIAL_FEATURE)
SERIAL_ECHOPGM(" T:", speedDial.current());
SERIAL_ECHOLNPGM(" S@:", speedDial.raw());
#else
SERIAL_ECHOLNPGM(" T:0"); // Some hosts send M105 to test the serial connection
#endif

#endif
}
60 changes: 56 additions & 4 deletions Marlin/src/module/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ uint32_t Stepper::acceleration_time, Stepper::deceleration_time;
bool Stepper::frozen; // = false
#endif

#if ENABLED(SPEED_DIAL_FEATURE)
uint8_t Stepper::speed_dial_value = 100;
#endif

// Delta error variables for the Bresenham line tracer
xyze_long_t Stepper::delta_error{0};
xyze_long_t Stepper::advance_dividend{0};
Expand Down Expand Up @@ -240,8 +244,11 @@ uint32_t Stepper::advance_divisor = 0,
* Standard Motion Linear Advance state
*/
#if ENABLED(LIN_ADVANCE)
hal_timer_t Stepper::nextAdvanceISR = LA_ADV_NEVER,
Stepper::la_interval = LA_ADV_NEVER;
hal_timer_t Stepper::nextAdvanceISR = LA_ADV_NEVER,
Stepper::la_interval = LA_ADV_NEVER;
#if ENABLED(SPEED_DIAL_FEATURE)
Stepper::la_interval_nom = LA_ADV_NEVER;
#endif
#if ENABLED(SMOOTH_LIN_ADVANCE)
uint32_t Stepper::curr_step_rate,
Stepper::curr_timer_tick = 0;
Expand Down Expand Up @@ -2465,13 +2472,20 @@ void Stepper::isr() {
acceleration_time += interval;
deceleration_time = 0; // Reset since we're doing acceleration first.

#if ENABLED(SPEED_DIAL_FEATURE)
speed_dial_adjust_interval(interval);
#endif

// Apply Nonlinear Extrusion, if enabled
calc_nonlinear_e(acc_step_rate << oversampling_factor);

#if HAS_ROUGH_LIN_ADVANCE
if (la_active) {
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
la_interval = calc_timer_interval((acc_step_rate + la_step_rate) >> current_block->la_scaling);
#if ENABLED(SPEED_DIAL_FEATURE)
speed_dial_adjust_interval(la_interval);
#endif
}
#endif

Expand Down Expand Up @@ -2530,6 +2544,10 @@ void Stepper::isr() {
interval = calc_multistep_timer_interval(step_rate << oversampling_factor);
deceleration_time += interval;

#if ENABLED(SPEED_DIAL_FEATURE)
speed_dial_adjust_interval(interval);
#endif

// Apply Nonlinear Extrusion, if enabled
calc_nonlinear_e(step_rate << oversampling_factor);

Expand All @@ -2539,6 +2557,9 @@ void Stepper::isr() {
if (la_step_rate != step_rate) {
const bool forward_e = la_step_rate < step_rate;
la_interval = calc_timer_interval((forward_e ? step_rate - la_step_rate : la_step_rate - step_rate) >> current_block->la_scaling);
#if ENABLED(SPEED_DIAL_FEATURE)
speed_dial_adjust_interval(la_interval);
#endif

if (forward_e != motor_direction(E_AXIS)) {
last_direction_bits.toggle(E_AXIS);
Expand Down Expand Up @@ -2589,8 +2610,13 @@ void Stepper::isr() {
calc_nonlinear_e(current_block->nominal_rate << oversampling_factor);

#if HAS_ROUGH_LIN_ADVANCE
if (la_active)
la_interval = calc_timer_interval(current_block->nominal_rate >> current_block->la_scaling);
if (la_active) {
#if ENABLED(SPEED_DIAL_FEATURE)
la_interval_nom = calc_timer_interval(current_block->nominal_rate >> current_block->la_scaling);
#else
la_interval = calc_timer_interval(current_block->nominal_rate >> current_block->la_scaling);
#endif
}
#endif

// Adjust Laser Power - Cruise
Expand All @@ -2610,6 +2636,15 @@ void Stepper::isr() {

// The timer interval is just the nominal value for the nominal speed
interval = ticks_nominal;

#if ENABLED(SPEED_DIAL_FEATURE)
speed_dial_adjust_interval(interval);

#if HAS_ROUGH_LIN_ADVANCE
la_interval = la_interval_nom;
speed_dial_adjust_interval(la_interval);
#endif
#endif
}
}

Expand Down Expand Up @@ -2921,6 +2956,10 @@ void Stepper::isr() {
// Initialize ac/deceleration time as if half the time passed.
acceleration_time = deceleration_time = interval / 2;

#if ENABLED(SPEED_DIAL_FEATURE)
speed_dial_adjust_interval(interval);
#endif

// Apply Nonlinear Extrusion, if enabled
calc_nonlinear_e(current_block->initial_rate << oversampling_factor);

Expand All @@ -2931,6 +2970,9 @@ void Stepper::isr() {
if (la_active) {
const uint32_t la_step_rate = la_advance_steps < current_block->max_adv_steps ? current_block->la_advance_rate : 0;
la_interval = calc_timer_interval((current_block->initial_rate + la_step_rate) >> current_block->la_scaling);
#if ENABLED(SPEED_DIAL_FEATURE)
speed_dial_adjust_interval(la_interval);
#endif
}
#endif
#endif
Expand Down Expand Up @@ -3864,3 +3906,13 @@ void Stepper::report_positions() {
}

#endif // BABYSTEPPING

#if ENABLED(SPEED_DIAL_FEATURE)

void Stepper::speed_dial_adjust_interval(uint32_t& interval) {
interval *= 100;
interval /= speed_dial_value;
if (interval == 0) interval = 1;
}

#endif // SPEED_DIAL_FEATURE
13 changes: 13 additions & 0 deletions Marlin/src/module/stepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,11 @@ class Stepper {
static bool frozen; // Set this flag to instantly freeze motion
#endif

#if ENABLED(SPEED_DIAL_FEATURE)
static inline void set_speed_dial(uint8_t speed) { speed_dial_value = speed > 0 ? speed : 1; }
static inline uint8_t current_speed_dial() { return speed_dial_value; }
#endif

#if ENABLED(NONLINEAR_EXTRUSION)
static nonlinear_t ne;
#endif
Expand Down Expand Up @@ -487,6 +492,9 @@ class Stepper {
static constexpr hal_timer_t LA_ADV_NEVER = HAL_TIMER_TYPE_MAX;
static hal_timer_t nextAdvanceISR,
la_interval; // Interval between ISR calls for LA
#if ENABLED(SPEED_DIAL_FEATURE)
static hal_timer_t la_interval_nom;
#endif
#if ENABLED(SMOOTH_LIN_ADVANCE)
static uint32_t curr_timer_tick, // Current tick relative to block start
curr_step_rate; // Current motion step rate
Expand Down Expand Up @@ -800,6 +808,11 @@ class Stepper {
static void ftMotion_stepper();
#endif

#if ENABLED(SPEED_DIAL_FEATURE)
static void speed_dial_adjust_interval(uint32_t& step_rate);
static uint8_t speed_dial_value;
#endif

};

extern Stepper stepper;
Loading