初识舵机

视频1:自动吃食的小动物模型

难度:⭐
相关材料:舵机(MG90S)、木板或硬纸板、剪刀
程序:舵机范例程序
点击查看【bilibili】

视频2:自动转头的小动物模型

难度:⭐
相关元器件:相关材料:舵机(MG90S)、木板或硬纸板、剪刀
程序:舵机范例程序
点击查看【bilibili】

舵机原理

这种电机内置电路可将电机输出轴的位置进行反馈,因此它的输出轴可以被Arduino等控制在某一个固定角度。它的主要应用为控制模型的运动方向(这就是”舵机“这一名称来历。),很多小型机械臂也会使用舵机驱动。舵机有些是可以旋转360度的,但有些只能旋转180度。
9.机械控制:控制方向的迷你舵机 - 图1
9.机械控制:控制方向的迷你舵机 - 图2
舵机的转动的角度是通过调节PWM(脉冲宽度调制)信号的占空比来实现的,标准PWM(脉冲宽度调制)信号的周期固定为20ms(50Hz),理论上脉宽分布应在1ms到2ms 之间,但是,事实上脉宽可由0.5ms 到2.5ms 之间,脉宽和舵机的转角0°~180°相对应。有一点值得注意的地方,由于舵机牌子不同,对于同一信号,不同牌子的舵机旋转的角度也会有所不同。
9.机械控制:控制方向的迷你舵机 - 图3
点击查看【bilibili】

参考资料:脉冲宽度调制技术(PWM)

脉冲宽度调制(英语:Pulse-width modulation,缩写:PWM),简称脉宽调制,是将模拟信号变换为脉冲的一种技术,一般变换后脉冲的周期固定,但脉冲的工作周期会依模拟信号的大小而改变。

在过去,当只有部分能量需求(以缝纫机马达为例),一个变阻器(被放在缝纫机的脚踏板上)串接在一个马达上将会调整流入马达中的电流,同时会因为电阻发热而消耗一些能量。这其实是一个可以接受(因为总能量够低)但没有效率的方式。然而,变阻器只是一个控制能量的方法之一(可参考自耦变压器做为参考),因此需要实现一个可以达到较低成本又有效率的调整方法。这个机制同时可以被运用来当作电扇马达、泵马达、机器伺服等,同时必须足够精细与台灯系统互动,因此,脉冲宽度调制应运而生,作为这个复杂问题的一个解决方案。

在模拟电路中,模拟信号的值可以连续进行变化,在时间和值的幅度上都几乎没有限制,基本上可以取任何实数值,输入与输出也呈线性变化。所以在模拟电路中,电压和电流可直接用来进行控制对象,例如家用电器设备中的音量开关控制、采用卤素灯泡灯具的亮度控制等等。

但模拟电路有诸多的问题:例如控制信号容易随时间漂移,难以调节;功耗大;易受噪声和环境干扰等等。

与模拟电路不同,数字电路是在预先确定的范围内取值,在任何时刻,其输出只可能为ON和OFF两种状态,所以电压或电流会通/断方式的重复脉冲序列加载到模拟负载。PWM技术是一种对模拟信号电平的数字编码方法,通过使用高分辨率计数器(调制频率)调制方波的占空比,从而实现对一个模拟信号的电平进行编码。其最大的优点是从处理器到被控对象之间的所有信号都是数字形式的,无需再进行数模转换过程;而且对噪声的抗干扰能力也大大增强(噪声只有在强到足以将逻辑值改变时,才可能对数字信号产生实质的影响),这也是PWM在通讯等信号传输行业得到大量应用的主要原因。
image.png
一个例子脉宽调制:供电电压(蓝色)调制为一系列的脉冲产生一个正弦样磁通密度波形(红色),在磁路的电磁致动器。平滑的波形由此可以控制的宽度和数目的脉冲调制(每特定周期)
模拟信号能否使用PWM进行编码调制,仅依赖带宽,这即意味着只要有足够的带宽,任何模拟信号值均可以采用PWM技术进行调制编码,一般而言,负载需要的调制频率要高于10Hz,在实际应用中,频率约在1kHz到200kHz之间。

在信号接收端,需将信号解调还原为模拟信号,目前在很多微型控制器(MCU)内部都包含有PWM控制器模块。

实例12:舵机的运行测试

【实验说明】
控制舵机转动一定角度
【材料准备】

  • Uno R3开发板
  • 配套USB数据线
  • 面包板及配套连接线
  • 舵机

【马上行动】

1.硬件连接

舵机:

  • VCC:电源正极(接5V电源)
  • GND:电源负极(接地)
  • SIGNAL:控制信号,接D9

    2.运行示例程序

    ```c /**

    舵机的直接控制

    修订历史/Revision History 日期/Date 作者/Author 参考号/Ref 修订说明/Revision Description

    2021/05/18 金陵中学 1.0 金陵中学Arduino选修课使用

    */

    include

Servo myServo; //创建Servo对象myServo int pos=90; // 创建变量pos存储舵机角度值

void setup() { myServo.attach(9); }

void loop() { // 检查串口缓存是否有数据等待传输 myServo.write(pos); // 使用pos变量数值设置伺服电机 delay(15); } }

  1. <a name="gEQGo"></a>
  2. ## 练习(舵机的往复控制)
  3. ```c
  4. /**********************************************************************
  5. 舵机的往复控制
  6. -----------------------------------------------------------------------
  7. 修订历史/Revision History
  8. 日期/Date 作者/Author 参考号/Ref 修订说明/Revision Description
  9. 2021/05/18 金陵中学 1.0 金陵中学Arduino选修课使用
  10. -----------------------------------------------------------------------
  11. */
  12. #include <Servo.h>
  13. Servo myservo; //创建Servo对象myservo
  14. int pos = 0; // 创建变量pos存储舵机角度值
  15. void setup()
  16. {
  17. myservo.attach(9);
  18. }
  19. void loop()
  20. {
  21. for(pos = 0; pos < 180; pos += 1) // 舵机从0到180度,间隔为1
  22. {
  23. myservo.write(pos); //告知舵机前往变量pos所对应的位置
  24. delay(15); // 等待15ms
  25. }
  26. for(pos = 180; pos>=1; pos-=1) // 舵机从180到0度
  27. {
  28. myservo.write(pos); // tell servo to go to position in variable 'pos'
  29. delay(15); // waits 15ms for the servo to reach the position
  30. }
  31. }

练习(通过串口实现舵机的控制)

  1. /**********************************************************************
  2. 通过串口实现舵机的控制
  3. -----------------------------------------------------------------------
  4. 修订历史/Revision History
  5. 日期/Date 作者/Author 参考号/Ref 修订说明/Revision Description
  6. 2021/05/18 金陵中学 1.0 金陵中学Arduino选修课使用
  7. -----------------------------------------------------------------------
  8. */
  9. #include <Servo.h>
  10. Servo myservo; //创建Servo对象myservo
  11. int dataIndex = 0; //创建整数型变量,存储输入数据序列号
  12. void setup() {
  13. myservo.attach(9);
  14. Serial.begin(9600); //启动串口通讯,传输波特率9600
  15. Serial.println("Please input serial data.");
  16. }
  17. void loop() { // 检查串口缓存是否有数据等待传输
  18. if ( Serial.available()>0 ) {
  19. dataIndex++; // 处理数据序列号并通过串口监视器显示
  20. Serial.print("dataIndex = ");
  21. Serial.print(dataIndex);
  22. Serial.print(" , ");
  23. int pos = Serial.parseInt(); // 解析串口数据中的整数信息并赋值给变量pos
  24. Serial.print("Set servo position: ");
  25. Serial.println(pos); // 通过串口监视器显示变量pos数值
  26. myservo.write(pos); // 使用pos变量数值设置伺服电机
  27. delay(15);
  28. }
  29. }