ESP8266: Using the PWM technique

Introduction

The objective of this post is to explain how to use the Pulse Width Modulation (PWM) technique with the ESP8266 and the main differences of the implementation comparing with the Arduino.

Pulse Width Modulation

In the PWM technique, we produce a square wave with a controllable duty cycle. This means that we can control, for each period of the wave, how much time it is at VCC (HIGH) or GND (LOW). So, it’s typical for the duty cycle to be specified as the percentage of time in which the WAVE is on an HIGH state, in a period, in respect to the period.

This way, PWM allows us to encode an analog value digitally and control an analog circuit [1]. In other words, we can simulate analog voltages between GND and VCC.

Some example applications are controlling the intensity of a LED or the speed of a motor using a signal produced by a microcontroller (naturally, for the motor, by using a transistor or other device to supply the current needed to move it).

The ESP8266 analogWrite

We assume the use of the ESP8266 libraries for the Arduino IDE. You can check here how to configure the Arduino IDE to support the ESP8266.

So, in order to use PWM, we can call the analogWrite function, which is a function also available (and commonly used) when programming Arduino boards. Nevertheless, there are some differences between the implementation for Arduinos and for the ESP8266.

In both cases, this function receives as arguments the pin where to produce the PWM signal and a parameter to specify the duty cycle. Although, as mentioned in the previous section, the duty cycle is typical specified as a percentage, this function receives a value between 0 and another value different from 100.

In the case of the ESP8266 implementation, we can pass a value between 0 (wave always with a value of GND) and 1023 (wave always with a value of VCC) for the duty cycle. Nevertheless, this range can be changed with a call to the analogWriteRange function [2].

analogWriteRange(range);

For the Arduino implementation of most boards, we can only define a value between 0 and 255 for the duty cycle [3], which is a lower resolution than for the ESP8266. Nevertheless, for some boards such as the Arduino Due, we can call the AnalogWriteResolution function to increase this resolution.

Other difference is that we need to call the AnalogWrite function with a value of 0 for the duty cycle in order to disable the PWM on that pin, in the case of the ESP8266.

analogWrite(pin,0);

If we don’t do it, the next calls to the digitalWrite function on that pin will not work. On the contrary, for Arduino boards implementation, a call to digitalWrite will disable PWM on that pin [3].

As for the frequency of the square wave produced on the ESP8266, the default value is 1KHz. Nevertheless, we can change it with a call to the analogWriteFreq function.

analogWriteFreq(frequency);

For the Arduino implementation, the frequency depends on the board used [3].

Related content

References

[1] http://www.embedded.com/electronics-blogs/beginner-s-corner/4023833/Introduction-to-Pulse-Width-Modulation

[2] https://github.com/esp8266/Arduino/blob/master/doc/reference.md

[3] https://www.arduino.cc/en/Reference/AnalogWrite

Technical details

  • ESP8266 libraries: v2.3.0.

12 thoughts on “ESP8266: Using the PWM technique”

  1. Pingback: ESP8266: Controlling a motor with the ULN2803A | techtutorialsx

  2. Pingback: ESP8266: Controlling a motor with the ULN2803A | techtutorialsx

  3. I’m using a nodemcu, which has an ESP8266, to generate 2 identical PWM signals (32KHz, 30% duty cycle), but I need to phase shift one of them 180º…. how can I do that??

    1. Hi!

      I’ve not played much more with the ESP pwm, I’m not sure how you can do more advanced stuff such as phase shifts.

      My suggestion is that you ask around at the ESP8266 git repository.

      Best regards,
      Nuno Santos

  4. I’m using a nodemcu, which has an ESP8266, to generate 2 identical PWM signals (32KHz, 30% duty cycle), but I need to phase shift one of them 180º…. how can I do that??

    1. Hi!
      I’ve not played much more with the ESP pwm, I’m not sure how you can do more advanced stuff such as phase shifts.
      My suggestion is that you ask around at the ESP8266 git repository.
      Best regards,
      Nuno Santos

  5. Hi,
    I tried to generate an pwm with 5 hz frequency but not morks.

    I tried many example.

    I set to:
    void setup(){
    analogWriteFreq(5);
    }

    without any result

    can I help me please ?

    1. Hi!

      I’ve not been working with the ESP8266 in a while, unfortunately I don’t recall if there was a minimum value that we can use .

      But what are you experiencing? Are you analyzing the wave on an oscilloscope?

      My suggestion is to task around the Arduino for the ESP8266, someone there will surely be able to confirm if there is some limitation 🙂

      Best regards,
      Nuno Santos

  6. Hi,
    I tried to generate an pwm with 5 hz frequency but not morks.
    I tried many example.
    I set to:
    void setup(){
    analogWriteFreq(5);
    }
    without any result
    can I help me please ?

    1. Hi!
      I’ve not been working with the ESP8266 in a while, unfortunately I don’t recall if there was a minimum value that we can use .
      But what are you experiencing? Are you analyzing the wave on an oscilloscope?
      My suggestion is to task around the Arduino for the ESP8266, someone there will surely be able to confirm if there is some limitation 🙂
      Best regards,
      Nuno Santos

  7. I think the lower limit on analogWrite() is 100Hz, but startWaveform() doesn’t have that limit:
    startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t runTimeUS);
    For 5Hz a minimum sketch would be

    #include

    void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    startWaveform(LED_BUILTIN, 100000, 100000, 0);
    }

    void loop() {
    yield();
    }

Leave a Reply

Discover more from techtutorialsx

Subscribe now to keep reading and get access to the full archive.

Continue reading