PWM Woes


Just in case anyone is having issues with the ESP8266 SDK and PWM. Problem now “solved” but you might find this interesting.

For many months now I’ve been using the PWM on the ESP8266 successfully, so much so that I’ve not tested it and just recently I’ve noticed it no longer works. Specifically, the PWM startup routine forces my ESP8266s to reboot with a watchdog timeout.

So first things first, the SDK manual appears to STILL be incorrect. It states in version 1.53 (ESP8266 SDK API guide) in page 178 that the DUTY parameter is pointer to an 8 bit array.

Yet the header and routines elsewhere require 32 bit values for the array. I’ve always ignored this.

#define PWM_1_OUT_IO_NUM 15

#define PWM_3_OUT_IO_NUM 4

#define PWM_4_OUT_IO_NUM 5

uint32 duty[] = {0, 0, 0};
uint32 freq = 1000;
static uint8 donepwm = 0;

uint32 io_info[][3] = {

So with these definitions I call….

if (donepwm == 0) {
   pwm_init(freq, duty, 3, io_info);
   donepwm = 1;


You should call the setup once only.. hence the wrapper using “donepwm”. This has always worked and yet now, no matter what I do, this crashes the processor – usually a few seconds after it has been called.


ets Jan  8 2013,rst cause:4, boot mode:(1,0)

wdt reset

This used to work – now it causes the WDT.

The example in the manual..

Example: uint32 io_info[][3] =  {{PWM_0_OUT_IO_MUX,PWM_0_OUT_IO_FUNC,PWM_0_OUT_IO_NUM},          {PWM_1_OUT_IO_MUX,PWM_1_OUT_IO_FUNC,PWM_1_OUT_IO_NUM}, {PWM_2_OUT_IO_MUX,PWM_2_OUT_IO_FUNC,PWM_2_OUT_IO_NUM}};

pwm_init(light_param.pwm_period, light_param.pwm_duty, 3, io_info);

HERE is a  “fix”…

I amended the rom0.ld file and sure enough – fixed…

But that means there’s an issue somewhere –  and that manual needs fixing  – I hope Espressif are looking in.


3 thoughts on “PWM Woes

  1. Do you a simple PWM example for the ESP8266, not code fragments but a full example?

    I still don’t understand the arguments for pwm_init(), online searches are not helping me and the espressif ‘documentation’ is crap.

    I want to turn on the PWM hardware, route it to a single GPIO pin, set the frequency to 5Khz and vary the duty cycle.

    1. The PWM for ESP is not one of their better features – you can’t turn it off as I found out when trying to run an RGB LED after starting up PWM…. and it’s not perfect – you can’t use 100% duty cycle – but it’s pretty reliable and great for running LEDs.

      If you check out my C code – in the commands there is PWM use which of course involves varying the duty cycle – I don’t have a complete running example as such but if you follow the instructions below….

      My source code is here..

      Check out /user/petes_code.c

      Around Line 22 for the setup for PWM channels – I’ve setup 3 IO pins for PWM – line 57 on define 1,4 and 5 which equates to GPIO 15, 4 and 5

      At line 2088 is the setup call which you must do once and once only….

      2092 onwards set the duty (32 bits) in my case using a lookup table…. then pwm_start()

      That’s really all there is to it.

      1. Hi,
        pwm_set_duty(); is include in which library. Are you using pwm.h from sdk?

Comments are closed.