I'm trying to control a brushless motor from an ESP32-devkit-v1 with an ESC with BLHeli S firmware. I've watched a LOT of videos, manuals, ChatGPT, etc., with no success. The following code got me at least a musical response from the ESC: the three-note startup chime twice, a low tone, a double high tone, and then four quick ascending tones repeat for a while. I've tried using DShot, too, without success. If anyone can point out what I'm missing or point me toward a resource that can help, that would be awesome.
Auxiliary info: The esp32 is connected and powered by my computer. The ESC is powered by a spare 60w desktop PSU; I cut a Molex connector off and connected the 12v wire and ground to the ESC, although the PSU only delivers about 10.5v. It's pretty stable, tho, so I don't think that's an issue.
#include <Arduino.h>
// GPIO pin for ESC signal
const int escPin = 18;
// PWM configuration
const int freq = 50; // 50 Hz for ESC control
const int resolution = 16; // 16-bit resolution
const int channel = 0; // PWM channel
void setThrottle(int dutyCycle);
void calibrateESC();
void setup() {
// Initialize serial communication
Serial.begin(115200);
Serial.println("Initializing ESC...");
// Configure the PWM channel
ledcSetup(channel, freq, resolution);
ledcAttachPin(escPin, channel);
// Send initial ESC calibration signals
calibrateESC();
}
void loop() {
// Example: Gradually increase motor speed
Serial.println("Increasing throttle...");
for (int dutyCycle = 1000; dutyCycle <= 2000; dutyCycle += 100) {
setThrottle(dutyCycle);
delay(500);
}
Serial.println("Stopping motor...");
setThrottle(1000); // Stop the motor
delay(2000);
}
void calibrateESC() {
Serial.println("Calibrating ESC...");
setThrottle(2000); // Maximum throttle
delay(2000); // Wait for ESC to recognize max throttle
setThrottle(1000); // Minimum throttle
delay(2000); // Wait for ESC to arm
Serial.println("ESC calibration complete.");
}
void setThrottle(int dutyCycle) {
// Map 1000-2000 µs to 16-bit resolution
int pwmValue = map(dutyCycle, 1000, 2000, 0, 65535);
ledcWrite(channel, pwmValue);
}
I don't know if you already solved this issue. I just got mine working. For anyone else that might have the same issue. The following code works. It goes from 0 (1000ms pw) to 5% (1050ms pw).
One thing that I found is that not every pin on my ESP32 Dev kit v1 can be used. It's also important that the ESC gnd is connected to the ESP32.
The code:
#include <Arduino.h>
#include <ESP32Servo.h>
const int ESC_PIN = 13; // GPIO pin connected to the ESC
const int MIN_THROTTLE = 1000; // Minimum throttle (1ms pulse width)
const int MAX_THROTTLE_5_PERCENT = 1050; // Maximum throttle at 5% (1.05ms pulse width)
const int FREQUENCY = 50; // 50Hz frequency for ESC
// Initialize the Servo object for ESC control
Servo escServo;
void setup() {
// Start Serial communication for debugging
Serial.begin(115200);
Serial.println("Starting PWM control using ESP32Servo...");
// Attach the ESC to the specified GPIO pin
escServo.setPeriodHertz(FREQUENCY); // Set frequency to 50Hz
escServo.attach(ESC_PIN, MIN_THROTTLE, MAX_THROTTLE_5_PERCENT); // Attach to the ESC pin
// Initial throttle setting (this will arm the ESC if it's idle)
Serial.println("Sending minimum throttle for arming sequence...");
escServo.writeMicroseconds(MIN_THROTTLE); // Minimum throttle to arm the ESC
delay(2000); // Wait for arming sequence
// Send zero throttle value to complete arming sequence
Serial.println("Sending zero throttle to complete the arming sequence...");
escServo.writeMicroseconds(MIN_THROTTLE); // Zero throttle
delay(1000); // Allow ESC to register the zero throttle
// Send zero throttle again (or fail-safe throttle if desired)
Serial.println("Sending zero throttle again.");
escServo.writeMicroseconds(MIN_THROTTLE); // Zero throttle again
}
void loop() {
// You can implement logic to gradually increase or decrease the throttle here
// Example: Ramp up throttle from min to 5% max
// Ramp up throttle from minimum to 5% of maximum (1600 µs)
for (int pulse = MIN_THROTTLE; pulse <= MAX_THROTTLE_5_PERCENT; pulse += 10) {
escServo.writeMicroseconds(pulse);
Serial.print("Throttle: ");
Serial.println(pulse);
delay(100); // Ramp up slowly
}
delay(2000); // Hold throttle for 2 seconds
// Ramp down throttle from 5% of maximum to minimum
for (int pulse = MAX_THROTTLE_5_PERCENT; pulse >= MIN_THROTTLE; pulse -= 10) {
escServo.writeMicroseconds(pulse);
Serial.print("Throttle: ");
Serial.println(pulse);
delay(50); // Ramp down slowly
}
delay(2000); // Hold minimum throttle for 2 seconds
}
The serial log:
Throttle: 1030
Throttle: 1040
Throttle: 1050
Throttle: 1050
Throttle: 1040
Throttle: 1030
Throttle: 1020
Throttle: 1010
Throttle: 1000
Edit:
Depending on you ESC 1050
for the max throttle might not be high enough. I have a 4 in 1 ESC board. Two of the ESCs were configured so the firmware would ignore anything below 1121
. I would recommend checking the firmware with something like BLHeliSuite or esc-configurator.com to she what the min values have to be. Also while you're in there make sure every ESC has the same value. (assuming you haven't done any calibiration).