Skip to content

Commit

Permalink
Temp fix for ESP32-S2 issue #5050
Browse files Browse the repository at this point in the history
When using ESP32S2 devices, this version offers a temporary fix for ***ESP32-S2 PWM for a Servo pulse issue #5050*** but with limited frequency range. Tested range is 8-bit: 4Hz to 2.5kHz, 13-bit 0.2Hz to 120Hz.
  • Loading branch information
Dlloydev committed Apr 22, 2021
1 parent b06ea74 commit a88d315
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 18 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ The use of this function is similar to the Arduino method as its resource manage

### PWM Wave

Arduino's reference for [`analogWrite()`](https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/) describes the PWM wave characteristics for various hardware architecture. The general operational characteristic is 8-bit duty cycle control where the output will be **always off** for value 0 and **always on** for value 255. With the various devices and timer modes, sometimes a bit correction is required to achieve full off or on. The ESP8266 follows this mode of operation, but with the different timer architecture on the ESP32 devices, the LEDc PWM operates in a different manner, where duty value 0 is always off, but duty value 255 will give an output that's 255/256 duty cycle (not fully on). This happens for any setting for bit resolution. As of version 1.2.0, this condition is detected and corrected, where the hardware is programmed with `2^resolution (bits)^`, which drives the output signal fully on.
Arduino's reference for [`analogWrite()`](https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/) describes the PWM wave characteristics for various hardware architecture. The general operational characteristic is 8-bit duty cycle control where the output will be **always off** for value 0 and **always on** for value 255. With the various devices and timer modes, sometimes a bit correction is required to achieve full off or on. The ESP8266 follows this mode of operation, but with the different timer architecture on the ESP32 devices, the **LEDc** PWM operates in a different manner, where duty value 0 is always off, but duty value 255 will give an output that's 255/256 duty cycle (not fully on).

As of version 1.2.1, this condition is detected and corrected, where the hardware is programmed with `2^resolution (bits)^`, which drives the output signal fully on for 8-bit and higher resolution settings. This full 0-100% control will now completely turn on/off both common anode and common cathode LED devices. For 1-7 bit resolution settings, the max value correction is not made and AnalogWrite works the same as the LEDc PWM control functions.

When using ESP32S2 devices, this version offers a temporary fix for ***ESP32-S2 PWM for a Servo pulse issue #5050*** but with limited frequency range. Tested range is 8-bit: 4Hz to 2.5kHz, 13-bit 0.2Hz to 120Hz.

| Board | PWM Pins | DAC Pins | PWM Frequency | Resolution |
| ------- | --------------------------------- | ---------- | --------------- | ----------------------- |
Expand Down Expand Up @@ -69,7 +73,7 @@ The the available PWM pins are determined by a pinMask constant. It might be ne
- [AnalogWriteTest](https://github.com/Dlloydev/ESP32-ESP32S2-AnalogWrite/blob/main/examples/AnalogWriteTest/AnalogWriteTest.ino)
- [Fade](https://github.com/Dlloydev/ESP32-ESP32S2-AnalogWrite/tree/main/examples/Fade)

### Notes and Warnings
### Notes

Both timer resolution and PWM frequency should be calculated to get expected results. Refer to [Supported Range of Frequency and Duty Resolution](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/ledc.html#ledc-api-supported-range-frequency-duty-resolution) as a reference.

Expand Down
12 changes: 5 additions & 7 deletions analogWrite.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**********************************************************************************
AnalogWrite Library for ESP32-ESP32S2 Arduino core - Version 1.2.0
AnalogWrite Library for ESP32-ESP32S2 Arduino core - Version 1.2.1
by dlloydev https://github.com/Dlloydev/ESP32-ESP32S2-AnalogWrite
This Library is licensed under the MIT License
**********************************************************************************/
Expand Down Expand Up @@ -39,12 +39,11 @@ void analogWrite(int8_t pin, int32_t value) {
ledcDetachPin(pinsStatus[ch / chd].pin);
REG_SET_FIELD(GPIO_PIN_MUX_REG[pin], MCU_SEL, GPIO_MODE_DEF_DISABLE);
} else { // write PWM
ledcSetup(ch, pinsStatus[ch / chd].frequency, pinsStatus[ch / chd].resolution);
/*constrain value to upper limit*/
if (value > ((1 << pinsStatus[ch / chd].resolution) - 1)) value = ((1 << pinsStatus[ch / chd].resolution) - 1);
uint8_t bits = pinsStatus[ch / chd].resolution;
ledcSetup(ch, pinsStatus[ch / chd].frequency, bits);
if (value > ((1 << bits) - 1)) value = (1 << bits); //constrain
if ((bits > 7) && (value == ((1 << bits) - 1))) value = (1 << bits); //keep PWM high
pinsStatus[ch / chd].value = value;
/*if value is at upper limit, keep PWM high*/
if (value == ((1 << pinsStatus[ch / chd].resolution) - 1)) value = (1 << pinsStatus[ch / chd].resolution);
ledcWrite(ch, value);
}
}
Expand All @@ -57,7 +56,6 @@ float analogWriteFrequency(int8_t pin, float frequency) {
if ((pinsStatus[ch / chd].pin) > 47) return -1;
pinsStatus[ch / chd].pin = pin;
pinsStatus[ch / chd].frequency = frequency;
//ledcChangeFrequency(ch, frequency, pinsStatus[ch / chd].resolution);
ledcSetup(ch, frequency, pinsStatus[ch / chd].resolution);
ledcWrite(ch, pinsStatus[ch / chd].value);
}
Expand Down
7 changes: 6 additions & 1 deletion analogWrite.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@
#if (defined(ESP32) || defined(ARDUINO_ARCH_ESP32))

#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)

#include "esp32-hal-ledc.h" //temporary fix for issue #5050

#define NUM_OUTPUT_PINS 45
#define DAC1 17
#define DAC2 18
const uint8_t muxSize = 48;
const uint64_t pinMask = 0x27FE00207FFE; //PWM
#else

#else //ESP32
#define NUM_OUTPUT_PINS 34
#define DAC1 25
#define DAC2 26
const uint8_t muxSize = 40;
const uint64_t pinMask = 0x308EFF034; //PWM

#endif

typedef struct pinStatus {
Expand Down
Loading

0 comments on commit a88d315

Please sign in to comment.