这篇文章来源于DevicePlus.com英语网站的翻译稿。
目录

  • •        第一部分
    什么是伺服电机?
    伺服电机的类型
    所需电压和电源
  • •        第二部分
    基于Arduino程序的伺服控制
    伺服电机可以做什么?
  • •        第三部分
    伺服控制电灯开关
    电灯开关的远程控制

image001-4.jpg
在本文中,我们将介绍一款伺服电机的基本用法,并且还会设计一个简单的DIY伺服控制电灯开关,使您可以随时随地打开/关闭电灯!
注意:我们将要制备的自动电灯开关仅适用于按钮式电灯开关系统。

本项目电子设备清单
第一部分:

  • •        Arduino UNO R3
  • •        FEETECH FS90 微伺服
  • •        Rapiro伺服电机 (大号)
  • •        数码微伺服HK-5330
  • •        50 KΩ B型电位器otentiometer
  • •        面包板
  • •        跳线(公对公)

第二部分:

  • •        Arduino UNO R3
  • •        ESPr开发板
  • •        Towerpro MG996R 伺服器
  • •        面包板
  • •        跳线(公对公)


1. 什么是伺服电机?
image003-4.jpg
图1:伺服电机

伺服电机是通过旋转连接至发动机节气门的轴进行工作的一种电机类型。因为可以对旋转角度和转速进行精确控制,所以被广泛应用于自动化制造、机器人以及个人的物联网项目等。
伺服电机 – 维基百科
伺服电机是一种旋转致动器或线性致动器,可精确控制角度或线性位移、速度和加速度。伺服电机包含一个与传感器耦合以进行位置信息反馈的适配电机。……伺服电机是一种闭环伺服系统,可以使用位置的反馈信息进行运转和最终位置的控制。

伺服电机具有一个编码器,用于检测旋转角度,并使用编码信号将输出轴定位到指定角度。我们可以来看一下不同类型电机之间的区别:

  • •        电机:通电时可旋转。
  • •        伺服电机:在0度到N度的范围内旋转,对信号作出响应。
  • •        步进电机:以离散的步进角旋转,并且在有信号或无信号的情况下都可以进行控制。
  • •        无刷直流电机:施加稳定直流电压时,可连续旋转,因此可以稳定地控制转速。
请务必根据应用的特点来选择合适的电机。
image005-5.jpg
图2:不同类型的电机。从左到右:无刷电机,步进电机,伺服电机,直流电机

2. 伺服电机的类型

那么,您应该购买哪种类型的伺服电机呢?购买伺服电机时,请考虑以下要点:

  • •        扭矩:用于驱动电机的力矩;扭矩数值越大,力矩越大(单位:kgf·cm等)
  • •        转角:在特定角度下电机的旋转/位置
  • •        工作速度:转速
  • •        工作电压:工作所需电压

2.1 扭矩的计算

使用伺服电机时,最重要的是要了解您所需要的扭矩值。伺服电机的扭矩以kgf·cm或kg为单位表示。如果以kgf·cm为单位来计算扭矩,计算出来的值就表示它在1[cm]的半径下可以举起的多少N[kg]物体。如果您想要举起5kg的物品,并且在伺服电机轴上连接的手柄长度为2cm,那么需要大于5 kgf × 2 cm = 10 kgf·cm的扭矩。
image007-4.jpg
图3:计算扭矩的方法

3. 所需电压和电源

当通过Arduino来对伺服电机进行控制时,就像其它类型的电机一样,几乎不可能从Arduino获取电压或电流。在这种情况下,您可以使用外部电源,然后将来自Arduino的角度控制信号传输到伺服电机中。
例如,在本系列中经常使用的Arduino UNO R3具有I/O引脚(数字/模拟引脚),每个引脚大约可以获取20 mA的电流(如果电流大于40 mA,可能会损坏)。虽然伺服电机的工作电压是5V,但是由于来自数字/模拟引脚的电流不足,伺服电机和Arduino也会发生损坏。因此,当您通过I/O引脚来供电时要小心处理!
5V或3.3V引脚上的最大额定电流值(所获取的电流极限)是200 mA。因此可以使用小型伺服电机。
例如,对于工作电压为9V的伺服电机,需要对伺服电机和Arduino分别供电,如以下电路图所示。
image009-4.jpg
图4:Arduino和伺服电机(分别供电)

如果伺服电机的工作电压很小(比如5V),并且您想要与Arduino共享电源,那么可以按照以下电路从5V电压中获取电流。
image011-4.jpg
图5:Arduino和伺服电机(共享电源)

4. 基于Arduino程序的伺服控制

Arduino对伺服电机控制的方式大致有两种。
PWM(脉冲宽度调制)是一种通过打开和关闭脉冲信号来控制电机的方法。通过直接使用PWM来控制伺服电机可以实现步进式转动。但是对于更复杂的项目,您可以使用Arduino IDE中包含的伺服电机库。
Arduino IDE → [File] → [Examples] → [10.StarterKit BasicKit] → [p05_ServoMoodindicator]
该程序可以根据模拟引脚0(A0)的输入值来更改伺服电机的角度。在模拟引脚上使用电位计或光学传感器等可变电阻,通过电阻值的变化来实现电机的转动。

伺服电机库函数

伺服电机库基于两种类型的指令:1)指定要发送到伺服电机的控制信号的引脚编号。2)指定伺服电机转动时的角度。

代码—示例
myServo.attach(9); //Specify the servo motor's signal pin
复制代码
代码—示例
myServo.write(angle); //Move the servomotor to a specific angle
复制代码
以下电路是使用FEETECH FS90微伺服电机的示例。该伺服电机的工作电压是6V。由于工作时的电流是200 mA,因此伺服电机由四节AA电池串联供电(6V)。
image013-3.jpg
图6:示例电路图
image015-3.jpg
图7:伺服电机控制电路
image017-3.jpg
图8: p05_ServoMoodIndicator

代码—示例
/*
  • Arduino Starter Kit example
  • Project 5 - Servo Mood Indicator
  • This sketch is written to accompany Project 5 in the
  • Arduino Starter Kit
  • Parts required:
  • servo motor
  • 10 kilohm potentiometer
  • 2 100 uF electrolytic capacitors
  • Created 13 September 2012
  • by Scott Fitzgerald
  • https://www.arduino.cc/starterKit
  • This example code is part of the public domain
  • */
  • // include the servo library
  • #include <Servo.h>
  • Servo myServo; // create a servo object
  • int const potPin = A0; // analog pin used to connect the potentiometer
  • int potVal; // variable to read the value from the analog pin
  • int angle; // variable to hold the angle for the servo motor
  • void setup() {
  • myServo.attach(9); // attaches the servo on pin 9 to the servo object
  • Serial.begin(9600); // open a serial connection to your computer
  • }
  • void loop() {
  • potVal = analogRead(potPin); // read the value of the potentiometer
  • // print out the value to the serial monitor
  • Serial.print("potVal: ");
  • Serial.print(potVal);
  • // scale the numbers from the pot
  • angle = map(potVal, 0, 1023, 0, 179);
  • // print out the angle for the servo motor
  • Serial.print(", angle: ");
  • Serial.println(angle);
  • // set the servo position
  • myServo.write(angle);
  • // wait for the servo to get there
  • delay(15);
  • }
  • 复制代码
    5. 伺服电机可以做什么?

    让我们简要回顾一下使用伺服电机可以完成的工作。以下是两种典型工作方式:

    I. 按下按钮
    伺服电机可以控制转动的角度。这就是为什么伺服电机最适于开发按钮控制的机械系统。您可以像下面的视频中那样制作一些有趣的设备,并且也可以开发出仅通过一个按钮来实现控制的多种设备,如房间里的开关等等。
    II. 移动物体
    伺服电机可以用于多种器件,但是它通常用于“移动”部件/物体,例如移动机器人汽车或机器人手臂等。

    6. 伺服控制电灯开关

    举一个实际生活中的例子,我想制造一种可以通过按下电灯开关来实现房间电灯自动打开的设备。下面,我将会结合Arduino + 伺服电机+ 3D 打印机 + Wi-Fi 模块来实现它!
    注意:我们将要制造的自动电灯开关仅适用于按钮式电灯开关系统。
    我们从通过3D打印制造用于按下电灯开关按钮的部件开始。
    本次使用的伺服电机是MG996R,其扭矩比之前的产品中使用的电机扭矩更大。该伺服电机的扭矩为9.4kg,工作电压为4.8 – 6.6 V。我们还将使用ESP-WROOM-02 Wifi,并尝试通过PC或智能手机来移动伺服电机,从而对开关进行控制操作。
    image025-3.jpg
    图9:按压开关的部件
    image027-3.jpg
    图10:用3D打印机制造
    image029-3.jpg
    图11:房间开关
    image031-2.jpg
    图12:在伺服电机上安装3D打印部件
    image035-2.jpg
    图13:安装在房间电灯开关上

    我用胶带将设备固定在电灯开关上。
    image037-2.jpg
    图14:胶带

    完成后,测试一下伺服电机是否正常工作,是否可以打开电灯。

    它做到了是吗?太好了!我想您已经意识到了,我们刚刚所制备的开关只能用来打开电灯。不幸的是,这种开关不能用来关掉电灯或者再次打开电灯。我希望我们的开关在两端都能够被按下,从而实现自动打开和关闭电灯。
    image041-2.jpg
    图15:测量开关尺寸

    我们来测量一下房间电灯开关的宽度。我的开关大约是4cm。我认为最好在支撑部件上设计一些突出的结构,以便从两端按下电灯的开关按钮。因此,我用3D打印的方法制造了以下部件:
    image043-2.jpg
    图16:可以按压开关按钮两端的部件
    image045-2.jpg
    图17:安装在伺服电机上

    安装到伺服电机上后,我们将对ESP-WROOM-02模块编写程序,以进行开关的远程控制。
    image047-2.jpg
    图18:遥控电灯开关的最终设置

    7. 电灯开关的远程控制

    将该机械系统连接到安装在房间中的无线路由器上,并且根据获取的IP地址,我们可以提供一个操作伺服电机的功能。
    当ESP-WROOM-02开机时,我们可以设置一个报告服务器,并连接外部API,以在从无线路由器获取IP地址后,通过电子邮件转发IP地址。
    #include <ESP8266WiFi.h>
  • #include <Servo.h>
  • const char *ssid = "[wifi_ssid]";
  • const char *password = "[wifi_password]";
  • //IP report server configuration
  • const char* host = "xxxx.xx.xxx";
  • String url = "/xxxx/";
  •   
  • Servo myservo;
  • Servo myservo2;
  • WiFiServer server(80);
  • String IpAddress2String(const IPAddress& ipAddress)
  • {
  • return String(ipAddress[0]) + String(".") +\
  • String(ipAddress[1]) + String(".") +\
  • String(ipAddress[2]) + String(".") +\
  • String(ipAddress[3]) ;
  • }
  •   
  • void setup() {
  • Serial.begin(115200);
  • delay(10);
  •   
  • Serial.println("Start!");
  • Serial.println();
  • Serial.print("Connecting to ");
  • Serial.println(ssid);
  •   
  • WiFi.begin(ssid, password);
  •   
  • while (WiFi.status() != WL_CONNECTED) {
  • delay(1500);
  • Serial.print(".");
  • }
  • Serial.println("");
  • Serial.println("WiFi connected");
  •   
  • server.begin();
  • Serial.println("Server started");
  • Serial.println(WiFi.localIP());
  • //*********************************************************
  • // IP address notification
  • //*********************************************************
  • WiFiClient client;
  • const int httpPort = 80;
  • if (!client.connect(host, httpPort)) {
  • Serial.println("connection failed");
  • return;
  • }
  •   
  • url += IpAddress2String(WiFi.localIP());
  • client.print(String("GET ") + url + " HTTP/1.1\r\n" +
  • "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");
  • delay(1000);
  • Serial.print("Connecting url to ");
  • Serial.println(url);
  • //*********************************************************************
  • }
  •   
  • void loop() {
  • WiFiClient client = server.available();
  • if (!client) {
  • return;
  • }
  •   
  • Serial.println("new client");
  • while(!client.available()){
  • delay(1);
  • }
  •   
  • String req = client.readStringUntil('\r');
  • Serial.println(req);
  • client.flush();
  • // Match the request
  • int selectServo = 0;
  • int posSlash0 = req.indexOf("/");
  • String tmp = req.substring(0,posSlash0);
  • int posSlash1st = req.indexOf("/",1+posSlash0);
  • String action = req.substring(1+posSlash0,posSlash1st);
  • int posSlash2nd = req.indexOf("/",1+posSlash1st);
  • String sel = req.substring(1+posSlash1st,posSlash2nd);
  • int posSlash3rd = req.indexOf("/",1+posSlash2nd);
  • String valueTmp = req.substring(1+posSlash2nd,posSlash3rd);
  • int posSpace = valueTmp.indexOf(" ");
  • String value = valueTmp.substring(0,posSpace);
  • if(action == "favicon.ico HTTP"){
  • return;
  • }
  • //GET /servo/1/60 HTTP/1.1
  • Serial.print("POS:");
  • Serial.print(posSlash1st);
  • Serial.print(":");
  • Serial.print(posSlash2nd);
  • Serial.print(":");
  • Serial.println(posSlash3rd);
  • Serial.print("ACTION:");
  • Serial.println(action);
  • Serial.print("SELECT SERVO:");
  • Serial.println(sel);
  • Serial.print("VALUE:");
  • Serial.println(value);
  • if(sel == "0"){
  • myservo.write(value.toInt());
  • }
  •   
  • client.flush();
  •   
  • String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>";
  • s += "<head><meta name='viewport' content='width=device-width, initial-scale=1'>";
  • s += "<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' media='screen'>";
  • s += "<script type='text/javascript' src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'></script>";
  • s += "</head><body>";
  • s += "\r\nSERVO ";
  • s += sel;
  • s += " is ";
  • s += String(value);
  • s += "<div class='container'><div class='row'>";
  • s += "<div class='col-md-12'><h3>Servo0</h3></div>";
  • s += "<div class='col-md-12'><a class='btn btn-primary' href='/servo/0/0'>ON</a></div>\n";
  • s += "<div class='col-md-12'><a class='btn btn-info' href='/servo/0/50'>OFF</a></div>\n";
  • s += "<div class='col-md-12'><a class='btn btn-info' href='/servo/0/30'>STAY</a></div>\n";
  • s += "</div></div>";
  • s += "</body>";
  • s += "</html>\n";
  •   
  • client.print(s);
  • delay(1);
  • Serial.println("Client disonnected");
  • }
  • 复制代码
    如上述视频所示,我能够从我的PC端打开/关闭电灯。
    我们创建了一个伺服控制电灯开关,实现了无线和远程控制。这些类型的设备有很多用途。
    image051-1.jpg

    来源:techclass.rohm