小猪学arduino—舵机的使用

上一篇文章我们讲到了使用红外线发射和接收装置控制led,儿子看后表示能不能做个遥控器控制一个小虫子走路,研究了一下,打算用两个舵机实现,每个舵机负责虫子的两只脚。本文先用学习一下舵机的使用,并用两个舵机测试一下这种想法的可行性。为了降低测试成本,在某宝5块多的价格买了几个9g的微型舵机。

%e8%88%b5%e6%9c%ba

舵机有很多规格,但所有的舵机都有外接三根线,分别用棕、红、橙三种颜色进行区分,由于舵机品牌不同,颜色也会有所差异,棕色为接地线,红色为电源正极线,橙色为信号线。

舵机的转动的角度是通过调节PWM(脉冲宽度调制)信号的占空比来实现的,标准PWM(脉冲宽度调制)信号的周期固定为20ms50Hz),理论上脉宽分布应在1ms2ms 之间,但是,事实上脉宽可由0.5ms 2.5ms 之间,脉宽和舵机的转角180°相对应。有一点值得注意的地方,由于舵机牌子不同,对于同一信号,不同牌子的舵机旋转的角度也会有所不同。

Arduino 控制舵机的方法有两种,一种是通过Arduino 的普通数字传感器接口产生占空比不同的方波,模拟产生PWM 信号进行舵机定位,第二种是直接利用Arduino 自带的Servo 函数进行舵机的控制,这种控制方法的优点在于程序编写,缺点是只能控制2 路舵机,因为Arduino 自带函数只能利用数字910 接口。

因为后续打算4个脚走路不稳的话给虫子再多加几条腿,所以本文使用第一种pwm脉冲宽度调制的方法控制舵机。

连线方法

如图所示,舵机,棕、红、橙线分别接GND、5V、8号端口

%e8%88%b5%e6%9c%ba%e8%bf%9e%e7%ba%bf

先用一个舵机进行测试,成功后再用两个舵机测试。

我在测试后顺便加上了红外线控制舵机左转、右转,及按钮按下时亮起led(因为遥控器有点不太灵,我又懒得老去看日志)。

实际连线图

img_3717

img_3718

具体代码如下:

#include <IRremote.h>//包含红外库
int infraredPin = 3;//红外线接收器端口
long INFRARED_PLAY = 0x00FFA857;//红外遥控器上的PLAY键指令
long INFRARED_LEFT = 0x00FFE01F;//红外遥控器上的左键指令
long INFRARED_RIGHT = 0x00FF906F;//红外遥控器上的右键指令
long INFRARED_UP = 0x00FF02FD;//红外遥控器上的上键指令
long INFRARED_DOWN = 0x00FF9867;//红外遥控器上的下键指令
int servo1Pin = 7;//舵机端口
int servo2Pin = 8;//舵机端口
int ledPin = 4; //led端口
int i = 0;
int servoAngle = 0;//当前舵机角度(0-180)

IRrecv irrecv(infraredPin);//初始化红外接收器对象
decode_results results;//定义results变量为红外结果存放位置

void setup() {
	//红外接收器端口初始化
	pinMode(infraredPin, INPUT);
	//舵机端口初始化
	pinMode(servo1Pin, OUTPUT);
	pinMode(servo2Pin, OUTPUT);
	//led端口初始化
	pinMode(ledPin, OUTPUT);
	//波特率9600
	Serial.begin(9600);
	//启动红外解码
	irrecv.enableIRIn();
}

void loop() {
	//检测红外信号
	int isClick = LOW;
	if (irrecv.decode(&results)) {//是否接收到解码数据,把接收到的数据存储在变量results中
		Serial.println(results.value, HEX);//接收到的数据以16进制的方式在串口输出//接收到的数据以16进制的方式在串口输出
		if (results.value == INFRARED_LEFT ) {//遥控器按下了左键,转到最左边
			led(ledPin, HIGH);
			servopulse(servo1Pin, 180, 30);
			servopulse(servo2Pin, 180, 30);
		} else if (results.value == INFRARED_RIGHT ) {//遥控器按下了右键,转到最右边
			led(ledPin, HIGH);
			servopulse(servo1Pin, 1, 30);
			servopulse(servo2Pin, 1, 30);
		} else if (results.value == INFRARED_UP ) {//遥控器按下了上键,左转20度
			led(ledPin, HIGH);
			servopulse(servo1Pin, servoAngle + 20, 10);
			servopulse(servo2Pin, servoAngle + 20, 10);
		} else if (results.value == INFRARED_DOWN ) {//遥控器按下了下键,右转20度
			led(ledPin, HIGH);
			servopulse(servo1Pin, servoAngle - 20, 10);
			servopulse(servo2Pin, servoAngle - 20, 10);
		}
		irrecv.resume(); // 继续等待接收下一组信号
	}

	//led熄灭
	delay(300);
	led(ledPin, LOW);
}

/* 向舵机发送移动角度指令 */
void servopulse(int pin, int angle, int stepval){
	if (angle > 180) {
		angle = 180;
	} else if (angle < 1) {
		angle = 1;
	}
	Serial.print("moving servo to ");
	Serial.print(angle, DEC);
	Serial.println();

	int pulsewidth = (angle * 11) + 500; //将角度转化为500-2480 的脉宽值
	for (i = 0; i < stepval; i++) {
		digitalWrite(pin, HIGH); //将舵机接口电平置高
		delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
		digitalWrite(pin, LOW); //将舵机接口电平置低
		delay(20 - pulsewidth / 1000); //延时周期内剩余时间
	}
	servoAngle = angle;
}

/* 控制led灯亮起或熄灭 */
void led(int pin, int output) {
	digitalWrite(pin, output);
	//delay(500);
}

下一步,等做虫子脚用的铁丝寄到了,到时再继续实现虫子走路,困了,睡觉。

yan 2016.9.8 23:50

发表评论

电子邮件地址不会被公开。