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接口的负极。
核心原因:确保电路回路闭合与信号参考电位一致

  1. 电路回路闭合需求
    电流路径:舵机的控制信号(如PWM)由ESP32的GPIO引脚输出,而舵机的电源由外部电源提供。为了形成完整的电流回路,舵机的GND必须与ESP32的GND共地,否则控制信号无法正确传输到舵机。
    信号参考电位:所有电气信号(如PWM的高电平)需要共同的参考电位(地电位)。若舵机的GND未与ESP32的GND连接,两者地电位不同,会导致控制信号无法被正确识别。
  2. 避免电位差导致的信号干扰
    电位差问题:若舵机的电源地(外部电源负极)与ESP32的地未连接,两者之间可能存在电位差。这种电位差会导致电流通过信号线流动,干扰PWM信号的准确性,甚至可能损坏ESP32的GPIO引脚。
    共地消除电位差:通过共地,确保舵机和ESP32的地电位一致,避免因电位差引起的信号失真或设备损坏。
  3. 稳定电源供应
    电流回流路径:舵机工作时需要较大电流(尤其是启动或负载变化时),外部电源需提供稳定电流。共地确保电流从外部电源正极流入舵机,再通过共地线回到外部电源负极,形成稳定回路。
    防止电压波动:若地线未共地,电流回流路径可能不完整,导致电压波动或噪声干扰,影响舵机稳定运行。

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");
    }
  }
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐