diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index f1f6594228..4f26a77cf6 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -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
*
diff --git a/Marlin/src/feature/speed_dial.cpp b/Marlin/src/feature/speed_dial.cpp
new file mode 100644
index 0000000000..7a2ca7a577
--- /dev/null
+++ b/Marlin/src/feature/speed_dial.cpp
@@ -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 .
+ *
+ */
+
+/**
+ * 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
diff --git a/Marlin/src/feature/speed_dial.h b/Marlin/src/feature/speed_dial.h
new file mode 100644
index 0000000000..c55f456e6f
--- /dev/null
+++ b/Marlin/src/feature/speed_dial.h
@@ -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 .
+ *
+ */
+#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
diff --git a/Marlin/src/gcode/temp/M105.cpp b/Marlin/src/gcode/temp/M105.cpp
index 4de5ba8eef..863ade57b6 100644
--- a/Marlin/src/gcode/temp/M105.cpp
+++ b/Marlin/src/gcode/temp/M105.cpp
@@ -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
*/
@@ -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
}
diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp
index 2a10c83800..e86816e20a 100644
--- a/Marlin/src/module/stepper.cpp
+++ b/Marlin/src/module/stepper.cpp
@@ -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};
@@ -2465,6 +2469,10 @@ 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);
diff --git a/ini/features.ini b/ini/features.ini
index 03a9bdbba8..89320e70ca 100644
--- a/ini/features.ini
+++ b/ini/features.ini
@@ -383,6 +383,7 @@ IS_SCARA = build_src_filter=+ +
MORGAN_SCARA = build_src_filter=+
HAS_MICROSTEPS = build_src_filter=+
+SPEED_DIAL_FEATURE = build_src_filter=+
(ESP3D_)?WIFISUPPORT = esp32async/AsyncTCP@3.3.3, mathieucarbou/ESP Async WebServer@3.0.6
ESP3DLib=https://github.com/luc-github/ESP3DLib/archive/6d62f76c3f.zip
arduinoWebSockets=links2004/WebSockets@2.3.4