1.Arduino控制舵机
舵机是一种位置伺服的驱动器,主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机或者单片机发出信号给舵机,其内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号(给舵机1.5ms脉宽、周期为20ms的PWM信号,舵机应该处在中位),将获得的直流偏置电压与电位器的电压比较,获得电压差输出。经由电路板上的IC判断转动方向,再驱动无核心马达开始转动,透过减速齿轮将动力传至摆臂,同时由位置检测器送回信号,判断是否已经到达定位。适用于那些需要角度不断变化并可以保持的控制系统。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。一般舵机旋转的角度范围 是0 度到180 度。
所有的舵机都有外接三根线,一般用棕、红、橙三种颜色进行区分,棕色为接地线,红色为电源正极线,橙色为信号线。
舵机的转动的角度是通过调节PWM(脉冲宽度调制)信号的占空比来实现的,标准PWM(脉冲宽度调制)信号的周期固定为20ms (50Hz),理论上脉宽分布应在1ms到2ms 之间,但是,事实上脉宽 可由0.5ms 到2.5ms 之间,脉宽和舵机的转角0°~180°相对应。有一点值得注意的地方,由于舵机牌子不同,对于同一信号,不同牌子的舵机旋转的角度也会有所不同。
用Arduino 控制舵机的方法有两种,一种是通过Arduino的普通数字传感器接口产生占空比不同的方波,模拟产生PWM信号进行舵机定位,第二种是直接利用Arduino 自带的Servo函数进行舵机的控制, 这种控制方法的优点在于程序编写,缺点是只能控制2路舵机,因为 Arduino 自带函数只能利用数字9、10 接口。Arduino 的驱动能力有限,所以当需要控制1 个以上的舵机时需要外接电源。
1.1方法一:模拟产生PWM信号
将舵机接数字12接口上(这种方法不是使用analogwrite产生PWM,因此不必使用PWM口)。编写一个程序让舵机转动到用户输入数字所对应的角度数的位置,并将角度打印显示到屏幕上。
int servopin = 12; // 定义数字接口12连接伺服舵机信号线
int myangle; // 定义角度变量
int pulsewidth; // 定义脉宽变量
int val;
void servopulse(int servopin, int myangle) // 定义一个(伺服)脉冲函数
{
pulsewidth = (myangle*11)+500; // 将角度转化为500-2480的脉宽值(0.5ms~2.5ms的脉宽)
digitalWrite(servopin, HIGH); // 将舵机接口电平至高
delayMicroseconds(pulsewidth); // 延时脉宽值的微妙数
digitalWrite(servopin,LOW); // 将舵机接口电平至低
delay(20-pulsewidth/1000); // 至低的时间远长于至高的时间
}
void setup() {
pinMode(servopin, OUTPUT); // 设定舵机接口为输出接口
Serial.begin(9600); // 连接到串行端口,波特率为9600
Serial.println("servo=o_seral_simple ready");
}
// 将0到9的数转化为0到180角度,并让LED闪烁相应数的次数
void loop() {
val = Serial.read(); // 读取串行端口的值(读取char型数据返回int类型)
if (val>'0'&&val<='9')
{
val = val - '0'; // 将特征量转化为数值变量()
val = val*(180/9); // 将数字转化为角度
Serial.print("moving servo to ");
Serial.print(val, DEC); // print as an ASCII-encoded decimal
Serial.println();
for (int i=0; i<=50; i++) // 给予舵机足够的时间让它转到指定角度
{
servopulse(servopin, val); // 引用脉冲函数
}
}
}
1.2方法二:自带的Servo函数
使用时必须#include
Servo也是一个Class,可以创建自己的Servo,例如:Servo myservo;
1、attach(接口)——设定舵机的接口(数字9或10)
2、write(角度)——设定旋转角度(0°~180°)
3、read()读取舵机角度
#include
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.begin(9600);
}
void loop() {
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)
Serial.println(val);
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
1.3关于 -'0'
int val;
void setup() {
Serial.begin(9600);
}
void loop() {
/*if(Serial.available()>0)
{
val = Serial.read(); // Serial.read() 读取char型数据,返回的类型根据变量绑定的类型自动转换
Serial.println(val);
}*/
while(Serial.available())
{
val = Serial.read();
Serial.println(val);
if (val > '0'&& val <='9')
{
val = val - '0';
Serial.println(val-'0');
}
}
}
2. Arduino控制无刷电机
关于电调的控制信号:电调信号是pwm信号,信号频率为50Hz,一个周期为20ms。对于电调来讲,高电平脉宽为1ms表示停转,高电平脉宽为2ms表示满油门运转;对于舵机来说1.5ms是归中,1ms和2ms分别为左右满舵。(因此下面才直接用Servo库来给实现ESC信号的输出)。
关于Servo.write()和Servo.writeMicroseconds()
0.Servo.writeMicroseconds(): Writes a value in microseconds (uS) to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft. On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle.
1.servo.write() allows a maximum of 180 servo positions
servo.writeMicroseconds() allows a maximum of 1000 servo positions
2.The "write" method simply maps the "degrees" to microseconds and calls the "writeMicroseconds" method anyway.
The "degree" of turn is simply a convenient abstraction, and few bother to calibrate it.
控制程序:
#include // Using servo library to control ESC
Servo esc; // Creating a servo class with name as esc
int val; // Creating a variable val
void setup()
{
esc.attach(9); // Specify the esc signal pin,Here as D9
esc.writeMicroseconds(1000); // initialize the signal to 1000
Serial.begin(9600);
}
void loop()
{
val= analogRead(A0); // Read input from analog pin a0 and store in val
val= map(val, 0, 1023,1000,2000); // mapping val to minimum and maximum(Change if needed)
Serial.println(val);
esc.writeMicroseconds(val); // using val as the signal to esc
}
补充:电调1ms停转,2ms满油门运转,是指的单向电调,且是方波脉冲。而一般双向电调,1ms反转最大油门,1.5油门中点,2ms满油门正转。