舵机原理介绍 简洁讲解面向实战 非阻塞式驱动代码, arduino
目录
1.舵机简介
2.舵机转动角度的PWM条件(以180度的SG90舵机为例)
2.1 控制关系
2.2arduino产生PWM
3.0 附代码 循环0度到180度开关舵机(非阻塞版本)
4.0 Servo.h 舵机代码
1.舵机简介
舵机也叫伺服电机,是控制输入PWM信号来精确控制转动角度.所以想要驱动舵机就是让arduino输出PWM信号即可.
2.舵机转动角度的PWM条件(以180度的SG90舵机为例)
2.1 控制关系
翻译成人话就是说 ,我们要想驱动它, PWM的周期T需要时20ms 修改它的占空比 对应角度
对于PWM的占空比和周期不熟悉的请看我之前的文章:(这个是必须要会的)
Arduino 占空比 脉冲 PWM-CSDN博客
占空比(周期是20ms) | 角度 | Timer1.pwm(pin,num) 占空比配置函数 num的值 |
0.5/20*100%=2.5% | 0度 | 26 |
5% | 45度 | 51.2 ≈51 |
7.5% | 90度 | 76.8≈76 |
10% | 135度 | 102.4≈102 |
12.5% | 180度 | 128 |
2.2arduino产生PWM
我使用的是定时器1的相关库TimerOne.h来配置PWM的,简单易操作,且上限高.
arduino定时器1 TimerOne 一篇搞懂_#include <timerone.h>-CSDN博客
它的PWM的分辨率是10位的也就是1024
定时器1的两个PWM引脚是9和10 这里我们用9引脚. 第二个是变量除以1024 就是高电平的占比 也就是占空比.
占空比函数 Timer1.pwm(pin,num);
Timer1.pwm(9,26);//26/1024≈2.5%
定时器初始化和设置周期函数 Timer1.initialize();
Timer1.initialize(20000);//周期20ms 变量是微秒级别的,20000就是20毫秒
#include <TimerOne.h>
volatile long ms_tick=0,ms_tick_flag=0;
void setup(void)
{
Timer1.initialize(20000);//周期20ms
Timer1.pwm(9,26);//26/1024≈5%
Serial.begin(115200);
}
void loop(void)
{
}
3.0 附代码 循环0度到180度开关舵机(非阻塞版本)
这个代码是循环的0-180度,我中间加了延时,只是为了让舵机运行的慢一点而已,其实是并没有阻塞程序.这里面的delay 完全可以用其他延时来替代
这里推荐看一看我写的延时大全:arduino延时最全解析。(完结)_arduino 延时微秒函数-CSDN博客
使用非阻塞的延时代码.
#include <TimerOne.h>
volatile long ms_tick=0,ms_tick_flag=0;
void setup(void)
{
Timer1.initialize(20000);//精确度20ms
Timer1.pwm(9,26);
Serial.begin(115200);
}
void loop(void)
{
static int i=26,flag=0;
//这两个if语句主要是为了实现亮灭亮交替
if(i<=26)
flag=0;
if(i>=130)
flag=1;
if(flag==0)
i+=1;
else
i-=1;
Timer1.pwm(9,i);
delay(10);
}
4.0 Servo.h 舵机代码
使用Serivo.h的库文件理论上可以达到控制舵机的效果,但是本人是不推荐的,我们使用arduino大多是为了学习单片机思维,我使用TimerOne.h来驱动舵机,即使我们换了一款单片机也同样能做到.这就代表着我们学会了这个模块,彻底的吃透了它.
#include <Servo.h>
#include<Arduino.h>
Servo myservo; // 定义Servo对象来控制
int pos = 0; // 角度存储变量
void setup() {
// put your setup code here, to run once:
myservo.attach(9); // 控制线连接数字6
myservo.write(0);
}
void loop() {
// put your main code here, to run repeatedly:
shun_180(myservo);
delay(1000);
ni_180(myservo);
delay(1000);
}
void shun_180(Servo name)
{
for (pos = 0; pos <= 180; pos ++) { // 0°到180°
name.write(pos); // 舵机角度写入
delay(5); // 等待转动到指定角度
}
}
void ni_180(Servo name)
{
for (pos = 180; pos >= 0; pos --) { // 从180°到0°
name.write(pos); // 舵机角度写入
delay(5); // 等待转动到指定角度
}
}