Let's control a Servo Motor using the PWM capability of our ESP32. The code will be basically the same one that was used to control the LED brightness.
First, it's important to remember that the frequency to work with a Micro Servo is 50Hz, so we must change the frequency parameter to 50 (instead of 5,000 used with LED). We must also specify the LED PWM channel and the resolution of the PWM duty cycle, in bits. We will use again channel 0 and a resolution of 8 bits.
int freq = 50; int channel = 0; int resolution = 8;
The Servo will be connected to GPIO 5 (see above electrical diagram).
#define SERVO_PIN 5
Same as with LED, those parameters must be defined during setup() phase, using below functions:
void setup()
{
ledcSetup(channel, freq, resolution);
ledcAttachPin(SERVO_PIN, channel);
}
To position the servo on a specific angle, we must define the "duty cycle" (please, see the above diagram).
For example, to position the servo around 90 degrees, the duty cycle must be around 21 and the function ledcWrite(ledChannel, dutyCycle) should be used to send the value thru the PWM channel:
int dutyCycle = 21; ledcWrite(channel, dutyCycle);
Different values of the dutyCycle variable will position the servo with different angles. This variable, dutyCycle, should vary from 10 to 32 (this range was gotten manually).
Same as we did with the LED, the Potentiometer (connected to analog_value variable) can be used to manually setup the dutyCycle variable and so, changing the servo position. Once their ranges of values are different, let's use a map function to match input and output:
dutyCycle = map(analog_value, 0, 4095, 10, 33);
Below the complete code:
/*****************************************************
* ESP32 Servo Control
* Analog Input: ADC_1_0 pin ==> GPIO36 (VP).
* PWM SERVO pin ==> GPIO 05
*
* MJRoBot.org 6Sept17
*****************************************************/
//Analog Input
#define ANALOG_PIN_0 36
int analog_value = 0;
// PMW SERVO
#define SERVO_PIN 5
int freq = 50;
int channel = 0;
int resolution = 8;
int dutyCycle = 21;
void setup()
{
Serial.begin(115200);
delay(1000); // give me time to bring up serial monitor
Serial.println("ESP32 Servo Control");
ledcSetup(channel, freq, resolution);
ledcAttachPin(SERVO_PIN, channel);
ledcWrite(channel, dutyCycle);
}
void loop()
{
analog_value = analogRead(ANALOG_PIN_0);
Serial.print(analog_value);
Serial.print(" Duty Cycle ==> ");
Serial.println(dutyCycle);
dutyCycle = map(analog_value, 0, 4095, 10, 33);
ledcWrite(channel, dutyCycle);
delay(50);
}