JAVA-PI4J 树莓派利用PCA9685操控舵机

 为了用JAVA操控舵机,用了很长的时间学习,现在来分享一下。

介绍舵机

舵机-SG90
 对于舵机来说,控制其转动不像直流电机那样连接电池就可以了,而是对输入信号有一定的要求。输入信号的脉冲宽度决定着舵机转动角度。这里是指一个周期内的脉冲宽度,通常一个周期是20ms。(通常来说 0.5ms宽度应对应0° ,2.5ms宽度应对应180°)
 注意:舵机的控制并不是依据占空比,而是根据脉宽的绝对时长.
对应关系树莓派要想控制舵机运动,有两种方法

  1. 把舵机的控制端口直接连接到树莓派,显然由于针脚数目限制,这种方法有一定局限。(注意
    使用这种方法建议使用外接5V供电并且把供电的地线与树莓派地线相连)
  2. 利用PCA9685控制

介绍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的

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值