Hello readers, I hope you all are doing great. Welcome to the 3rd Lecture of Section 2 in the ESP32 Programming Series. In this tutorial, we are going to discuss another important feature of ESP32 i.e. PWM(Pulse Width Modulation).
Pulse Width Modulation is a technique to reduce the voltage by pulsating it. In today's lecture, we will first understand the basic concept of PWM, and after that will design two projects to fully grasp it. In the first project, we will control the brightness of an LED, while in the second one, we will control the speed of a DC Motor.
Before going forward, let's first have a look at the PWM working:
Where To Buy? | ||||
---|---|---|---|---|
No. | Components | Distributor | Link To Buy | |
1 | ESP32 | Amazon | Buy Now |
PWM is used to control the power delivered to the load by pulsating the ON-Time of the voltage pulse, without causing any power loss. Let's understand the PWM concept with the help of below image:
Suppose a DC Motor runs at 200RPM over 5V. Now, if we want to reduce its speed to 100 RPM, we need to reduce its input voltage to 2.5V(approx). So, either we can replace the 5V battery with a 2.5V Battery or use a PWM circuit to reduce the voltage level from 5V to 2.5V. In this specific case, the PWM pulse will be ON for 50% of the time and get OFF for the remaining 50% of the time.
The behavior of the PWM signal is determined by the following factors:
As you can see in the below figure, we have taken two signals for a duration of 1 second. The first signal completes 10 Cycles in 1 second, so we can say it has a frequency of 10Hz, while the second one has a frequency of 5Hz as it completes 5 cycles in 1 second. So, I hope now it's clear that the number of cycles per second is the frequency of a signal.
Duty Cycle is the ratio of ON time(when the signal is high) to the total time taken to complete the cycle. The duty cycle is represented in the form of a percentage (%) or ratio. Let's understand the PWM Duty Cycle with the help of below image:
The resolution of a PWM signal defines the number of steps it can have from zero power to full power. The resolution of the PWM signal is configurable for example, the ESP32 module has a 1-16 bit resolution, which means we can configure maximum a of 65536 (2^16) steps from zero to full power.
In the ESP WROOM-32 module, there are 16 PWM channels. All the channels are divided into two groups containing 8 channels in each group. The resolution can be programmed between 1 to 16 bits and frequency also depends upon the programmed resolution of the PWM signal.
Now
For the demonstration of PWM in ESP32 we are going to explain two examples:
We are using Arduino IDE to compile and upload the code into the ESP WROOM-32 board.
// Global variable declaration to set PWM properties
const int ledChannel = 0; // select channel 0
const int resolution = 8; //8-bit resolutin i.e., 0-255
const int frequency = 5000; // set frequency in Hz
int dutyCycle = 0;
void setup()
{
Serial.begin(115200);
ledcSetup(ledChannel, frequency, resolution); // configure LED PWM functionalities
ledcAttachPin(LED_BUILTIN, ledChannel); // attach the channel to the GPIO to be controlled
}
void loop()
{
while(dutyCycle <200)
{
ledcWrite(ledChannel, dutyCycle++); // changing the LED brightness with PWM
Serial.print(" duty Cycle ++ :");
Serial.println(dutyCycle); // display the duty cycle on serial monitor
delay(5);
}
while(dutyCycle>0)
{
ledcWrite(ledChannel, dutyCycle--); // changing the LED brightness with PWM
Serial.print(" duty Cycle -- :");
Serial.println(dutyCycle); // display the duty cycle on serial monitor
delay(5);
}
}
// Global variable declaration to set PWM properties
const int ledChannel = 0; // select channel 0
const int resolution = 8; //8-bit resolutin i.e., 0-255
const int frequency = 5000; // set frequency in Hz
int dutyCycle = 0;
Serial.begin(115200);
ledcSetup(ledChannel, frequency, resolution); // configure LED PWM functionalities
ledcAttachPin(LED_BUILTIN, ledChannel); // attach the channel to the GPIO to be controlled
while(dutyCycle <200)
{
ledcWrite(ledChannel, dutyCycle++); // changing the LED brightness with PWM
Serial.print(" duty Cycle ++ :");
Serial.println(dutyCycle); // display the duty cycle on serial monitor
delay(5);
}
while(dutyCycle>0)
{
ledcWrite(ledChannel, dutyCycle--); // changing the LED brightness with PWM
Serial.print(" duty Cycle -- :");
Serial.println(dutyCycle); // display the duty cycle on serial monitor
delay(5);
}
Fig. 9 Serial plotter PWM output
Fig. 10
In this example, we are going to implement PWM using ESP WROOM-32 to control the speed of a DC motor.
The speed of the DC motor depends upon the input power supply. So, by varying the power input we can also vary (increase or decrease) the speed of DC motor.
Hardware components required:
L298N motor driver: A motor driver is used between the ESP32 board and DC motor to resolve the power compatibility issues.
Both the ESP32 board and DC motor operate at different power ratings due to which you can not connect the two devices directly. So a motor driver is used to receive a low power input from the ESP32 board and drive/run DC motor at slightly high power.
L298N can drive a DC motor that operated between 5 to 35 voltage range and maximum current of 2A.
There are various DC motor drivers available in the market for example L293D, DRV8833, MAX14870 single brushed motor driver etc. You can choose the driver of your choice depending upon the application and power ratings.
Fig. 11
FIG. 12 IC L298N pin-out
IN_1 | IN_2 | Rotation |
HIGH | LOW | DC motor rotates in a clockwise direction |
LOW | HIGH | The motor rotates in an anti-clockwise direction |
LOW | LOW | Motor STOP |
HIGH | HIGH | Motor STOP |
Table 1
//configure GPIO pins to connect motor driver
int enable1Pin = 14;
int M_Pin1 = 26;
int M_Pin2 = 27;
// Setting PWM properties
const int freq = 10000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 150;
void setup()
{
Serial.begin(115200);
// sets the pins as outputs:
pinMode(M_Pin1, OUTPUT);
pinMode(M_Pin2, OUTPUT);
pinMode(enable1Pin, OUTPUT);
//Configure LED PWM functionalities
ledcSetup(pwmChannel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(enable1Pin, pwmChannel);
Serial.print("Testing DC Motor...");
}
void loop()
{
// Move the DC motor in anti-clockwise direction at maximum speed
Serial.println("Moving reverse");
digitalWrite(M_Pin1, LOW);
digitalWrite(M_Pin2, HIGH);
delay(500);
// Move DC motor forward with increasing speed
Serial.println("Moving Forward");
digitalWrite(M_Pin1, HIGH);
digitalWrite(M_Pin2, LOW);
//----while loop----
while (dutyCycle <= 255)
{
ledcWrite(pwmChannel, dutyCycle);
Serial.print("Speed increasing with duty cycle: ");
Serial.println(dutyCycle);
dutyCycle = dutyCycle +5;
delay(100);
}
while (dutyCycle >150)
{
ledcWrite(pwmChannel, dutyCycle);
Serial.print("Speed decreasing with duty cycle: ");
Serial.println(dutyCycle);
dutyCycle = dutyCycle -5;
delay(100);
}
// _____Stop the DC motor
Serial.println("STOP DC motor");
digitalWrite(M_Pin1, LOW);
digitalWrite(M_Pin2, LOW);
delay(500);
}
//configure GPIO pins to connect motor driver
int enable1Pin = 14;
int M_Pin1 = 26;
int M_Pin2 = 27;
// Setting PWM properties
const int freq = 10000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 150;
Serial.begin(115200);
// sets the pins as outputs:
pinMode(M_Pin1, OUTPUT);
pinMode(M_Pin2, OUTPUT);
pinMode(enable1Pin, OUTPUT);
//Configure LED PWM functionalities
ledcSetup(pwmChannel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(enable1Pin, pwmChannel);
Fig. 20
Fig. 21 Increasing speed
Fig. 22 Reducing speed
Fig. 23 STOP DC motor
Fig. 24 PWM output on serial monitor
Fig. 25 PWM output on Serial Plotter
This concludes the tutorial. I hope you found this useful, and I hope to see you soon for the new ESP32 tutorial.