如何使用 Arduino 控制伺服电机 – 完整指南
在本教程中,我们将了解伺服电机的工作原理 以及如何使用 Arduino 控制伺服电机 .伺服电机非常受欢迎,并在许多 Arduino 项目中广泛使用,因为它们易于使用并提供出色的位置控制。
伺服系统是机器人项目、自动化、RC 模型等的绝佳选择。我已经在我的许多 Arduino 项目中使用了它们,您可以在这里查看其中的一些:
您可以观看以下视频或阅读下面的书面教程。它包括几个如何使用带有 Arduino 的伺服电机的示例、接线图和代码。此外,它还提供了如何使用 Arduino 使用 PCA9685 PWM 驱动器控制多个伺服电机的指南。
伺服电机是一个闭环系统,它使用位置反馈来控制其运动和最终位置。伺服电机种类繁多,主要特点是能够精确控制其轴的位置。
在工业型伺服电机中,位置反馈传感器通常是高精度编码器,而在较小的 RC 或业余伺服电机中,位置传感器通常是简单的电位器。这些设备捕获的实际位置被反馈到误差检测器,并与目标位置进行比较。然后控制器根据误差修正电机的实际位置,使其与目标位置相匹配。
在本教程中,我们将详细介绍爱好伺服电机。我们将解释这些舵机的工作原理以及如何使用 Arduino 控制它们。
Hobby 舵机是用于控制 RC 玩具汽车、船、飞机等的小型执行器。工科学生也使用它们来进行机器人原型设计、制造机械臂、仿生机器人、仿人机器人等。
爱好伺服内部有四个主要组件,直流电机,变速箱,电位器和控制电路。直流电机是高速低扭矩的,但齿轮箱将速度降低到 60 RPM 左右,同时增加扭矩。
电位器安装在末级齿轮或输出轴上,因此随着电机旋转,电位器也随之旋转,从而产生与输出轴绝对角度相关的电压。在控制电路中,该电位器电压与来自信号线的电压进行比较。如果需要,控制器会激活一个集成的 H 桥,使电机能够向任一方向旋转,直到两个信号达到零差。
通过信号线发送一系列脉冲来控制伺服电机。控制信号的频率应为 50Hz 或每 20ms 出现一个脉冲。脉冲宽度决定舵机的角位置,这类舵机通常可以旋转 180 度(它们有行程的物理限制)。
一般来说,1ms 持续时间的脉冲对应 0 度位置,1.5ms 持续时间对应 90 度,2ms 对应 180 度。虽然脉冲的最小和最大持续时间有时会因不同品牌而异,0度位置为0.5ms,180度位置为2.5ms。
RC 或爱好有许多不同的型号和制造商。选择伺服电机的主要考虑因素是其扭矩、工作电压、电流消耗和尺寸。
以下是制造商中最受欢迎的两种伺服型号,SG90 Micro Servo 和 MG996R。
SG90微伺服 技术规格:
MG996R 伺服 技术规格:
让我们将上述内容进行测试并制作一个使用Arduino控制爱好伺服的实际示例。我将使用 MG996R,这是一款高扭矩伺服系统,具有金属齿轮,失速扭矩为 10 kg-cm。高扭矩是有代价的,即伺服的失速电流为 2.5A。运行电流500mA~900mA,工作电压4.8~7.2V。
目前的额定值表明我们不能将此伺服直接连接到Arduino,但我们必须为其使用单独的电源。
这是这个例子的电路图。
我们只需要将舵机的控制管脚连接到Arduino板的任意一个数字管脚,将地线和正极线连接到外部5V电源,并将Arduino地线连接到舵机地。
如果我们使用更小的爱好伺服,S90 Micro Servo,可以直接从 5V Arduino 引脚为其供电。
S90 微伺服的电流消耗较低,空载运行电流约为 100-200mA,但失速电流约为 500-700mA。另一方面,如果通过 USB 供电,Arduino 5V 引脚只能输出 500mA 左右的电流,而通过桶形连接器供电时最高可以输出 1A。
尽管这些 9g 伺服电机可以直接运行到 Arduino,但为了更稳定的工作,我建议始终为它们使用外部电源。
您可以从以下链接获取此示例所需的组件:
现在让我们看一下控制伺服电机的 Arduino 代码。代码非常简单。我们只需要定义伺服连接的引脚,将该引脚定义为输出,并在循环部分生成具有特定持续时间和频率的脉冲,如前所述。
经过一些测试,我想出了以下值,用于与我的伺服一起工作的脉冲持续时间。 0.6ms脉冲对应0度位置,1.45ms对应90度,2.3ms对应180度。
我将万用表与伺服串联连接以检查电流消耗。我注意到的最大电流消耗在失速时高达 0.63A。那是因为这不是原来的 TowerPro MG996R 舵机,而是更便宜的复制品,显然性能更差。
不过,让我们看一下使用 Arduino 控制舵机的更方便的方法。那是使用 Arduino 伺服库。
在这里,我们只需要包含库,定义伺服对象,并使用 attach() 函数定义伺服连接的引脚以及定义脉冲持续时间的最小值和最大值。然后使用 write() 函数,我们只需将舵机的位置设置为 0 到 180 度。
Arduino 伺服库支持使用大多数 Arduino 板同时控制多达 12 个伺服器,使用 Arduino Mega 板可同时控制 48 个伺服器。最重要的是,使用 Arduino 控制多个伺服电机就像控制一个伺服电机一样简单。
下面是一个控制多个舵机的示例代码:
因此,我们只需为每个伺服电机从 Servo 类创建对象,并定义连接到哪个 Arduino 引脚。当然,我们可以设置任意舵机随时移动到任意位置。
例如,您还可以查看我的 Arduino Ant Hexapod Robot 项目,其中我使用 Arduino MEGA 板来控制 22 个伺服电机。
还有另一种使用 Arduino 控制伺服的方法,那就是使用 PCA9685 伺服驱动器。这是一个 16 通道 12 位 PWM 和伺服驱动器,它使用 I2C 总线与 Arduino 通信。它有一个内置时钟,因此它可以驱动 16 个伺服器自由运行,或独立于 Arduino。
更酷的是,我们可以在单个 I2C 总线上以菊花链方式连接多达 62 个这些驱动程序。所以理论上我们可以只使用 Arduino 板上的两个 I2C 引脚来控制多达 992 个舵机。 6 个地址选择引脚用于为每个附加驱动器设置不同的 I2C 寻址。我们只需要按照这张表连接焊盘即可。
这是电路原理图,我们可以再次注意到我们需要为舵机提供单独的电源。
您可以从以下链接获取此示例所需的组件:
现在让我们看一下Arduino代码。为了控制这个伺服驱动器,我们将使用可以从 GitHub 下载的 PCA9685 库。
所以首先我们需要包含库并定义 PCA9685 对象。然后使用 Servo_Evaluator 实例定义驱动器的脉冲持续时间或 PWM 输出。请注意,输出是 12 位的,或者是 4096 步的分辨率。因此,0.5ms 或 0 度位置的最小脉冲持续时间对应 102 步,而 2.5ms 或 180 度位置的最大脉冲持续时间对应 512 步。但如前所述,这些值应根据您的伺服电机进行调整。我的值从 102 到 470 对应于 0 到 180 度的位置。
在设置部分我们需要定义I2C时钟频率,设置驱动地址,设置频率为50Hz。
在循环部分,使用 setChannelPWM() 和 pwmForAngle() 功能我们只需将伺服设置为所需的角度。
我将第二个伺服器连接到驱动器,正如我所料,它的定位与第一个不同,那是因为我使用的伺服器是廉价副本,它们不太可靠。但是,这不是什么大问题,因为使用 Servo_Evaluator 例如,我们可以为每个伺服设置不同的输出设置。我们还可以调整 90 度位置,以防它不在中间。这样一来,所有舵机的工作方式都相同,并以准确的角度定位。
我们将再看一个示例,它使用多个链接的 PCA9685 驱动器控制大量伺服系统。
为此,我们需要将驱动器相互连接并连接适当的地址选择焊盘。电路原理图如下:
现在让我们看一下Arduino代码。
所以我们应该为每个驱动程序创建单独的 PCA9685 对象,定义每个驱动程序的地址并将频率设置为 50Hz。现在只需使用 setChannelPWM() 和 pwmForAngle() 函数,我们就可以在任何驱动器上设置任何伺服来定位我们想要的任何角度。
这是这些爱好伺服电机 SG90 Micro Servo 和 MG996R 的常见问题。这样做的原因是,如前所述,它们在负载时会消耗相当大的电流。这可能会导致 Arduino 板重置,尤其是当您直接从 Arduino 5V 引脚为伺服供电时。
为了解决这个问题,您可以在 GND 和 5V 引脚之间使用一个电容器。它将充当去耦电容器,在直流电机启动时为系统提供额外的电流。
这是这些爱好伺服器的另一个常见问题。正如我们前面所解释的,1ms(0.5ms)的脉冲宽度对应于 0 度位置,2ms(2.5ms)对应于 180 度。但是,这些值可能因伺服和不同制造商而异。
为了解决这个问题,我们需要用 Arduino 调整发送到伺服电机的脉冲宽度。幸运的是,使用 Arduino Servo 库,我们可以轻松地调整 attach() 中的脉冲宽度值 功能。
attach() 函数可以采用两个附加参数,即最小和最大脉冲宽度(以微秒为单位)。最小(0 度)角度的默认值为 544 微秒(0.544 毫秒)和 2400 微秒(2.4 毫秒)。所以通过调整这些值我们可以微调舵机的力矩范围。
我制作了两种最流行的伺服电机 SG90 Micro Servo 和 MG996R 伺服电机的 3D 模型。您可以从下面的链接下载加载它们。
3D模型:从Thangs下载。
尺寸:
MG996R伺服电机3D模型:从Thangs下载。
尺寸:
因此,我们几乎涵盖了我们需要了解的关于在 Arduino 中使用伺服电机的所有信息。当然,这类爱好或RC伺服电机的制造商和型号有很多,它们每个都有自己独特的特点,可能与我们上面解释的不同。
使用电机创建出色的机器人、自动化和 RC 项目的可能性是无穷无尽的,但是为您的应用选择正确的模型非常重要。
我希望你喜欢这个教程并学到了一些新东西。随时在下面的评论部分提出任何问题,并确保您可以我的 Arduino 项目集合。
使用带有 Arduino 的伺服电机非常容易。伺服电机只有 3 根线,其中 2 根是 GND 和 5V 用于供电,第三根是连接到 Arduino 板的控制线。
我们可以直接从 Arduino 运行伺服电机,但我们可能会遇到电源问题。如果伺服电机消耗超过 500mA 的电流,Arduino 板可能会断电并复位。伺服电机最好始终使用单独的电源。
使用 Arduino Servo 库,我们可以使用大多数 Arduino 板控制多达 12 个伺服电机,使用 Arduino Mega 板控制多达 48 个伺服电机。当然,我们需要为伺服电机使用专用电源。
什么是伺服电机?
伺服电机的工作原理?
适用于 Arduino 项目的流行 RC/爱好伺服系统
图> 失速扭矩 1.2kg·cm @4.8V, 1.6kg·cm @6V, 工作电压 3.5 – 6V 当前无负载 100mA 停滞当前 650mA 最大速度 60 度在 0.12 秒内 权重 9g
图> 失速扭矩 11kg.cm @4.8v, 13kg.cm @6V 工作电压 4.8 – 7.2V 当前无负载 220mA @4.8V, 250mA @6V 停滞当前 650mA 最大速度 60 度在 0.20 秒内 权重 55g Arduino 伺服电机控制
电路图
伺服电机控制Arduino代码
/*
Servo Motor Control - 50Hz Pulse Train Generator
by Dejan, https://howtomechatronics.com
*/
#define servoPin 9
void setup() {
pinMode(servoPin, OUTPUT);
}
void loop() {
// A pulse each 20ms
digitalWrite(servoPin, HIGH);
delayMicroseconds(1450); // Duration of the pusle in microseconds
digitalWrite(servoPin, LOW);
delayMicroseconds(18550); // 20ms - duration of the pusle
// Pulses duration: 600 - 0deg; 1450 - 90deg; 2300 - 180deg
}
Code language: Arduino (arduino)/*
Servo Motor Control using the Arduino Servo Library
by Dejan, https://howtomechatronics.com
*/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
void setup() {
myservo.attach(9,600,2300); // (pin, min, max)
}
void loop() {
myservo.write(0); // tell servo to go to a particular angle
delay(1000);
myservo.write(90);
delay(500);
myservo.write(135);
delay(500);
myservo.write(180);
delay(1500);
}
Code language: Arduino (arduino)使用 Arduino 控制多个伺服电机
/*
Controlling multiple servo motors with Arduino
by Dejan, https://howtomechatronics.com
*/
#include <Servo.h>
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;
void setup() {
servo1.attach(8);
servo2.attach(9);
servo3.attach(10);
servo4.attach(11);
servo5.attach(12);
}
void loop() {
// move all servos to position 0
servo1.write(0);
servo2.write(0);
servo3.write(0);
servo4.write(0);
servo5.write(0);
delay(2000);
// move all servos to position 90
servo1.write(90);
servo2.write(90);
servo3.write(90);
servo4.write(90);
servo5.write(90);
delay(2000);
// move all servos to position 180
servo1.write(180);
servo2.write(180);
servo3.write(180);
servo4.write(180);
servo5.write(180);
delay(2000);
}
Code language: Arduino (arduino)Arduino 和 PCA9685 PWM/伺服驱动器
Arduino 和 PCA9685 代码
/*
Servo Motor Control using Arduino and PCA9685 Driver
by Dejan, https://howtomechatronics.com
Library: https://github.com/NachtRaveVL/PCA9685-Arduino
*/
#include <Wire.h>
#include "PCA9685.h"
PCA9685 driver;
// PCA9685 outputs = 12-bit = 4096 steps
// 2.5% of 20ms = 0.5ms ; 12.5% of 20ms = 2.5ms
// 2.5% of 4096 = 102 steps; 12.5% of 4096 = 512 steps
PCA9685_ServoEvaluator pwmServo(102, 470); // (-90deg, +90deg)
// Second Servo
// PCA9685_ServoEvaluator pwmServo2(102, 310, 505); // (0deg, 90deg, 180deg)
void setup() {
Wire.begin(); // Wire must be started first
Wire.setClock(400000); // Supported baud rates are 100kHz, 400kHz, and 1000kHz
driver.resetDevices(); // Software resets all PCA9685 devices on Wire line
driver.init(B000000); // Address pins A5-A0 set to B000000
driver.setPWMFrequency(50); // Set frequency to 50Hz
}
void loop() {
driver.setChannelPWM(0, pwmServo.pwmForAngle(-90));
delay(1000);
driver.setChannelPWM(0, pwmServo.pwmForAngle(0));
delay(1000);
driver.setChannelPWM(0, pwmServo.pwmForAngle(90));
delay(1000);
}
Code language: Arduino (arduino)使用 Arduino 和 PCA9685 驱动程序控制大量舵机
/*
Servo Motor Control using Arduino and PCA9685 Driver
by Dejan, https://howtomechatronics.com
Library: https://github.com/NachtRaveVL/PCA9685-Arduino
*/
#include <Wire.h>
#include "PCA9685.h"
PCA9685 driver;
// PCA9685 outputs = 12-bit = 4096 steps
// 2.5% of 20ms = 0.5ms ; 12.5% of 20ms = 2.5ms
// 2.5% of 4096 = 102 steps; 12.5% of 4096 = 512 steps
PCA9685_ServoEvaluator pwmServo(102, 470); // (-90deg, +90deg)
// Second Servo
PCA9685_ServoEvaluator pwmServo2(102, 310, 505); // (0deg, 90deg, 180deg)
void setup() {
Wire.begin(); // Wire must be started first
Wire.setClock(400000); // Supported baud rates are 100kHz, 400kHz, and 1000kHz
driver.resetDevices(); // Software resets all PCA9685 devices on Wire line
driver.init(B000000); // Address pins A5-A0 set to B000000
driver.setPWMFrequency(50); // Set frequency to 50Hz
}
void loop() {
driver.setChannelPWM(0, pwmServo.pwmForAngle(-90));
delay(1000);
driver.setChannelPWM(0, pwmServo.pwmForAngle(0));
delay(1000);
driver.setChannelPWM(0, pwmServo.pwmForAngle(90));
delay(1000);
}
Code language: Arduino (arduino)疑难解答
伺服电机抖动并重置我的 Arduino 板
伺服电机不会在 0 到 180 度的整个范围内移动
myservo.attach(9,600,2300); // (pin, min, max)
Code language: Arduino (arduino)尺寸和 3D 模型
SG90微伺服
MG996R伺服电机
结论
常见问题解答 (FAQ)
如何在 Arduino 中使用伺服电机?
制造工艺