舵机介绍
舵机是一种位置伺服的电机,与马达不同,我们需要马达提供的是旋转,控制的是转速和方向。而舵机不需要整圈的旋转,需要的是旋转角度并维持住。一般舵机旋转的角度范围是 0 度到 180 度。舵机引线为 3 线,分别用棕、红、橙三种颜色进行区分,舵机品牌和生产厂家不同,会有些许差异,使用之前需查看资料。我们使用的是最常见的舵机,棕、红、橙分别对应“电源负极,电源正极,控制信号”
通过向舵机的信号线发送电平时序信号来控制舵机的转动位置
SG90:
MG996R与MG90S:
- 0.5ms————–0度; 2.5% (0.5ms高电平 + 19.5低电平)
- 1.0ms————45度; 5.0% (1.0ms高电平 + 19.0低电平)
- 1.5ms————90度; 7.5% (1.5ms高电平 + 18.5低电平)
- 2.0ms———–135度;10% (2.0ms高电平 + 18.0低电平)
- 2.5ms———–180度;12.5%(2.5ms高电平 + 17.5低电平)
舵机的控制周期通常为20毫秒、50Hz的频率,但是许多舵机在 40 至 200 Hz的范围内都能正常工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <Arduino.h> #include <ESP32Servo.h>
Servo servo1;
int minUs = 500; int maxUs = 2500;
int servo1Pin = 23;
ESP32PWM pwm; void setup() { Serial.begin(9600); servo1.setPeriodHertz(50); servo1.attach(servo1Pin, minUs, maxUs); servo1.write(0); delay(3000);
}
void loop() { int pos = 0; for (pos = 0; pos <= 180; pos += 1) { servo1.write(pos); delay(20); } for (pos = 180; pos >= 0; pos -= 1) { servo1.write(pos); delay(20); } delay(3000); }
|
多舵机控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include <Arduino.h> #include <ESP32Servo.h>
Servo servoA; Servo servoB; Servo servoC; Servo servoG;
int minUs = 500; int maxUs = 2500;
int servoAPin = 23; int servoBPin = 22; int servoCPin = 21; int servoGPin = 19;
void setup() { Serial.begin(9600); servoA.setPeriodHertz(50); servoB.setPeriodHertz(50); servoC.setPeriodHertz(50); servoG.setPeriodHertz(50); servoA.attach(servoAPin, minUs, maxUs); servoB.attach(servoBPin, minUs, maxUs); servoC.attach(servoCPin, minUs, maxUs); servoG.attach(servoGPin, minUs, maxUs); }
void loop() { servoA.write(0); servoB.write(0); servoC.write(0); servoG.write(0); delay(2000); servoA.write(30); servoB.write(30); servoC.write(30); servoG.write(30); delay(2000); servoA.write(70); servoB.write(70); servoC.write(70); servoG.write(70); delay(2000); servoA.write(30); servoB.write(30); servoC.write(30); servoG.write(30); delay(2000); }
|
速度控制
- 初始化舵机控制结构体,把5个舵机控制变量放入结构体内
- 编写定时器函数,每15ms执行一轮,通过当前角度与控制角度检测舵机是否需要运动
- 编写设置舵机控制角度函数,后续可以通过该函数控制运动角度
- 编写舵机回原点控制函数,后续可通过该函数控制所有舵机回原点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| #include <Arduino.h> #include <ESP32Servo.h> #include <Ticker.h>
#define SERVO_NUM 4
#define RESET_ANGLE 0
#define PIN_SERVOA 23 #define PIN_SERVOB 22 #define PIN_SERVOC 21 #define PIN_SERVOG 19
typedef struct { Servo servo[SERVO_NUM]; uint8_t last_angle[SERVO_NUM]; uint8_t set_angle[SERVO_NUM]; }t_servo_list;
t_servo_list list;
Ticker read_state_timer;
static uint8_t em_motor_speed_ctl_run(uint8_t id,uint8_t set_angle,uint8_t now_angle){ if(set_angle > now_angle){ now_angle++; list.servo[id].write(now_angle); }else if(set_angle < now_angle){ now_angle--; list.servo[id].write(now_angle); } return now_angle; }
static void motor_timer_callbackfun(){ for(int index = 0;index < SERVO_NUM;index++){ list.last_angle[index] = em_motor_speed_ctl_run(index, list.set_angle[index] , list.last_angle[index]); } }
static bool check_angle(uint8_t *angle) { for(int index = 0;index < SERVO_NUM ;index++){ if (angle[index] < 0 || angle[index] > 180) return false; } return true; }
void em_motor_run(uint8_t *angle) { if (check_angle(angle) == false) return; for(int index = 0;index < SERVO_NUM;index++){ list.set_angle[index] = angle[index]; } }
void em_motor_run_by_angle(uint8_t angle1,uint8_t angle2,uint8_t angle3,uint8_t angle4){ list.set_angle[0] = angle1; list.set_angle[1] = angle2; list.set_angle[2] = angle3; list.set_angle[3] = angle4; }
void em_motor_reset() { for(int index = 0;index < SERVO_NUM;index++){ list.set_angle[index] = RESET_ANGLE; } }
void em_motor_init() { list.servo[0].attach(PIN_SERVOA, 500, 2500); list.servo[1].attach(PIN_SERVOB, 500, 2500); list.servo[2].attach(PIN_SERVOC, 500, 2500); list.servo[3].attach(PIN_SERVOG, 500, 2500); read_state_timer.attach_ms(15,motor_timer_callbackfun); for(int index = 0;index < SERVO_NUM;index++){ list.set_angle[index] = RESET_ANGLE; list.last_angle[index] = RESET_ANGLE + 1; } }
void setup() { em_motor_init(); }
void loop() { em_motor_run_by_angle(0,0,0,0); delay(5000); em_motor_run_by_angle(90,90,90,90); delay(5000); em_motor_run_by_angle(180,180,180,180); delay(5000); }
|