ESP32 控制舵机
这里舵机的工作电压为5v,而esp32的最大供电电压为3.6v,所以不能使用esp32直接进行供电。这里将家里多余的usb充电线剪开,最好是那种老的两根充电线,插上充电宝或者usb接口,用电压表量一下确定线的正负。我这里选择D13接口,即GPIO13接口。这里特地说明一下为什么ESP32-WROOM-32的GND需要连接usb接口的负极。将舵机的白线接到ESP32-WROOM-32的D13引脚。E
1.硬件准备
首先准备一块ESP32-WROOM-32的电路板以及舵机。然后去网上搜一下该芯片的哪些引脚支持pwm接口。
从图中可以看到所有的GPIO接口都支持pwm输出。我这里选择D13接口,即GPIO13接口。
2.接线连接
舵机是3根线,红黑白,红正黑负白色为信号线。这里将家里多余的usb充电线剪开,最好是那种老的两根充电线,插上充电宝或者usb接口,用电压表量一下确定线的正负。


这里舵机的工作电压为5v,而esp32的最大供电电压为3.6v,所以不能使用esp32直接进行供电。另外还需要考虑电流是否足够,比如电机堵转电流为550mA,而esp32的最大电流可能没有这么大,那一旦电机堵转就很容易烧掉板子。这里我们采用外部独立电源来为舵机进行供电。
接下来进行接线:
ESP32-WROOM-32插上usb转type-c线进行充电和通讯。
将舵机的白线接到ESP32-WROOM-32的D13引脚。
舵机的红正接usb接口的正极,黑负接usb接口的负极。
ESP32-WROOM-32的GND连接usb接口的负极。
这里特地说明一下为什么ESP32-WROOM-32的GND需要连接usb接口的负极。
核心原因:确保电路回路闭合与信号参考电位一致
- 电路回路闭合需求
电流路径:舵机的控制信号(如PWM)由ESP32的GPIO引脚输出,而舵机的电源由外部电源提供。为了形成完整的电流回路,舵机的GND必须与ESP32的GND共地,否则控制信号无法正确传输到舵机。
信号参考电位:所有电气信号(如PWM的高电平)需要共同的参考电位(地电位)。若舵机的GND未与ESP32的GND连接,两者地电位不同,会导致控制信号无法被正确识别。 - 避免电位差导致的信号干扰
电位差问题:若舵机的电源地(外部电源负极)与ESP32的地未连接,两者之间可能存在电位差。这种电位差会导致电流通过信号线流动,干扰PWM信号的准确性,甚至可能损坏ESP32的GPIO引脚。
共地消除电位差:通过共地,确保舵机和ESP32的地电位一致,避免因电位差引起的信号失真或设备损坏。 - 稳定电源供应
电流回流路径:舵机工作时需要较大电流(尤其是启动或负载变化时),外部电源需提供稳定电流。共地确保电流从外部电源正极流入舵机,再通过共地线回到外部电源负极,形成稳定回路。
防止电压波动:若地线未共地,电流回流路径可能不完整,导致电压波动或噪声干扰,影响舵机稳定运行。
3.程序编写
#include <ESP32Servo.h>
Servo myServo;
const int servoPin = 13; // 舵机信号线接GPIO13
const int ledPin = 2; // 状态指示灯(可选
const int minUs = 500; // 最小脉冲宽度(微秒)
const int maxUs = 2500; // 最大脉冲宽度(微秒)
void setup() {
// 初始化LED,2号引脚置为输出模式
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// 初始化默认串口(UART0)
Serial.begin(115200);
while (!Serial) {
; // 等待串口连接(仅对原生USB端口有效)
}
Serial.println("\n ESP32 Serial Servo Control");
Serial.println("Send angle value (0-180) to rotate servo");
// 配置PWM通道0(频率50Hz,分辨率8位)
ledcSetup(0, 50, 8);
ledcAttachPin(servoPin, 0);
// myServo.attach(servoPin);
myServo.attach(servoPin, minUs, maxUs);
myServo.write(90); // 初始位置90°
// 状态指示
digitalWrite(ledPin, HIGH);
delay(200);
digitalWrite(ledPin, LOW);
}
void loop() {
// 检查串口数据
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n'); // 读取直到换行符
input.trim(); // 去除首尾空格/换行符
// 尝试转换为整数
int angle = input.toInt();
angle = (angle/3)*2;
// 验证角度范围
if (angle >= 0 && angle <= 270) {
myServo.write(angle);
delay(2000);
Serial.print("Set angle: ");
Serial.println(angle);
// 状态指示(可选)
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
} else {
Serial.print("Error: Invalid angle ");
Serial.println(angle);
Serial.println("Use 0-180");
}
}
}
更多推荐



所有评论(0)