AnalogWrite Library for ESP32-ESP32S2 Arduino core

A request to add the new AnalogWrite library for ESP32-ESP32S2 Arduino core.
Here’s the link to the GitHub repo…

GitHub - Dlloydev/ESP32-ESP32S2-AnalogWrite: Provides analogWrite for ESP32 and ESP32S2 using the LEDC functions. Controls both PWM and DAC outputs. Smart GPIO resource management.

1 Like

So as not to confuse with another library with similar name, here’s the ArduBadge so you can install the correct library or check out the documentation.


You can post feedback here if you like … I’ll try to answer any questions.

  • I fully tested this on a SP32Dev Board and couldn’t find any issues.
  • Currently awaiting delivery of an ESP32-S2 Saola-1M for testing.
  • Plan of testing and updating this to work with the ESP32-S3 when available.

… unless the Arduino core for the ESP32 eventually offers analogWrite as part of the core :slightly_smiling_face:

Something is currently broken with PWM on the ESP32 S2.

Thanks @cattledog! Yes, I saw that link about the PWM problem with the servo. I think he’s using the MPWM peripheral, but didn’t look too closely. There’s also the Delta Sigma and LEDc peripherals … the Arduino core provides functions that give analog write / PWM capabilities for these. I think the reason for not yet offering analogWrite functions with the core is the complexities of utilizing the best resource management strategy to avoid conflicts with other code.

I’m using the LEDc peripheral and have discovered something that’s quite simple to check and see if any pin has been assigned to GPIO. (the MCU_SEL mux register). Apparently, after power-up, the GPIO pins are assigned to function 1 (0), but after any code works with a pin … even just setting it to input, this mux register switches to function 3 (GPIO). So now I can monitor if a pin is available for use and avoid taking over pins used by other code. With LEDc, I don’t think there’s any purpose (or if it’s even possible) to use a timer/channel without dedicating it to a pin.

I couldn’t find any code that puts this multiplexor back to startup status … took forever to work out something to control this, but ended up being quite simple.

1 Like

I have a Feather S2 from Unexpected Maker

I have not gotten very far into using it, and mostly used it as an opportunity to experiment with Circuit Python. The native USB support makes that possible. Both UM and Adafruit recommend using Circuit Python, and advise that the Arduino core is not fully developed and to not use it.

The Arduino S2 core is not available from the board manager, and the procedure for installing it from the development branch is complicated. I also understand that Espressif has slowed work on the S2 core, and was working on the S3. I’m not clear about the long term role that the S2 has in the product line.

I have never used the Espressif IDF directly, but I guess that is another option.

My advice would be to focus your library work on the ESP32 and leave the S2 and S3 alone until there is Arduino core support available through the boards manager. People who can currently use the Arduino core on those devices are likely experienced enough to use the ledc peripheral.

Good luck with your efforts.

1 Like

The analogWrite library is now fully tested on the ESP32-S2 Saola-1M (library has been updated to version 1.1.0). I used this link to install the S2 support and it worked fine. I have both cores installed on my PC and just rename the folders navigate between both cores which was quite handy during development.

For ESP-S2 boards, I found that the issue #5050 with the ledc function will set the frequency low by a factor of 80. So the temporary workaround is to enter a value 80x high.

The analogWrite, analogWriteFrequency and analogWriteResolution functions provided are quite simple to use … no requirement as to when, where or in what order they’re used. That is, frequency, resolution and duty cycle can be changed on the fly.

Pin resource and timer management is automatic and transparent. It detects if a timer resource or pin is used by external code to avoid conflicts. A PWM status function is provided.

1 Like

Thanks for this very good library.

The Arduino S2 core is not available from the board manager, and the procedure for installing it from the development branch is complicated.

I used this link to install the S2 support and it worked fine

It’s much easier to install S2 and C3 core with esp32 core v1.0.6+ now.

HOWTO Install esp32 core for ESP32-S2 (Saola, AI-Thinker ESP-12K) and ESP32-C3 boards

1 Like

As of April 16th 2021 , the esp32-s2/c3 board support has been included in master branch of esp32 core.

This is likely a big step forward towards getting the core through the boards manager.

I followed this procedure to install the current master development branch which supports the s2/s3 boards.

I can now see the UM Feather S2 as a board choice.

It’s getting easier. Add this link to the preferences file in Arduino15 and the boards manager will install v2.0.0 alpha1

I don’t know when they added the feature of installing the development master through the boards manager but it makes things simple


Both UM and Adafruit recommend using Circuit Python, and advise that the Arduino core is not fully developed and to not use it.

I can now see the UM Feather S2 as a board choice.

The S2 now is OK to use, especially with esp32 core v1.0.6+. The SSL, Blynk, LittleFS and SPIFFS are all working now. You don’t need to use only Python anymore.

Try these libraries which supports those features on ESP32-S2

  1. WebSockets2_Generic
  2. Blynk_WM
  3. Blynk_Async_WM
  4. ESP_WiFiManager
  5. ESPAsync_WiFiManager

and many more to come.


The Arduino reference for 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 today’s new version 1.2.0, this condition is detected and corrected, where the hardware timer is programmed with 2resolution, which drives the output signal fully on. The pin status function will return 2resolution-1 which is the duty cycle value entered.

New version 1.2.1

  • 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.

  • There is now normal LEDc PWM for 1-7 bit resolution (ideal for high frequency applications) and the max duty value is set to 2resolution for 8-16-bit resolution for 0-100% PWM (ideal for complete control of common anode LED devices (and other devices).

AnalogWrite with phase control!


Now analogWrite can assign a pin and contol PWM duty value, frequency, resolution and phase all from one function. This function now returns the PWM frequency reported from the ledc framework.


float analogWrite(int8_t pin, int32_t value, float frequency, uint8_t resolution, uint32_t phase);
float analogWrite(int8_t pin, int32_t value, float frequency, uint8_t resolution);
float analogWrite(int8_t pin, int32_t value, float frequency);
float analogWrite(int8_t pin, int32_t value);

3-phase PWM Example:

Details: 3-pins (4, 5 and 12), 10-bit PWM split into 3 equal ON-periods of 341. Frequency is 100Hz. Signal on pin 5 is phase shifted by 341 steps, signal on pin 12 is shifted by 682 steps.

The control range for duty value and phase is the same (0-1023) for 10-bit resolution.

  analogWrite(4, 341, 100, 10, 0);
  analogWrite(5, 341, 100, 10, 341);
  analogWrite(12, 341, 100, 10, 682);

1 Like

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.

pwm.write() 3.0.2

  • Compatible with latest ESP32 Arduino core
  • Code refactored, now in a Class
  • The main function syntax is pwm.write()
  • Added ESP32-C3 support and example

Wokwi phase shift examples ... ESP32 ... ESP32-S2 ... ESP32-C3

1 Like