Pulse Width Modulation, or PWM, is a technique for getting analog results with digital means. Digital control is used to create a square wave, a signal switched between on and off. This on-off pattern can simulate voltages in between full on (5 Volts) and off (0 Volts). The duration of “on time” is called the pulse width. To get varying analog values, you change or modulate, that pulse width. If you repeat this on-off pattern fast enough with an LED, for example, the result is as if the signal is a steady voltage between 0 and 3.3V controlling the brightness. By using PWM technique we can control the speed of servo, dc motors, and control brightness of RGB LEDs and it also used for communication purpose to control the power.
The following waveform shows the PWM signals in different duty cycles.
The Duty cycle is equated as,
The example showing the use of analog output(PWM) to fade an LED. In terms of hardware, the LED PWM of the ESP32 is composed of 16 independent channels, with configurable duty cycles and wave periods. The accuracy of the duty cycle can be configured until 16 bits of resolution.
The commonly used analogWrite() Arduino function was not yet available for the ESP32 Arduino environment support.
int freq = 1000; int ledChannel = 0; int resolution = 16; int dutyCycle = 0;
A PWM signal to be generated is its frequency. Here we will use a value of 1000 Hz, that works fine with the LED. We must also specify the LED PWM channel and the resolution of the PWM duty cycle, in bits. We can choose a channel from 0 to 15 and a resolution between 1 and 16 bits. Here we will use channel 0 and a resolution of 16 bits.
ESP32 board has a built-in LED on pin D9. Pin D9 corresponds to pin 2 of the ESP32 microcontroller.
#define LED_PIN 2
configure the LED PWM functionality by set up the channel, frequency, and resolution as specified. To do so, we call the ledcSetup function, which receives as input the 3 previously mentioned parameters, in the same order.
ledcSetup(ledChannel, freq, resolution);
To attach the pin to the PWM channel, we call the ledcAttachPin function, passing as arguments the number of the GPIO pin and the PWM channel previously defined.
ledcAttachPin(LED_PIN, ledChannel);
ledcWrite function specifies the duty cycle value. Since we defined a 16 bits resolution, we can specify a duty cycle value between 0 and 32767(2^16 -1). So, we will iterate between these values in two loops, one ascending and other descending.which already includes the call for the ledcWrite function and these two loops.
dutyCycle = map(analog_value, 0, 4095, 0, 32767); ledcWrite(ledChannel, dutyCycle);
ESP32 ADCs have 12bits of resolution.so the total range of ADCs reading go to 4,095.
map()-Remaps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of fromHigh to toHigh, values in-between to values in-between, etc.analog_value is the number to map.