为了用JAVA操控舵机,用了很长的时间学习,现在来分享一下。
介绍舵机
对于舵机来说,控制其转动不像直流电机那样连接电池就可以了,而是对输入信号有一定的要求。输入信号的脉冲宽度决定着舵机转动角度。这里是指一个周期内的脉冲宽度,通常一个周期是20ms。(通常来说 0.5ms宽度应对应0° ,2.5ms宽度应对应180°)
注意:舵机的控制并不是依据占空比,而是根据脉宽的绝对时长.
树莓派要想控制舵机运动,有两种方法
- 把舵机的控制端口直接连接到树莓派,显然由于针脚数目限制,这种方法有一定局限。(注意
使用这种方法建议使用外接5V供电并且把供电的地线与树莓派地线相连) - 利用PCA9685控制
介绍PCA9685
PCA9685是一个舵机驱动板,最大可以控制16路的舵机,利用它可以很方便的解决舵机驱动问题。
PCA9685安装
一:首先,正确的连接树莓派
二:树莓派设置
sudo raspi-config
输入上方代码,选择Interfacing Options—>I2C 打开树莓派的IIC功能,然后等待重启。
sudo apt-get install i2c-tools
安装完毕之后,输入i2cdetect -y 0或i2cdetect -y 1结果如下
得到两个地址:0x40,0x70
控制原理:树莓派利用I2C向寄存器写入值,控制舵机,即使断电也不会影响配置,恢复之后还会是原来的位置。
通过JAVA操控PCA9685
上代码,详细的解释见代码注解
注意:这里是把舵机连接到PCA9685接口0号的位置。
import java.math.BigDecimal;
import com.pi4j.gpio.extension.pca.PCA9685GpioProvider;
import com.pi4j.gpio.extension.pca.PCA9685Pin;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinPwmOutput;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CFactory;
public class Main{
@SuppressWarnings("resource")
public static void main(String args[]) throws Exception {
System.out.println("Started");
BigDecimal frequency = new BigDecimal("50");
//设定舵机控制频率,一般来说是50hz,一个周期20ms
BigDecimal frequencyCorrectionFactor = new BigDecimal("1");
//设定修正因子,PCA9685的实际输出频率与设定的频率有误差 所以说需要修正,如果必须要纠正只需要填写1就好
I2CBus bus = I2CFactory.getInstance(I2CBus.BUS_1);
final PCA9685GpioProvider provider = new PCA9685GpioProvider(bus, 0x40, frequency, frequencyCorrectionFactor);
GpioPinPwmOutput[] myOutputs = provisionPwmOutputs(provider);
provider.reset();
Pin pin_0 = PCA9685Pin.ALL[0];
provider.setPwm(pin_0,0, 500);
//这里的第三个值与舵机控制角度有关
//计算公式:date=4096*((angle*11)+500)/20000
Thread.sleep(1000);
//这里要添加休眠 否则舵机可能来不及反应
provider.setPwm(pin_0,0, 300);
Thread.sleep(1000);
provider.setPwm(pin_0,0, 500);
Thread.sleep(1000);
provider.setPwm(pin_0,0, 300);
}
private static GpioPinPwmOutput[] provisionPwmOutputs(final PCA9685GpioProvider gpioProvider) {
GpioController gpio = GpioFactory.getInstance();
GpioPinPwmOutput myOutputs[] = {
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_00, "uesd"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_01, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_02, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_03, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_04, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_05, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_06, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_07, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_08, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_09, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_10, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_11, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_12, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_13, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_14, "not used"),
gpio.provisionPwmOutputPin(gpioProvider, PCA9685Pin.PWM_15, "not used")};
//注意这里要把所有的都给初始化
return myOutputs;
}
}
sudo javac -classpath .:classes:/opt/pi4j/lib/’’ Main.java
sudo java -classpath .:classes:/opt/pi4j/lib/’’ Main
编译运行就好
注1:数值计算公式来源
-
angle输入的角度值(0–180)
- pulsewidth高电平占空时间(0.5ms–2.5ms)
- 1000将us转换为ms #20ms时基脉冲(50HZ)
- pulse_width=((angle*11)+500)/1000; //将角度转化为500(0.5)<–>2480(2.5)的脉宽值(高电平时间) angle=180时 pulse_width=2480us(2.5ms)
- date/4096(date/分辨率)=pulse_width/20(占空比) ->有上pulse_width的计算结果得date=4096( ((angle11)+500)/1000 )/20 –>int date=4096((angle*11)+500)/20000;
注2:在PI4J安装目录里有很多示例程序,其中也有PCA9685的