Hi guys and gals!
I'm trying to control a servo motor with an ESP32 based development board, specifically a LOLIN32 Lite. The servos I'm using (SG90 and MG90S) both claim to move through 180 degrees of motion with a standard 50Hz square wave control signal, with the high pulse width ranging from 1.0mS to 2.0mS, but for me to get the full 180 degrees of motion, I had to modify my program so that the high pulse width ranges from 0.48mS to 2.24mS.
I know that the standard Arduino way to control servers is to use servo.h, but apparently this is not supported by the ESP32, but I had recently written my own version of analogWrite(), which I call analogWriteESP32(), and I used this to generate the PWM signal. I measured this PWM signal on an oscilloscope, and both the original and modified pulse widths were exactly as expected.
One thought I had was that the problem might be due to the LOLIN32 Lite board being powered by 3.3V while the servo is being powered by 5V, but I ran my control signal through a DRV8833 motor driver module to bring it up to a full 5V signal, and that didn't seem to change anything.
I'm somewhat suspicious about my servos. I bought them on AliExpress, so although they're labeled as Tower Pro, there's a decent chance that they're counterfeit. However, both of them work exactly the same, even though they're different models.
Any ideas what's going on?
A.J.
BTW, the code is a modified version of the program on pp. 85-86 of Jeremy Blum's "Exploring Arduino" (2013).
// Exploring04-04
// Servo Potentiometer Control
// Arduino: LOLIN32 Lite (with ESP32)
// #include <Servo.h> This is not implemented for the ESP32, so the servo pulse has
// to be controlled directly using the analogWriteESP32() function below.
// The following array and two functions are needed because the analogWrite() function
// is not implemented for the ESP32.
int pin2channel[64]; // holds the PWM channel (0-15) attached to a given pin (0-63)
void setupAnalogWritePin(int pin, int channel, int freq=500, int resolution=8)
// The default values freq=500 and resolution=8 are used for compatibility with the
// Arduino UNO, which generates PWM signals at 500Hz and 8 bit resolution.
{
ledcSetup(channel, freq, resolution);
pin2channel[pin] = channel;
ledcAttachPin(pin, pin2channel[pin]);
ledcWrite(channel, 0);
}
void analogWriteESP32(int pin, int value)
{
ledcWrite(pin2channel[pin], value);
}
const int SERVO = 18; // Pin to control (pulse) servo
const int SERVO_CHANNEL = 0; // 0-15
const int SERVO_FREQ = 50; // 50Hz
const int SERVO_RES = 16; // 16 bit resolution
const int POT = 34; // Pin to middle tap of pot
const int MIN_PULSE = 1575; // 0.48mS previously 0xFFFF/20 for 1.0mS
const int MAX_PULSE = 7335; // 2.24mS previously 0xFFFF/10 for 2.0mS
int val = 0; // For storing the reading from the POT
void setup()
{
setupAnalogWritePin(SERVO, SERVO_CHANNEL, SERVO_FREQ, SERVO_RES);
}
void loop()
{
val = analogRead(POT); // ESP32's A/D varies from 0-4095 (12 bits)
// instead of 0-1023 (10 bits).
val = map(val, 0, 4095, MIN_PULSE, MAX_PULSE); // Scale A/D value to servo range
analogWriteESP32(SERVO, val); // Set the servo
delay(15);
}