树莓派通过PCA9685控制FT2331M舵机(Python)

11 篇文章 0 订阅
3 篇文章 0 订阅

        很久之前整过PWM舵机,刚好最近师弟需要,并且网上现有教程不是很完整,就整理一下。方便交流以及后面回顾。

        首先要明确,在这个控制方式中需要用到哪些方面:

1、树莓派与PCA9685之间使用I2C通信

2、PCA9685通讯协议

3、FT2331M舵机性能参数

        一、树莓派与PCA9685 I2C通信

        接线        

        接线方式可如下图所示,参考树莓派4B使用PCA9685控制舵机

         其中VCC供电为6V.

        开启I2C:

        在终端执行:

sudo raspi-config
Interfacing Options-->I2C-->YES-->Finish 

        保险起见 重启树莓派 终端输入 :

sudo reboot

        安装相关库文件:

sudo apt-get update
sudo apt-get install python-pip 
sudo pip install RPi.GPIO
sudo apt-get install python-smbus

        开启I2C并且完成树莓派与PCA9685接线之后,可以通过如下命令查看设备是否正常搭载:

ls /dev/*i2c*

        查看I2C搭载设备地址:

pi@raspberrypi:~ $ sudo i2cdetect -y 1  # 默认为I2C1,如果是I2C0.则只需要将1-->0即可

        关于I2C设备的操作,详细可看之前的文章关于树莓派4B两个I2C通道(I2C0、I2C1)的总结 。

        二、PCA9685通讯协议

相关代码我放在文中,并且有具体注释

from __future__ import division
import logging
import time
import math


# Registers/etc:
PCA9685_ADDRESS    = 0x40
MODE1              = 0x00
MODE2              = 0x01
SUBADR1            = 0x02
SUBADR2            = 0x03
SUBADR3            = 0x04
PRESCALE           = 0xFE
LED0_ON_L          = 0x06
LED0_ON_H          = 0x07
LED0_OFF_L         = 0x08
LED0_OFF_H         = 0x09
ALL_LED_ON_L       = 0xFA
ALL_LED_ON_H       = 0xFB
ALL_LED_OFF_L      = 0xFC
ALL_LED_OFF_H      = 0xFD

# Bits:
RESTART            = 0x80
SLEEP              = 0x10
ALLCALL            = 0x01
INVRT              = 0x10
OUTDRV             = 0x04


logger = logging.getLogger(__name__)


def software_reset(i2c=None, **kwargs):
    """Sends a software reset (SWRST) command to all servo drivers on the bus."""
    # Setup I2C interface for device 0x00 to talk to all of them.
    if i2c is None:
        import Adafruit_GPIO.I2C as I2C
        i2c = I2C
    self._device = i2c.get_i2c_device(0x00, **kwargs)
    self._device.writeRaw8(0x06)  # SWRST


class PCA9685(object):
    """PCA9685 PWM LED/servo controller."""

    def __init__(self, address=PCA9685_ADDRESS, i2c=None, **kwargs):
        """Initialize the PCA9685."""
        # Setup I2C interface for the device.
        if i2c is None:
            import Adafruit_GPIO.I2C as I2C
            i2c = I2C
        self._device = i2c.get_i2c_device(address, **kwargs)
        self.set_all_pwm(0, 0)
        self._device.write8(MODE2, OUTDRV)
        self._device.write8(MODE1, ALLCALL)
        time.sleep(0.005)  # wait for oscillator
        mode1 = self._device.readU8(MODE1)
        mode1 = mode1 & ~SLEEP  # wake up (reset sleep)
        self._device.write8(MODE1, mode1)
        time.sleep(0.005)  # wait for oscillator

    def set_pwm_freq(self, freq_hz):
        """Set the PWM frequency to the provided value in hertz."""
        prescaleval = 25000000.0    # 25MHz
        prescaleval /= 4096.0       # 12-bit
        prescaleval /= float(freq_hz)
        prescaleval -= 1.0
        logger.debug('Setting PWM frequency to {0} Hz'.format(freq_hz))
        logger.debug('Estimated pre-scale: {0}'.format(prescaleval))
        prescale = int(math.floor(prescaleval + 0.5))
        logger.debug('Final pre-scale: {0}'.format(prescale))
        oldmode = self._device.readU8(MODE1);
        newmode = (oldmode & 0x7F) | 0x10    # sleep
        self._device.write8(MODE1, newmode)  # go to sleep
        self._device.write8(PRESCALE, prescale)
        self._device.write8(MODE1, oldmode)
        time.sleep(0.005)
        self._device.write8(MODE1, oldmode | 0x80)

    def set_pwm(self, channel, on, off):
        """Sets a single PWM channel."""
        self._device.write8(LED0_ON_L+4*channel, on & 0xFF)
        self._device.write8(LED0_ON_H+4*channel, on >> 8)
        self._device.write8(LED0_OFF_L+4*channel, off & 0xFF)
        self._device.write8(LED0_OFF_H+4*channel, off >> 8)

    def set_all_pwm(self, on, off):
        """Sets all PWM channels."""
        self._device.write8(ALL_LED_ON_L, on & 0xFF)
        self._device.write8(ALL_LED_ON_H, on >> 8)
        self._device.write8(ALL_LED_OFF_L, off & 0xFF)
        self._device.write8(ALL_LED_OFF_H, off >> 8)
    
    def cmd(self, channel, Position):
        '''
        已经进行数据转换,position范围0-210度
        '''
        '''
        PCA9685是一种PWM控制器,可以产生从0到4096之间的脉宽值,对应于PWM信号的高电平时间
        PWM频率被设置为60Hz,周期的时间为 1 / 60 秒,即约 16.67 毫秒(16666 微秒)
        servo_min = 150  # Min pulse length out of 4096
        servo_max = 600  # Max pulse length out of 4096
        servo_min 的实际脉宽时间为 (150 / 4096) * 16666 微秒 ≈ 610 微秒
        servo_max 的实际脉宽时间为 (600 / 4096) * 16666 微秒 ≈ 2440 微秒
        Ft2331舵机参数为0~240°对应500~2500us
        '''
        servo_min = int(500 * 60 / 1000000 * 4096)  # Min pulse length out of 4096
        servo_max = int(2500 * 60 / 1000000 * 4096)  # Max pulse length out of 4096
        
        Position = int(Position / (240 - 0) * (servo_max - servo_min) + servo_min)  # 240这个数值需对每个舵机进行标定,有可能需要增大,有可能需要减小
        
        self.set_pwm(channel, 0, Position)



pwm = PCA9685()
pwm.set_pwm_freq(60)
channel = 0

while True:
    
    pwm.cmd(channel, 0)
    time.sleep(1)
    
    pwm.cmd(channel, 90)
    time.sleep(1)
    
    pwm.cmd(channel, 180)
    time.sleep(1)
    
    pwm.cmd(channel, 90)
    time.sleep(1)

        三、FT233M1舵机参数

 舵机控制参数如下所示:

        从旋转角度那一栏可知,舵机由0-240°,对应周期时间为500-2500us。 

所以在第二节中的协议中,控制函数cmd(self, channel, Position)中存在(同样和通信频率有关),如下代码:

'''
        PCA9685是一种PWM控制器,可以产生从0到4096之间的脉宽值,对应于PWM信号的高电平时间
        PWM频率被设置为60Hz,周期的时间为 1 / 60 秒,即约 16.67 毫秒(16666 微秒)
        servo_min = 150  # Min pulse length out of 4096
        servo_max = 600  # Max pulse length out of 4096
        servo_min 的实际脉宽时间为 (150 / 4096) * 16666 微秒 ≈ 610 微秒
        servo_max 的实际脉宽时间为 (600 / 4096) * 16666 微秒 ≈ 2440 微秒
        Ft2331舵机参数为0~240°对应500~2500us
        '''
        servo_min = int(500 * 60 / 1000000 * 4096)  # Min pulse length out of 4096
        servo_max = int(2500 * 60 / 1000000 * 4096)  # Max pulse length out of 4096
        
        Position = int(Position / (240 - 0) * (servo_max - servo_min) + servo_min)  # 240这个数值需对每个舵机进行标定,有可能需要增大,有可能需要减小

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.1python软件的安装 先安装python软件优先,因为其他步骤如果用到sudo apt-get update 会导致python程序不是py2而是py3,就用不了我们的程序了 树莓派鼓励用户使用python和C++作为其开发语言,所以原则上可以不用安装python的编译器,但是树莓派自带的python(IDLE)和Thonny python IDE都过于简陋,不太适合python使用者进行复杂的OpenCV开发。在这里推荐Spyder作为树莓派python IDE。这种编译器相对上述两种编译器略显笨重,但是对内核和运算值的控制更加灵活。   树莓派安装Spyder非常的方便,在命令行输入: sudo apt-get install spyder 下载时间可能比较长,因为在安装spyder3的同时很多python开发开发必要的依赖也一并被安装到树莓派里了,这也说明牺牲一定的空间下载spyder3是值得的。此时,我们已经可以在树莓派的开始菜单-programming中看到编译器了。注意: 1、 在下载spyder之前请不要输入 “sudo apt-get update/upgrade”, 否则会下载适用于python3.6的spyder,无法正常使用,比如图1-0中的spyder的python版本就是3.6,说明下载出现错误。 2、 如果看不到编译器说明安装过程出错,尝试重新执行:sudo apt-get update和 sudo apt-get install spyder3两条命令。   图 1-0下载完成后,在“start”中已经能看到Spyder编译器了     图 1-00 Spyder3的Python3.6版本 我们可以在preference/syntax coloring scheme中更换自己喜欢的主题,怎么样?是不是已经觉得树莓派和普通PC一样方便了呢?现在我们已经可以用在树莓派上舒适的开发python了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值