From f2a1e107b9585d6a927471889f361965acdca748 Mon Sep 17 00:00:00 2001 From: JohnR Date: Fri, 25 Feb 2022 17:49:08 +0000 Subject: [PATCH 01/18] Add hardware PWM for fan & laser/spindle PWM --- Marlin/src/HAL/ESP32/HAL.cpp | 116 +++++++++++++++++++------ Marlin/src/HAL/ESP32/HAL.h | 26 ++++-- Marlin/src/HAL/ESP32/Servo.cpp | 15 ++-- Marlin/src/HAL/ESP32/Servo.h | 3 +- Marlin/src/HAL/ESP32/inc/SanityCheck.h | 8 +- 5 files changed, 121 insertions(+), 47 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index adf5cecabe41..155056b4129a 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -76,6 +76,9 @@ uint32_t thresholds[ADC_ATTEN_MAX]; volatile int numPWMUsed = 0, pwmPins[MAX_PWM_PINS], pwmValues[MAX_PWM_PINS]; +pin_t chan_pin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32 +uint32_t chan_freq[(CHANNEL_MAX_NUM + 1) / 2]; // ledcReadFreq doesn't work if a duty hasn't been set yet! +uint16_t chan_res[(CHANNEL_MAX_NUM + 1) / 2]; // ------------------------ // Public functions @@ -248,42 +251,99 @@ void MarlinHAL::adc_start(const pin_t pin) { adc1_set_attenuation(chan, atten); } -void analogWrite(pin_t pin, int value) { +// ------------------------ +// PWM +// ------------------------ + +int8_t pin_to_chan(uint8_t pin) { + for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { + if (chan_pin[i] == pin) return i; + } + return -1; +} + +// get PWM channel for pin - if none then attach a new one +// return -1 if fail or invalid pin#, channel # (0-15) if success +int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) { + if (pin == 0 || (pin > MAX_PWM_IOPIN)) return -1; // not a hardware PWM pin! + int8_t chan = pin_to_chan(pin); + if (chan >= 0) return chan; + + // find an empty adjacent chanel (same timer & freq/res) + for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { + if (chan_pin[i] == 0) { + if (chan_pin[i ^ 0x1] != 0) { + if ((chan_freq[i / 2] == freq) && (chan_res[i / 2] == res)) { + chan_pin[i] = pin; // allocate pwm to this channel + ledcAttachPin(pin, i); + return i; + } + } + else if (chan == -1) { // pair of empty channels? + chan = i & 0xfe; // save lower channel number + } + } + } + // not attached, is an empty timer slot avail? + if (chan >= 0) { + chan_freq[chan / 2] = freq; + chan_pin[chan] = pin; + chan_res[chan / 2] = res; + ledcSetup(chan, freq, res); + ledcAttachPin(pin, chan); + } + return chan; // -1 if no channel avail +} + +void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) { + int8_t channel = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); + if (channel >= 0) { + uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1); + ledcWrite(channel, duty); + } +} + +uint8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { + int8_t channel = pin_to_chan(pin); + if (channel >= 0) { + if (f_desired == ledcReadFreq(channel)) return channel; // no freq change + ledcDetachPin(chan_pin[channel]); + chan_pin[channel] = 0; // remove old freq channel + } + return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one +} + +// use hardware PWM if avail, if not then ISR +void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution! // Use ledc hardware for internal pins - if (pin < 34) { - static int cnt_channel = 1, pin_to_channel[40] = { 0 }; - if (pin_to_channel[pin] == 0) { - ledcAttachPin(pin, cnt_channel); - ledcSetup(cnt_channel, 490, 8); - ledcWrite(cnt_channel, value); - pin_to_channel[pin] = cnt_channel++; - } - ledcWrite(pin_to_channel[pin], value); - return; + int8_t channel = get_pwm_channel(pin, freq, res); + if (channel >= 0) { + ledcWrite(channel, value); // set duty value } + else { // not a hardware PWM pin OR no PWM channels available + int idx = -1; - int idx = -1; + // Search Pin + for (int i = 0; i < numPWMUsed; ++i) + if (pwmPins[i] == pin) { idx = i; break; } - // Search Pin - for (int i = 0; i < numPWMUsed; ++i) - if (pwmPins[i] == pin) { idx = i; break; } + // not found ? + if (idx < 0) { + // No slots remaining + if (numPWMUsed >= MAX_PWM_PINS) return; - // not found ? - if (idx < 0) { - // No slots remaining - if (numPWMUsed >= MAX_PWM_PINS) return; + // Take new slot for pin + idx = numPWMUsed; + pwmPins[idx] = pin; + // Start timer on first use + if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); - // Take new slot for pin - idx = numPWMUsed; - pwmPins[idx] = pin; - // Start timer on first use - if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); + ++numPWMUsed; + } - ++numPWMUsed; + // Use 7bit internal value - add 1 to have 100% high at 255 + pwmValues[idx] = (value + 1) / 2; } - - // Use 7bit internal value - add 1 to have 100% high at 255 - pwmValues[idx] = (value + 1) / 2; } // Handle PWM timer interrupt diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index df52e2186cbd..9d9fe8526ff8 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -64,6 +64,12 @@ #define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock) #define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock) +#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment +#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency() +#define PWM_RESOLUTION 10u // Default PWM bit resolution +#define CHANNEL_MAX_NUM 15u // max PWM channel to allocate (7 to only use low speed, 15 to use high speed - see above) +#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34 + // ------------------------ // Types // ------------------------ @@ -83,7 +89,7 @@ typedef Servo hal_servo_t; void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0); void noTone(const pin_t _pin); -void analogWrite(pin_t pin, int value); +void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq=PWM_FREQUENCY, const uint16_t res=8); // // Pin Mapping for M42, M43, M226 @@ -208,13 +214,19 @@ class MarlinHAL { // The current value of the ADC register static uint16_t adc_value() { return adc_result; } + /** + * If not already allocated, allocate a hardware PWM channel + * to the pin and set the duty cycle.. + * Optionally invert the duty cycle [default = false] + * Optionally change the scale of the provided value to enable finer PWM duty control [default = 255] + */ + static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false); + /** - * Set the PWM duty cycle for the pin to the given value. - * No inverting the duty cycle in this HAL. - * No changing the maximum size of the provided value to enable finer PWM duty control in this HAL. + * Allocate and set the frequency of a hardware PWM pin + * Returns -1 if no pin available. */ - static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) { - analogWrite(pin, v); - } + static uint8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired); + }; diff --git a/Marlin/src/HAL/ESP32/Servo.cpp b/Marlin/src/HAL/ESP32/Servo.cpp index fcf58485819e..79c0ce692ec5 100644 --- a/Marlin/src/HAL/ESP32/Servo.cpp +++ b/Marlin/src/HAL/ESP32/Servo.cpp @@ -32,19 +32,18 @@ int Servo::channel_next_free = 12; Servo::Servo() { - channel = channel_next_free++; } int8_t Servo::attach(const int inPin) { - if (channel >= CHANNEL_MAX_NUM) return -1; if (inPin > 0) pin = inPin; - - ledcSetup(channel, 50, 16); // channel X, 50 Hz, 16-bit depth - ledcAttachPin(pin, channel); - return true; + channel = get_pwm_channel(pin, 50u, 16u); + return channel; // -1 if no PWM avail. } -void Servo::detach() { ledcDetachPin(pin); } +// leave channel connected to servo - set duty to zero +void Servo::detach() { + if (channel != -1) ledcWrite(channel, 0); +} int Servo::read() { return degrees; } @@ -52,7 +51,7 @@ void Servo::write(int inDegrees) { degrees = constrain(inDegrees, MIN_ANGLE, MAX_ANGLE); int us = map(degrees, MIN_ANGLE, MAX_ANGLE, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); int duty = map(us, 0, TAU_USEC, 0, MAX_COMPARE); - ledcWrite(channel, duty); + if (channel >= 0) ledcWrite(channel, duty); // don't save duty for servos! } void Servo::move(const int value) { diff --git a/Marlin/src/HAL/ESP32/Servo.h b/Marlin/src/HAL/ESP32/Servo.h index 8542092d66ea..1dbb416a8317 100644 --- a/Marlin/src/HAL/ESP32/Servo.h +++ b/Marlin/src/HAL/ESP32/Servo.h @@ -30,8 +30,7 @@ class Servo { MAX_PULSE_WIDTH = 2400, // Longest pulse sent to a servo TAU_MSEC = 20, TAU_USEC = (TAU_MSEC * 1000), - MAX_COMPARE = _BV(16) - 1, // 65535 - CHANNEL_MAX_NUM = 16; + MAX_COMPARE = _BV(16) - 1; // 65535 public: Servo(); diff --git a/Marlin/src/HAL/ESP32/inc/SanityCheck.h b/Marlin/src/HAL/ESP32/inc/SanityCheck.h index 8bbc68d8715b..7af5d4b692dc 100644 --- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h +++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h @@ -25,8 +25,12 @@ #error "EMERGENCY_PARSER is not yet implemented for ESP32. Disable EMERGENCY_PARSER to continue." #endif -#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY - #error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on ESP32." +#if ENABLED(BOARD_MKS_TINYBEE) && ENABLED(FAST_PWM_FAN) + #error "FAST_PWM_FAN not available on TinyBee." +#endif + +#if (ENABLED(SPINDLE_LASER_USE_PWM) && (SPINDLE_LASER_FREQUENCY > 78125)) || (ENABLED(FAST_PWM_FAN_FREQUENCY) && (FAST_PWM_FAN_FREQUENCY > 78125)) + #error "SPINDLE_LASER_FREQUENCY and FAST_PWM_FREQUENCY maximum value is 78125Hz for ESP32." #endif #if HAS_TMC_SW_SERIAL From 91b50879231412bc3ddaf9e3bc7a7abb2548c97d Mon Sep 17 00:00:00 2001 From: JohnR Date: Fri, 25 Feb 2022 18:55:09 +0000 Subject: [PATCH 02/18] Delete duplicate code --- Marlin/src/HAL/ESP32/HAL.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 155056b4129a..29184298ce05 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -340,9 +340,6 @@ void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PW ++numPWMUsed; } - - // Use 7bit internal value - add 1 to have 100% high at 255 - pwmValues[idx] = (value + 1) / 2; } } From 95a4e90d4b1ea6317cb0df1bc633e79d073f646d Mon Sep 17 00:00:00 2001 From: JohnR Date: Fri, 25 Feb 2022 18:58:10 +0000 Subject: [PATCH 03/18] Replaced deleted code --- Marlin/src/HAL/ESP32/HAL.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 29184298ce05..44426e746b1d 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -338,6 +338,8 @@ void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PW // Start timer on first use if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); + // Use 7bit internal value - add 1 to have 100% high at 255 + pwmValues[idx] = (value + 1) / 2; ++numPWMUsed; } } From d3a3a8599a1eb1c2eb46b175ca8f26ca872e09ce Mon Sep 17 00:00:00 2001 From: JohnR Date: Fri, 25 Feb 2022 19:02:09 +0000 Subject: [PATCH 04/18] Revert "Replaced deleted code" This reverts commit 95a4e90d4b1ea6317cb0df1bc633e79d073f646d. --- Marlin/src/HAL/ESP32/HAL.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 44426e746b1d..29184298ce05 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -338,8 +338,6 @@ void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PW // Start timer on first use if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); - // Use 7bit internal value - add 1 to have 100% high at 255 - pwmValues[idx] = (value + 1) / 2; ++numPWMUsed; } } From e34268982b628bda30b5be2964ebc56100b9c269 Mon Sep 17 00:00:00 2001 From: JohnR Date: Fri, 25 Feb 2022 19:02:34 +0000 Subject: [PATCH 05/18] Revert "Delete duplicate code" This reverts commit 91b50879231412bc3ddaf9e3bc7a7abb2548c97d. --- Marlin/src/HAL/ESP32/HAL.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 29184298ce05..155056b4129a 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -340,6 +340,9 @@ void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PW ++numPWMUsed; } + + // Use 7bit internal value - add 1 to have 100% high at 255 + pwmValues[idx] = (value + 1) / 2; } } From 571e41bd1cb6352e322cb2ba58a5d7a3b6c8c2f4 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 26 Feb 2022 14:39:53 -0600 Subject: [PATCH 06/18] misc. cleanup --- Marlin/src/HAL/ESP32/HAL.cpp | 87 +++++++++++++------------- Marlin/src/HAL/ESP32/HAL.h | 11 ++-- Marlin/src/HAL/ESP32/Servo.cpp | 9 ++- Marlin/src/HAL/ESP32/inc/SanityCheck.h | 10 +-- 4 files changed, 57 insertions(+), 60 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 155056b4129a..e2b8f111bfd5 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -256,61 +256,60 @@ void MarlinHAL::adc_start(const pin_t pin) { // ------------------------ int8_t pin_to_chan(uint8_t pin) { - for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { - if (chan_pin[i] == pin) return i; - } - return -1; + for (int i = 0; i <= CHANNEL_MAX_NUM; i++) + if (chan_pin[i] == pin) return i; + return -1; } // get PWM channel for pin - if none then attach a new one // return -1 if fail or invalid pin#, channel # (0-15) if success int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) { - if (pin == 0 || (pin > MAX_PWM_IOPIN)) return -1; // not a hardware PWM pin! - int8_t chan = pin_to_chan(pin); - if (chan >= 0) return chan; - - // find an empty adjacent chanel (same timer & freq/res) - for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { - if (chan_pin[i] == 0) { - if (chan_pin[i ^ 0x1] != 0) { - if ((chan_freq[i / 2] == freq) && (chan_res[i / 2] == res)) { - chan_pin[i] = pin; // allocate pwm to this channel - ledcAttachPin(pin, i); - return i; - } - } - else if (chan == -1) { // pair of empty channels? - chan = i & 0xfe; // save lower channel number - } - } - } - // not attached, is an empty timer slot avail? - if (chan >= 0) { - chan_freq[chan / 2] = freq; - chan_pin[chan] = pin; - chan_res[chan / 2] = res; - ledcSetup(chan, freq, res); - ledcAttachPin(pin, chan); - } - return chan; // -1 if no channel avail + if (pin == 0 || (pin > MAX_PWM_IOPIN)) return -1; // not a hardware PWM pin! + int8_t chan = pin_to_chan(pin); + if (chan >= 0) return chan; + + // find an empty adjacent chanel (same timer & freq/res) + for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { + if (chan_pin[i] == 0) { + if (chan_pin[i ^ 0x1] != 0) { + if ((chan_freq[i / 2] == freq) && (chan_res[i / 2] == res)) { + chan_pin[i] = pin; // allocate pwm to this channel + ledcAttachPin(pin, i); + return i; + } + } + else if (chan == -1) { // pair of empty channels? + chan = i & 0xfe; // save lower channel number + } + } + } + // not attached, is an empty timer slot avail? + if (chan >= 0) { + chan_freq[chan / 2] = freq; + chan_pin[chan] = pin; + chan_res[chan / 2] = res; + ledcSetup(chan, freq, res); + ledcAttachPin(pin, chan); + } + return chan; // -1 if no channel avail } void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) { - int8_t channel = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); - if (channel >= 0) { - uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1); - ledcWrite(channel, duty); - } + int8_t channel = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); + if (channel >= 0) { + uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1); + ledcWrite(channel, duty); + } } uint8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { - int8_t channel = pin_to_chan(pin); - if (channel >= 0) { - if (f_desired == ledcReadFreq(channel)) return channel; // no freq change - ledcDetachPin(chan_pin[channel]); - chan_pin[channel] = 0; // remove old freq channel - } - return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one + int8_t channel = pin_to_chan(pin); + if (channel >= 0) { + if (f_desired == ledcReadFreq(channel)) return channel; // no freq change + ledcDetachPin(chan_pin[channel]); + chan_pin[channel] = 0; // remove old freq channel + } + return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one } // use hardware PWM if avail, if not then ISR diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index 9d9fe8526ff8..f37dd62a8688 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -65,10 +65,10 @@ #define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock) #define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment -#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency() -#define PWM_RESOLUTION 10u // Default PWM bit resolution -#define CHANNEL_MAX_NUM 15u // max PWM channel to allocate (7 to only use low speed, 15 to use high speed - see above) -#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34 +#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency() +#define PWM_RESOLUTION 10u // Default PWM bit resolution +#define CHANNEL_MAX_NUM 15u // max PWM channel to allocate (7 to only use low speed, 15 to use high speed - see above) +#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34 // ------------------------ // Types @@ -214,7 +214,7 @@ class MarlinHAL { // The current value of the ADC register static uint16_t adc_value() { return adc_result; } - /** + /** * If not already allocated, allocate a hardware PWM channel * to the pin and set the duty cycle.. * Optionally invert the duty cycle [default = false] @@ -228,5 +228,4 @@ class MarlinHAL { */ static uint8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired); - }; diff --git a/Marlin/src/HAL/ESP32/Servo.cpp b/Marlin/src/HAL/ESP32/Servo.cpp index 79c0ce692ec5..de72b7110480 100644 --- a/Marlin/src/HAL/ESP32/Servo.cpp +++ b/Marlin/src/HAL/ESP32/Servo.cpp @@ -31,18 +31,17 @@ // so we only allocate servo channels up high to avoid side effects with regards to analogWrite (fans, leds, laser pwm etc.) int Servo::channel_next_free = 12; -Servo::Servo() { -} +Servo::Servo() {} int8_t Servo::attach(const int inPin) { if (inPin > 0) pin = inPin; - channel = get_pwm_channel(pin, 50u, 16u); + channel = get_pwm_channel(pin, 50u, 16u); return channel; // -1 if no PWM avail. } // leave channel connected to servo - set duty to zero -void Servo::detach() { - if (channel != -1) ledcWrite(channel, 0); +void Servo::detach() { + if (channel != -1) ledcWrite(channel, 0); } int Servo::read() { return degrees; } diff --git a/Marlin/src/HAL/ESP32/inc/SanityCheck.h b/Marlin/src/HAL/ESP32/inc/SanityCheck.h index 7af5d4b692dc..052c7e9d12fe 100644 --- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h +++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h @@ -25,11 +25,7 @@ #error "EMERGENCY_PARSER is not yet implemented for ESP32. Disable EMERGENCY_PARSER to continue." #endif -#if ENABLED(BOARD_MKS_TINYBEE) && ENABLED(FAST_PWM_FAN) - #error "FAST_PWM_FAN not available on TinyBee." -#endif - -#if (ENABLED(SPINDLE_LASER_USE_PWM) && (SPINDLE_LASER_FREQUENCY > 78125)) || (ENABLED(FAST_PWM_FAN_FREQUENCY) && (FAST_PWM_FAN_FREQUENCY > 78125)) +#if (ENABLED(SPINDLE_LASER_USE_PWM) && SPINDLE_LASER_FREQUENCY > 78125) || (ENABLED(FAST_PWM_FAN_FREQUENCY) && FAST_PWM_FAN_FREQUENCY > 78125) #error "SPINDLE_LASER_FREQUENCY and FAST_PWM_FREQUENCY maximum value is 78125Hz for ESP32." #endif @@ -44,3 +40,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) #error "POSTMORTEM_DEBUGGING is not yet supported on ESP32." #endif + +#if MB(MKS_TINYBEE) && ENABLED(FAST_PWM_FAN) + #error "FAST_PWM_FAN is not available on TinyBee." +#endif From c2b1e3ae7bc2551ba6bdfd21d40912e94c300db6 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 26 Feb 2022 14:49:43 -0600 Subject: [PATCH 07/18] use structs, replace WRITE --- Marlin/src/HAL/ESP32/HAL.cpp | 88 +++++++++++++++++----------------- Marlin/src/HAL/ESP32/HAL.h | 2 +- Marlin/src/HAL/ESP32/Servo.cpp | 2 +- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index e2b8f111bfd5..76037e372386 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -73,12 +73,15 @@ uint16_t MarlinHAL::adc_result; esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX]; adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {}; uint32_t thresholds[ADC_ATTEN_MAX]; -volatile int numPWMUsed = 0, - pwmPins[MAX_PWM_PINS], - pwmValues[MAX_PWM_PINS]; -pin_t chan_pin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32 -uint32_t chan_freq[(CHANNEL_MAX_NUM + 1) / 2]; // ledcReadFreq doesn't work if a duty hasn't been set yet! -uint16_t chan_res[(CHANNEL_MAX_NUM + 1) / 2]; + +volatile int numPWMUsed = 0; +volatile struct { pin_t pin; int value; } pwmInfo[MAX_PWM_PINS]; + +struct { + pin_t pin; // PWM capable IOpins - not 0 or >33 on ESP32 + uint32_t freq; // ledcReadFreq doesn't work if a duty hasn't been set yet! + uint16_t res; +} channel[CHANNEL_MAX_NUM + 1]; // ------------------------ // Public functions @@ -257,57 +260,56 @@ void MarlinHAL::adc_start(const pin_t pin) { int8_t pin_to_chan(uint8_t pin) { for (int i = 0; i <= CHANNEL_MAX_NUM; i++) - if (chan_pin[i] == pin) return i; + if (channel[i].pin == pin) return i; return -1; } // get PWM channel for pin - if none then attach a new one // return -1 if fail or invalid pin#, channel # (0-15) if success int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) { - if (pin == 0 || (pin > MAX_PWM_IOPIN)) return -1; // not a hardware PWM pin! - int8_t chan = pin_to_chan(pin); - if (chan >= 0) return chan; + if (!WITHIN(pin, 1, MAX_PWM_IOPIN)) return -1; // Not a hardware PWM pin! + int8_t cid = pin_to_chan(pin); + if (cid >= 0) return cid; - // find an empty adjacent chanel (same timer & freq/res) + // Find an empty adjacent channel (same timer & freq/res) for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { - if (chan_pin[i] == 0) { - if (chan_pin[i ^ 0x1] != 0) { - if ((chan_freq[i / 2] == freq) && (chan_res[i / 2] == res)) { - chan_pin[i] = pin; // allocate pwm to this channel + if (channel[i].pin == 0) { + if (channel[i ^ 0x1].pin != 0) { + if (channel[i / 2].freq == freq && channel[i / 2].res == res) { + channel[i].pin = pin; // Allocate PWM to this channel ledcAttachPin(pin, i); return i; } } - else if (chan == -1) { // pair of empty channels? - chan = i & 0xfe; // save lower channel number - } + else if (cid == -1) // Pair of empty channels? + cid = i & 0xfe; // Save lower channel number } } // not attached, is an empty timer slot avail? - if (chan >= 0) { - chan_freq[chan / 2] = freq; - chan_pin[chan] = pin; - chan_res[chan / 2] = res; - ledcSetup(chan, freq, res); - ledcAttachPin(pin, chan); + if (cid >= 0) { + channel[cid / 2].freq = freq; + channel[cid].pin = pin; + channel[cid / 2].res = res; + ledcSetup(cid, freq, res); + ledcAttachPin(pin, cid); } - return chan; // -1 if no channel avail + return cid; // -1 if no channel avail } void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) { - int8_t channel = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); - if (channel >= 0) { + const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); + if (cid >= 0) { uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1); - ledcWrite(channel, duty); + ledcWrite(cid, duty); } } -uint8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { - int8_t channel = pin_to_chan(pin); - if (channel >= 0) { - if (f_desired == ledcReadFreq(channel)) return channel; // no freq change - ledcDetachPin(chan_pin[channel]); - chan_pin[channel] = 0; // remove old freq channel +int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { + const int8_t cid = pin_to_chan(pin); + if (cid >= 0) { + if (f_desired == ledcReadFreq(cid)) return cid; // no freq change + ledcDetachPin(channel[cid].pin); + channel[cid].pin = 0; // remove old freq channel } return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one } @@ -315,16 +317,16 @@ uint8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) // use hardware PWM if avail, if not then ISR void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution! // Use ledc hardware for internal pins - int8_t channel = get_pwm_channel(pin, freq, res); - if (channel >= 0) { - ledcWrite(channel, value); // set duty value + const int8_t cid = get_pwm_channel(pin, freq, res); + if (cid >= 0) { + ledcWrite(cid, value); // set duty value } else { // not a hardware PWM pin OR no PWM channels available int idx = -1; // Search Pin for (int i = 0; i < numPWMUsed; ++i) - if (pwmPins[i] == pin) { idx = i; break; } + if (pwmInfo[i].pin == pin) { idx = i; break; } // not found ? if (idx < 0) { @@ -333,7 +335,7 @@ void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PW // Take new slot for pin idx = numPWMUsed; - pwmPins[idx] = pin; + pwmInfo[idx].pin = pin; // Start timer on first use if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); @@ -341,7 +343,7 @@ void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PW } // Use 7bit internal value - add 1 to have 100% high at 255 - pwmValues[idx] = (value + 1) / 2; + pwmInfo[idx].value = (value + 1) / 2; } } @@ -353,9 +355,9 @@ HAL_PWM_TIMER_ISR() { for (int i = 0; i < numPWMUsed; ++i) { if (count == 0) // Start of interval - WRITE(pwmPins[i], pwmValues[i] ? HIGH : LOW); - else if (pwmValues[i] == count) // End of duration - WRITE(pwmPins[i], LOW); + digitalWrite(pwmInfo[i].pin, pwmInfo[i].value ? HIGH : LOW); + else if (pwmInfo[i].value == count) // End of duration + digitalWrite(pwmInfo[i].pin, LOW); } // 128 for 7 Bit resolution diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index f37dd62a8688..b5d10db8f2e4 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -226,6 +226,6 @@ class MarlinHAL { * Allocate and set the frequency of a hardware PWM pin * Returns -1 if no pin available. */ - static uint8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired); + static int8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired); }; diff --git a/Marlin/src/HAL/ESP32/Servo.cpp b/Marlin/src/HAL/ESP32/Servo.cpp index de72b7110480..ca3950d07f75 100644 --- a/Marlin/src/HAL/ESP32/Servo.cpp +++ b/Marlin/src/HAL/ESP32/Servo.cpp @@ -41,7 +41,7 @@ int8_t Servo::attach(const int inPin) { // leave channel connected to servo - set duty to zero void Servo::detach() { - if (channel != -1) ledcWrite(channel, 0); + if (channel >= 0) ledcWrite(channel, 0); } int Servo::read() { return degrees; } From 5f9d625c1c7e4ea6cfb5d09bf1b321a11f92a298 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 26 Feb 2022 14:59:52 -0600 Subject: [PATCH 08/18] outdent --- Marlin/src/HAL/ESP32/HAL.cpp | 37 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 76037e372386..33c18471be01 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -320,31 +320,32 @@ void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PW const int8_t cid = get_pwm_channel(pin, freq, res); if (cid >= 0) { ledcWrite(cid, value); // set duty value + return; } - else { // not a hardware PWM pin OR no PWM channels available - int idx = -1; - // Search Pin - for (int i = 0; i < numPWMUsed; ++i) - if (pwmInfo[i].pin == pin) { idx = i; break; } + // not a hardware PWM pin OR no PWM channels available + int idx = -1; - // not found ? - if (idx < 0) { - // No slots remaining - if (numPWMUsed >= MAX_PWM_PINS) return; + // Search Pin + for (int i = 0; i < numPWMUsed; ++i) + if (pwmInfo[i].pin == pin) { idx = i; break; } - // Take new slot for pin - idx = numPWMUsed; - pwmInfo[idx].pin = pin; - // Start timer on first use - if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); + // not found ? + if (idx < 0) { + // No slots remaining + if (numPWMUsed >= MAX_PWM_PINS) return; - ++numPWMUsed; - } + // Take new slot for pin + idx = numPWMUsed; + pwmInfo[idx].pin = pin; + // Start timer on first use + if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); - // Use 7bit internal value - add 1 to have 100% high at 255 - pwmInfo[idx].value = (value + 1) / 2; + ++numPWMUsed; } + + // Use 7bit internal value - add 1 to have 100% high at 255 + pwmInfo[idx].value = (value + 1) / 2; } // Handle PWM timer interrupt From a8bd231ad8559b1830e8780a7773a17c432b4617 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 26 Feb 2022 14:49:43 -0600 Subject: [PATCH 09/18] use structs, replace WRITE --- Marlin/src/HAL/ESP32/HAL.cpp | 114 +++++++++++++++++---------------- Marlin/src/HAL/ESP32/HAL.h | 2 +- Marlin/src/HAL/ESP32/Servo.cpp | 2 +- 3 files changed, 61 insertions(+), 57 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index e2b8f111bfd5..5bc49b6689d0 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -73,12 +73,16 @@ uint16_t MarlinHAL::adc_result; esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX]; adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {}; uint32_t thresholds[ADC_ATTEN_MAX]; -volatile int numPWMUsed = 0, - pwmPins[MAX_PWM_PINS], - pwmValues[MAX_PWM_PINS]; + +volatile int numPWMUsed = 0; +volatile struct { pin_t pin; int value; } pwmState[MAX_PWM_PINS]; + pin_t chan_pin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32 -uint32_t chan_freq[(CHANNEL_MAX_NUM + 1) / 2]; // ledcReadFreq doesn't work if a duty hasn't been set yet! -uint16_t chan_res[(CHANNEL_MAX_NUM + 1) / 2]; + +struct { + uint32_t freq; // ledcReadFreq doesn't work if a duty hasn't been set yet! + uint16_t res; +} pwmInfo[(CHANNEL_MAX_NUM + 1) / 2]; // ------------------------ // Public functions @@ -255,7 +259,7 @@ void MarlinHAL::adc_start(const pin_t pin) { // PWM // ------------------------ -int8_t pin_to_chan(uint8_t pin) { +int8_t channel_for_pin(const uint8_t pin) { for (int i = 0; i <= CHANNEL_MAX_NUM; i++) if (chan_pin[i] == pin) return i; return -1; @@ -264,50 +268,49 @@ int8_t pin_to_chan(uint8_t pin) { // get PWM channel for pin - if none then attach a new one // return -1 if fail or invalid pin#, channel # (0-15) if success int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) { - if (pin == 0 || (pin > MAX_PWM_IOPIN)) return -1; // not a hardware PWM pin! - int8_t chan = pin_to_chan(pin); - if (chan >= 0) return chan; + if (!WITHIN(pin, 1, MAX_PWM_IOPIN)) return -1; // Not a hardware PWM pin! + int8_t cid = channel_for_pin(pin); + if (cid >= 0) return cid; - // find an empty adjacent chanel (same timer & freq/res) + // Find an empty adjacent channel (same timer & freq/res) for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { if (chan_pin[i] == 0) { if (chan_pin[i ^ 0x1] != 0) { - if ((chan_freq[i / 2] == freq) && (chan_res[i / 2] == res)) { - chan_pin[i] = pin; // allocate pwm to this channel + if (pwmInfo[i / 2].freq == freq && pwmInfo[i / 2].res == res) { + chan_pin[i] = pin; // Allocate PWM to this channel ledcAttachPin(pin, i); return i; } } - else if (chan == -1) { // pair of empty channels? - chan = i & 0xfe; // save lower channel number - } + else if (cid == -1) // Pair of empty channels? + cid = i & 0xFE; // Save lower channel number } } // not attached, is an empty timer slot avail? - if (chan >= 0) { - chan_freq[chan / 2] = freq; - chan_pin[chan] = pin; - chan_res[chan / 2] = res; - ledcSetup(chan, freq, res); - ledcAttachPin(pin, chan); + if (cid >= 0) { + chan_pin[cid] = pin; + pwmInfo[cid / 2].freq = freq; + pwmInfo[cid / 2].res = res; + ledcSetup(cid, freq, res); + ledcAttachPin(pin, cid); } - return chan; // -1 if no channel avail + return cid; // -1 if no channel avail } void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) { - int8_t channel = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); - if (channel >= 0) { + const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); + if (cid >= 0) { uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1); - ledcWrite(channel, duty); + ledcWrite(cid, duty); } } -uint8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { - int8_t channel = pin_to_chan(pin); - if (channel >= 0) { - if (f_desired == ledcReadFreq(channel)) return channel; // no freq change - ledcDetachPin(chan_pin[channel]); - chan_pin[channel] = 0; // remove old freq channel +int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { + const int8_t cid = channel_for_pin(pin); + if (cid >= 0) { + if (f_desired == ledcReadFreq(cid)) return cid; // no freq change + ledcDetachPin(chan_pin[cid]); + chan_pin[cid] = 0; // remove old freq channel } return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one } @@ -315,34 +318,35 @@ uint8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) // use hardware PWM if avail, if not then ISR void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution! // Use ledc hardware for internal pins - int8_t channel = get_pwm_channel(pin, freq, res); - if (channel >= 0) { - ledcWrite(channel, value); // set duty value + const int8_t cid = get_pwm_channel(pin, freq, res); + if (cid >= 0) { + ledcWrite(cid, value); // set duty value + return; } - else { // not a hardware PWM pin OR no PWM channels available - int idx = -1; - // Search Pin - for (int i = 0; i < numPWMUsed; ++i) - if (pwmPins[i] == pin) { idx = i; break; } + // not a hardware PWM pin OR no PWM channels available + int idx = -1; - // not found ? - if (idx < 0) { - // No slots remaining - if (numPWMUsed >= MAX_PWM_PINS) return; + // Search Pin + for (int i = 0; i < numPWMUsed; ++i) + if (pwmState[i].pin == pin) { idx = i; break; } - // Take new slot for pin - idx = numPWMUsed; - pwmPins[idx] = pin; - // Start timer on first use - if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); + // not found ? + if (idx < 0) { + // No slots remaining + if (numPWMUsed >= MAX_PWM_PINS) return; - ++numPWMUsed; - } + // Take new slot for pin + idx = numPWMUsed; + pwmState[idx].pin = pin; + // Start timer on first use + if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY); - // Use 7bit internal value - add 1 to have 100% high at 255 - pwmValues[idx] = (value + 1) / 2; + ++numPWMUsed; } + + // Use 7bit internal value - add 1 to have 100% high at 255 + pwmState[idx].value = (value + 1) / 2; } // Handle PWM timer interrupt @@ -353,9 +357,9 @@ HAL_PWM_TIMER_ISR() { for (int i = 0; i < numPWMUsed; ++i) { if (count == 0) // Start of interval - WRITE(pwmPins[i], pwmValues[i] ? HIGH : LOW); - else if (pwmValues[i] == count) // End of duration - WRITE(pwmPins[i], LOW); + digitalWrite(pwmState[i].pin, pwmState[i].value ? HIGH : LOW); + else if (pwmState[i].value == count) // End of duration + digitalWrite(pwmState[i].pin, LOW); } // 128 for 7 Bit resolution diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index f37dd62a8688..b5d10db8f2e4 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -226,6 +226,6 @@ class MarlinHAL { * Allocate and set the frequency of a hardware PWM pin * Returns -1 if no pin available. */ - static uint8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired); + static int8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired); }; diff --git a/Marlin/src/HAL/ESP32/Servo.cpp b/Marlin/src/HAL/ESP32/Servo.cpp index de72b7110480..ca3950d07f75 100644 --- a/Marlin/src/HAL/ESP32/Servo.cpp +++ b/Marlin/src/HAL/ESP32/Servo.cpp @@ -41,7 +41,7 @@ int8_t Servo::attach(const int inPin) { // leave channel connected to servo - set duty to zero void Servo::detach() { - if (channel != -1) ledcWrite(channel, 0); + if (channel >= 0) ledcWrite(channel, 0); } int Servo::read() { return degrees; } From 4ef39893a92c3bac3ed29e7f8b21aab274e8b836 Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 28 Feb 2022 10:29:13 +0000 Subject: [PATCH 10/18] Array changes Initialise pin array to zeroes. Revert to separate pin array to save a few bytes of memory (freq & res arrays only need to be 8 deep). --- Marlin/src/HAL/ESP32/HAL.cpp | 28 ++++++++++++++-------------- Marlin/src/HAL/ESP32/HAL.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 33c18471be01..43763e80856f 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -77,11 +77,11 @@ uint32_t thresholds[ADC_ATTEN_MAX]; volatile int numPWMUsed = 0; volatile struct { pin_t pin; int value; } pwmInfo[MAX_PWM_PINS]; +pin_t chanPin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32 struct { - pin_t pin; // PWM capable IOpins - not 0 or >33 on ESP32 uint32_t freq; // ledcReadFreq doesn't work if a duty hasn't been set yet! uint16_t res; -} channel[CHANNEL_MAX_NUM + 1]; +} pwmTimer[(CHANNEL_MAX_NUM + 1) / 2]; // ------------------------ // Public functions @@ -258,9 +258,9 @@ void MarlinHAL::adc_start(const pin_t pin) { // PWM // ------------------------ -int8_t pin_to_chan(uint8_t pin) { +int8_t pin_to_chan(pin_t pin) { for (int i = 0; i <= CHANNEL_MAX_NUM; i++) - if (channel[i].pin == pin) return i; + if (chanPin[i] == pin) return i; return -1; } @@ -273,10 +273,10 @@ int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) // Find an empty adjacent channel (same timer & freq/res) for (int i = 0; i <= CHANNEL_MAX_NUM; i++) { - if (channel[i].pin == 0) { - if (channel[i ^ 0x1].pin != 0) { - if (channel[i / 2].freq == freq && channel[i / 2].res == res) { - channel[i].pin = pin; // Allocate PWM to this channel + if (chanPin[i] == 0) { + if (chanPin[i ^ 0x1] != 0) { + if (pwmTimer[i / 2].freq == freq && pwmTimer[i / 2].res == res) { + chanPin[i] = pin; // Allocate PWM to this channel ledcAttachPin(pin, i); return i; } @@ -287,9 +287,9 @@ int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) } // not attached, is an empty timer slot avail? if (cid >= 0) { - channel[cid / 2].freq = freq; - channel[cid].pin = pin; - channel[cid / 2].res = res; + pwmTimer[cid / 2].freq = freq; + pwmTimer[cid / 2].res = res; + chanPin[cid] = pin; ledcSetup(cid, freq, res); ledcAttachPin(pin, cid); } @@ -307,9 +307,9 @@ void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) { const int8_t cid = pin_to_chan(pin); if (cid >= 0) { - if (f_desired == ledcReadFreq(cid)) return cid; // no freq change - ledcDetachPin(channel[cid].pin); - channel[cid].pin = 0; // remove old freq channel + if (f_desired == pwmTimer[cid / 2].freq) return cid; // no freq change + ledcDetachPin(chanPin[cid]); + chanPin[cid] = 0; // remove old freq channel } return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one } diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index b5d10db8f2e4..8b26c3471d39 100644 --- a/Marlin/src/HAL/ESP32/HAL.h +++ b/Marlin/src/HAL/ESP32/HAL.h @@ -67,7 +67,7 @@ #define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment #define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency() #define PWM_RESOLUTION 10u // Default PWM bit resolution -#define CHANNEL_MAX_NUM 15u // max PWM channel to allocate (7 to only use low speed, 15 to use high speed - see above) +#define CHANNEL_MAX_NUM 15u // max PWM channel # to allocate (7 to only use low speed, 15 to use low & high) #define MAX_PWM_IOPIN 33u // hardware pwm pins < 34 // ------------------------ From 381c2bc145847f3afa38fb1a0f7b45e060897bf9 Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 28 Feb 2022 10:59:27 +0000 Subject: [PATCH 11/18] fixed chanPin variable name --- Marlin/src/HAL/ESP32/HAL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 60dbafb4f9cc..69cf1c3fe209 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -263,7 +263,7 @@ void MarlinHAL::adc_start(const pin_t pin) { int8_t channel_for_pin(const uint8_t pin) { for (int i = 0; i <= CHANNEL_MAX_NUM; i++) - if (chanPin[i] == pin) return i; + if (chan_pin[i] == pin) return i; return -1; } From 76a4b3ffb71bcec10cda0b14676a1738745d463c Mon Sep 17 00:00:00 2001 From: JohnR Date: Sun, 13 Mar 2022 10:45:14 +0000 Subject: [PATCH 12/18] Update Configuration_adv.h Comment update. --- Marlin/Configuration_adv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 83a8eaa0fb87..8ee24063e0e4 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -3465,7 +3465,7 @@ #define SPINDLE_LASER_USE_PWM // Enable if your controller supports setting the speed/power #if ENABLED(SPINDLE_LASER_USE_PWM) #define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower - #define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC) + #define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR, ESP32 and LPC) #endif //#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11 From 407d9f54c3e0d2246e84291f8c73b871a88c1126 Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 14 Mar 2022 17:20:58 +0000 Subject: [PATCH 13/18] Change ADC ref for MKS TinyBee MKS TinyBee uses a 2.5V ADC reference instead of a 3.3V on other ESP32 boards. --- Marlin/src/HAL/ESP32/HAL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 69cf1c3fe209..aceae7a73e0e 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -240,7 +240,7 @@ void MarlinHAL::adc_start(const pin_t pin) { const adc1_channel_t chan = get_channel(pin); uint32_t mv; esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); - adc_result = mv * 1023.0 / 3300.0; + adc_result = mv * 1023.0 / TERN(MB(MKS_TINYBEE), 2500.0, 3300.0); // TinyBee uses 2.5v VDDA ref // Change the attenuation level based on the new reading adc_atten_t atten; From 8259ee9884645f9de550ee20da9bc99ad4de1b9b Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 14 Mar 2022 17:32:27 +0000 Subject: [PATCH 14/18] Corrects ADC Vref divisor for MKS TinyBee MKS TinyBee uses a 2.5V VDDA ADC reference instead of the more common 3.3V. --- Marlin/src/HAL/ESP32/HAL.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index aceae7a73e0e..785fce7d6f67 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -240,8 +240,12 @@ void MarlinHAL::adc_start(const pin_t pin) { const adc1_channel_t chan = get_channel(pin); uint32_t mv; esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); - adc_result = mv * 1023.0 / TERN(MB(MKS_TINYBEE), 2500.0, 3300.0); // TinyBee uses 2.5v VDDA ref - + #if MB(MKS_TINYBEE) + adc_result = mv * 1023.0 / 2500.0; // TinyBee uses 2.5v VDDA ref + #else + adc_result = mv * 1023.0 / 3300.0; + #endif + // Change the attenuation level based on the new reading adc_atten_t atten; if (mv < thresholds[ADC_ATTEN_DB_0] - 100) From 8bccc11d474c1cd099ba8b870bb7018b1a5b3f01 Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 14 Mar 2022 17:49:01 +0000 Subject: [PATCH 15/18] Revert "Corrects ADC Vref divisor for MKS TinyBee" This reverts commit 8259ee9884645f9de550ee20da9bc99ad4de1b9b. --- Marlin/src/HAL/ESP32/HAL.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 785fce7d6f67..aceae7a73e0e 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -240,12 +240,8 @@ void MarlinHAL::adc_start(const pin_t pin) { const adc1_channel_t chan = get_channel(pin); uint32_t mv; esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); - #if MB(MKS_TINYBEE) - adc_result = mv * 1023.0 / 2500.0; // TinyBee uses 2.5v VDDA ref - #else - adc_result = mv * 1023.0 / 3300.0; - #endif - + adc_result = mv * 1023.0 / TERN(MB(MKS_TINYBEE), 2500.0, 3300.0); // TinyBee uses 2.5v VDDA ref + // Change the attenuation level based on the new reading adc_atten_t atten; if (mv < thresholds[ADC_ATTEN_DB_0] - 100) From 63c296592870491d65a0ac84c4fa7ef1730e3095 Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 14 Mar 2022 17:49:06 +0000 Subject: [PATCH 16/18] Revert "Change ADC ref for MKS TinyBee" This reverts commit 407d9f54c3e0d2246e84291f8c73b871a88c1126. --- Marlin/src/HAL/ESP32/HAL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index aceae7a73e0e..69cf1c3fe209 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -240,7 +240,7 @@ void MarlinHAL::adc_start(const pin_t pin) { const adc1_channel_t chan = get_channel(pin); uint32_t mv; esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); - adc_result = mv * 1023.0 / TERN(MB(MKS_TINYBEE), 2500.0, 3300.0); // TinyBee uses 2.5v VDDA ref + adc_result = mv * 1023.0 / 3300.0; // Change the attenuation level based on the new reading adc_atten_t atten; From 931fd6bc453128326687e4d75e883e951ef7a8fb Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 14 Mar 2022 17:51:06 +0000 Subject: [PATCH 17/18] Correct ADC Vref divisor for MKS TinyBee MKS TinyBee uses a 2.5V VDDA ADC reference instead of the more common 3.3V. 2500.0 = 2.5V. Board uses a Zener diode - measuring the actual voltage on any disconnected thermistor pin and using that value ( x 1000) will improve precision. --- Marlin/src/HAL/ESP32/HAL.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 69cf1c3fe209..2836120da045 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -240,8 +240,12 @@ void MarlinHAL::adc_start(const pin_t pin) { const adc1_channel_t chan = get_channel(pin); uint32_t mv; esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); - adc_result = mv * 1023.0 / 3300.0; - + #if MB(MKS_TINYBEE) + adc_result = mv * 1023.0 / 2500.0; // TinyBee uses 2.5v VDDA ref + #else + adc_result = mv * 1023.0 / 3300.0; + #endif + // Change the attenuation level based on the new reading adc_atten_t atten; if (mv < thresholds[ADC_ATTEN_DB_0] - 100) From 47e60673f3f0cc242abf07e9c9daf1a8b84576c5 Mon Sep 17 00:00:00 2001 From: JohnR Date: Mon, 14 Mar 2022 17:58:18 +0000 Subject: [PATCH 18/18] Revert "Correct ADC Vref divisor for MKS TinyBee" This reverts commit 931fd6bc453128326687e4d75e883e951ef7a8fb. --- Marlin/src/HAL/ESP32/HAL.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index 2836120da045..69cf1c3fe209 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -240,12 +240,8 @@ void MarlinHAL::adc_start(const pin_t pin) { const adc1_channel_t chan = get_channel(pin); uint32_t mv; esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); - #if MB(MKS_TINYBEE) - adc_result = mv * 1023.0 / 2500.0; // TinyBee uses 2.5v VDDA ref - #else - adc_result = mv * 1023.0 / 3300.0; - #endif - + adc_result = mv * 1023.0 / 3300.0; + // Change the attenuation level based on the new reading adc_atten_t atten; if (mv < thresholds[ADC_ATTEN_DB_0] - 100)