风筝
发表于: 2018-11-2 22:54:07 | 显示全部楼层

在本篇文章中,我们将了解伺服电机的工作原理以及如何使用Arduino开发板和PWM驱动器PCA9685控制伺服电机。伺服电机种类繁多,它们的主要特征是能够精确控制轴的位置。伺服电机是一种闭环系统,它使用位置反馈来控制其运动和最终位置。

Closed-loop-System.png


在工业型伺服电机中,位置反馈传感器通常是高精度编码器,而在较小的RC或Hobby伺服电机中,位置传感器通常是一个简易的电位器。这些设备捕获的实际位置被反馈到误差检测器,在那里将其与目标位置进行比较。然后根据误差,控制器校正电机的实际位置以匹配目标位置。

Servo-Motor-Closed-Loop-System.jpg


在本篇文章中,我们将详细介绍Hobby伺服电机。我们将解释这些伺服电机是如何工作的,以及如何使用Arduino开发板控制它们。

Controlling-multiple-servo-motors-with-Arduino-and-PCA9685-PWM-Driver.jpg


Hobby伺服电机是用于控制RC玩具汽车、船只、飞机等的小型执行器。它们也被工程学生用于机器人原型制作、机器人手臂、生物机器人、人形机器人等。

Servo-Motor-Applications-Robotic-Arm-Hexapod-Humanoid-Robot.jpg


RC / Hobby伺服电机是如何工作的?

在Hobby伺服电机中,有四个主要部件:直流电机、变速箱、电位器和控制电路。直流电机是高速和低扭矩,但变速箱将速度降低到大约60 RPM,同时增加扭矩。

How-Hobby-Servo-Works-Inside-Components-DC-Motor-Potentiometer-Control-Circuit.jpg

电位器安装在最末端的齿轮或输出轴上,因d此当电动机旋转时,电位器也会旋转,从而产生与输出轴的绝对角度相关的电压。在控制电路中,将该电位器电压与来自信号线的电压进行比较。如果需要,控制器激活集成的H桥,使电机能够沿任一方向旋转,直到两个信号达到零差。


伺服电机是通过信号线发送一系列脉冲来实现控制的。控制信号的频率应为50Hz或每20ms发生一次脉冲。脉冲的宽度决定了伺服电机的角度位置,这种类型的伺服机构通常可以旋转180度(它们物理上都会设置行程限制)。

RC-Servo-Motor-Control-Signal.png

通常,持续时间为1ms的脉冲对应于0度位置,1.5ms持续时间对应于90度,2ms对应180度。虽然如此,但是脉冲的最小和最大持续时间有时会随着不同的品牌而变化,对于0度可以是0.5ms,对于180度位置可以是2.5ms。


Arduino控制伺服电机

让我们把上面说的内容测试一下,并制作一个使用Arduino控制hobby伺服电机的实际例子。我将使用MG996R伺服电机,这是一种大扭矩伺服,具有金属齿轮,失速扭矩为10 kg-cm。高扭矩是有代价的,而伺服的失速电流是2.5A。运行电流为500mA至900mA,工作电压为4.8至7.2V。

Arduino-Servo-Motor-Control-MG996R.jpg

电流额定值表明我们无法直接将此伺服连接到Arduino开发板,必须使用单独的电源。以下是此示例的电路原理图。

Arduino-Servo-Control-Circuit-Schematic.jpg

我们只需要将伺服的控制引脚连接到Arduino开发板的任何数字引脚,将地线和正极线连接到外部5V电源,并将Arduino地连接到伺服电机地。


Arduino控制伺服电机的代码

现在让我们来看看用于控制伺服电机的Arduino代码。 代码非常简单。 我们只需要定义伺服连接的引脚,将该引脚定义为输出,并在loop函数部分产生具有特定持续时间和频率的脉冲,如前所述。

  1. /*
  2.      Servo Motor Control - 50Hz Pulse Train Generator
  3.            by Dejan, https://howtomechatronics.com
  4. */
  5. #define servoPin 9
  6. void setup() {
  7.   pinMode(servoPin, OUTPUT);
  8. }
  9. void loop() {
  10.    // A pulse each 20ms
  11.     digitalWrite(servoPin, HIGH);
  12.     delayMicroseconds(1450); // Duration of the pusle in microseconds
  13.     digitalWrite(servoPin, LOW);
  14.     delayMicroseconds(18550); // 20ms - duration of the pusle
  15.     // Pulses duration: 600 - 0deg; 1450 - 90deg; 2300 - 180deg
  16. }
复制代码

经过一些测试后,我找到了用于与伺服系统一起使用的脉冲持续时间的以下值。 持续时间为0.6ms的脉冲对应于0度位置,1.45ms对应90度和2.3ms对应180度。

我将万用表与伺服系统串联,以检查电流消耗。 我注意到的最大电流消耗在失速时高达0.63A。 那是因为这不是原来的TowerPro MG996R伺服,而是更便宜的复制品,显然性能更差。

MG996R-Servo-Motor-Current-Draw.jpg


不过,让我们来看看使用Arduino控制伺服的更方便的方法。 那就是使用Arduino伺服库。

  1. /*
  2.      Servo Motor Control using the Arduino Servo Library
  3.            by Dejan, https://howtomechatronics.com
  4. */
  5. #include <Servo.h>
  6. Servo myservo;  // create servo object to control a servo
  7. void setup() {
  8.   myservo.attach(9,600,2300);  // (pin, min, max)
  9. }
  10. void loop() {
  11.   myservo.write(0);  // tell servo to go to a particular angle
  12.   delay(1000);
  13.   
  14.   myservo.write(90);              
  15.   delay(500);
  16.   
  17.   myservo.write(135);              
  18.   delay(500);
  19.   
  20.   myservo.write(180);              
  21.   delay(1500);                     
  22. }
复制代码

这里我们只需要包含库,定义伺服对象,并使用attach()函数定义伺服所连接的引脚,并定义脉冲持续时间的最小值和最大值。 然后使用write()函数,我们只需将伺服位置设置为0到180度。 通过该库,我们可以同时驱动多达12个伺服电机或使用Arduino Mega开发板驱动48个伺服电机。

跳转到指定楼层
风筝
发表于: 2018-11-3 21:45:12 | 显示全部楼层

Arduino和PWM伺服驱动器PCA9685

还有另一种用Arduino开发板控制伺服系统的方法,那就是使用PCA9685伺服驱动器。这是一个16通道12位PWM伺服驱动器,使用I2C总线与Arduino开发板通信。它有一个内置时钟,因此它可以驱动16个伺服电机。

Arduino-and-PCA9685-PWM-Servo-Driver.jpg

更酷的是,我们可以在单个I2C总线上以菊花链形式连接62个这样的驱动器。因此理论上我们只使用Arduino开发板上的两个I2C引脚就可以控制多达992个伺服电机。 6个地址选择引脚用于为每个附加驱动器设置不同的I2C寻址。我们只需要根据下表连接焊盘。

PCA9685-Address-Select-Pins-Table-I2CAddress.png

以下是电路原理图,我们再次注意到需要为伺服电机提供单独的电源。

Multiple-PCA9685-Drivers-Daisy-Chained-Circuit.png


此示例所需的组件:

●    MG996R伺服电机

●    PWM伺服驱动器PCA9685

●    Arduino开发板

●    5V/6A直流电源


现在让我们来看看Arduino代码。为了控制这个伺服驱动器,我们可以使用从GitHub下载的PCA9685库


PCA9685 Arduino代码

  1. /*
  2.      Servo Motor Control using Arduino and PCA9685 Driver
  3.            by Dejan, https://howtomechatronics.com
  4.            
  5.      Library: https://github.com/NachtRaveVL/PCA9685-Arduino
  6. */
  7. #include <Wire.h>
  8. #include "PCA9685.h"
  9. PCA9685 driver;
  10. // PCA9685 outputs = 12-bit = 4096 steps
  11. // 2.5% of 20ms = 0.5ms ; 12.5% of 20ms = 2.5ms
  12. // 2.5% of 4096 = 102 steps; 12.5% of 4096 = 512 steps
  13. PCA9685_ServoEvaluator pwmServo(102, 470); // (-90deg, +90deg)
  14. // Second Servo
  15. // PCA9685_ServoEvaluator pwmServo2(102, 310, 505); // (0deg, 90deg, 180deg)
  16. void setup() {
  17.   Wire.begin();                 // Wire must be started first
  18.   Wire.setClock(400000);        // Supported baud rates are 100kHz, 400kHz, and 1000kHz
  19.   driver.resetDevices();        // Software resets all PCA9685 devices on Wire line
  20.   driver.init(B000000);         // Address pins A5-A0 set to B000000
  21.   driver.setPWMFrequency(50);   // Set frequency to 50Hz
  22. }
  23. void loop() {
  24.   driver.setChannelPWM(0, pwmServo.pwmForAngle(-90));
  25.   delay(1000);
  26.   driver.setChannelPWM(0, pwmServo.pwmForAngle(0));
  27.   delay(1000);
  28.   driver.setChannelPWM(0, pwmServo.pwmForAngle(90));
  29.   delay(1000);
  30. }
复制代码

首先,我们需要包含库并定义PCA9685对象。然后使用Servo_Evaluator实例定义驱动器的脉冲持续时间或PWM输出。请注意,输出是12位,或者是分辨率为4096步。因此,0.5ms或0度位置的最小脉冲持续时间将对应于102步,并且最大脉冲持续时间为2.5ms或180度位置为512步。但如前所述,这些值应根据伺服电机进行调整。在本例中,102到470的值对应于0到180度的位置。


在setup函数部分,我们需要定义I2C时钟速率,设置驱动器地址并将频率设置为50Hz。


在loop函数部分,使用setChannelPWM()pwmForAngle()函数,我们只需将伺服电机设置为所需的角度。


我将第二个伺服电机连接到驱动器上,正如我所预料的那样,它的定位与第一个不同,这是因为我使用的伺服系统是便宜的复制品而且它们不那么可靠。但是,这不是一个大问题,因为使用Servo_Evaluator实例我们可以为每个伺服设置不同的输出设置。我们也可以调整90度位置,以防它不在中间。这样,所有伺服系统都能以相同的方式工作,并以精确的角度定位。


使用菊花链式PCA9685驱动程序控制大量伺服电机

我们将再看一个例子,它用多个链式PCA9685驱动程序控制很多伺服器。

Controlling-22-Servo-Motors-with-Arduino-and-PCA9685.jpg

为此,我们需要将驱动器相互连接并连接适当的地址选择焊盘。以下是电路原理图:

Multiple-PCA9685-Drivers-Daisy-Chained-Circuit.png

我们现在来看看Arduino代码。

  1. /*
  2.      Servo Motor Control using Arduino and PCA9685 Driver
  3.            by Dejan, https://howtomechatronics.com
  4.            
  5.      Library: https://github.com/NachtRaveVL/PCA9685-Arduino
  6. */
  7. #include <Wire.h>
  8. #include "PCA9685.h"
  9. PCA9685 driver;
  10. // PCA9685 outputs = 12-bit = 4096 steps
  11. // 2.5% of 20ms = 0.5ms ; 12.5% of 20ms = 2.5ms
  12. // 2.5% of 4096 = 102 steps; 12.5% of 4096 = 512 steps
  13. PCA9685_ServoEvaluator pwmServo(102, 470); // (-90deg, +90deg)
  14. // Second Servo
  15. PCA9685_ServoEvaluator pwmServo2(102, 310, 505); // (0deg, 90deg, 180deg)
  16. void setup() {
  17.   Wire.begin();                 // Wire must be started first
  18.   Wire.setClock(400000);        // Supported baud rates are 100kHz, 400kHz, and 1000kHz
  19.   driver.resetDevices();        // Software resets all PCA9685 devices on Wire line
  20.   driver.init(B000000);         // Address pins A5-A0 set to B000000
  21.   driver.setPWMFrequency(50);   // Set frequency to 50Hz
  22. }
  23. void loop() {
  24.   driver.setChannelPWM(0, pwmServo.pwmForAngle(-90));
  25.   delay(1000);
  26.   driver.setChannelPWM(0, pwmServo.pwmForAngle(0));
  27.   delay(1000);
  28.   driver.setChannelPWM(0, pwmServo.pwmForAngle(90));
  29.   delay(1000);
  30. }
复制代码

因此,我们应该为每个驱动程序创建单独的PCA9685对象,定义每个驱动程序的地址以及将频率设置为50Hz。 现在只需使用setChannelPWM()pwmForAngle()函数,我们就可以在任何驱动器上设置任何伺服电机,以定位我们想要的任何角度。


以下就是本文的全部内容,我希望你喜欢它并学到新东西。 请随时在下面回复帖子。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1479



手机版|

GMT+8, 2024-3-28 22:55 , Processed in 0.098126 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表