爱板网论坛

查看: 115|回复: 0

[原创] 【BPI-M2 Berry试用】pca9685控制舵机

[复制链接]

11

主题

0

好友

255

积分

秀才

Rank: 3Rank: 3

  • TA的每日心情
    开心
    3 天前
  • 签到天数: 31 天

    连续签到: 3 天

    [LV.5]常住居民I

    发表于 2017-10-19 21:50:11 |显示全部楼层
    本帖最后由 day_day 于 2017-10-23 21:46 编辑

    (一)舵机控制原理
    2159278683su7u8sy32lkz.jpg

    20ms的周期长度、0.6-2.4ms的占空比。不过对于楼主使用的sg90舵机,通常的介绍占空比一般在0.5ms-1.5ms之间,不过楼主实测是在0.5ms-2.2ms之间,所以以后者为准。

    (二)pca9685介绍
    pca9685模块基于pca9685pw芯片,可以同时控制16路舵机,而控制线为iic,只占两路io口。还可以通过焊接改变读写地址,从而实现级联。
    215053eejnc2ndkb6uu764.jpg

    寄存器:
    pca9685.png

    第一第二位是模式控制; 从第七位(06)开始,每四位控制一路舵机信号。当ON匹配时,输出高电平(LEDX_ON_L==LEDX_ON_H);当OFF匹配时,输出低电平。 FE位控制占空比,计算公式:
    pca9685_rpe.jpg

    所以说,如果我们想得到上述的占空比形式,LEDX_ON_L=0,PRE_SCALE=osc_clock/4096*T - 1;

    (三)wiringPi操作函数
    初始化:wiringPiI2CSetup
    写:wiringPiI2CWriteReg8
    读:wiringPiI2CReadReg8

    (四)代码
    读写模块:
    1. #include "iic_pwm.h"

    2. #define PCA9685_SUBADR1 0x2
    3. #define PCA9685_SUBADR2 0x3
    4. #define PCA9685_SUBADR3 0x4

    5. #define PCA9685_MODE1 0x0
    6. #define PCA9685_PRESCALE 0xFE

    7. #define LED0_ON_L 0x6
    8. #define LED0_ON_H 0x7
    9. #define LED0_OFF_L 0x8
    10. #define LED0_OFF_H 0x9

    11. #define ALLLED_ON_L 0xFA
    12. #define ALLLED_ON_H 0xFB
    13. #define ALLLED_OFF_L 0xFC
    14. #define ALLLED_OFF_H 0xFD

    15. int pca9685_init(unsigned char addr)        // addr是7位的i2c从机地址,返回的是linux标准的设备描述符,调用它的地方视作pca9685的设备描述符
    16.                                                                                 //因为可以多个pca9685级联,通过设备描述符区别它们
    17.                                                                                 //此驱动仅作为驱动舵机使用,周期固定死位20ms,不允许外部设置
    18. {
    19.         int pca9685;
    20.         pca9685 = wiringPiI2CSetup(addr);
    21.         {        
    22.                 //初始化pca9685芯片
    23.                 double T = 20000;        //周期,单位是us
    24.                 unsigned char prescale;
    25.                 double osc_clock = 25000000;
    26.                 unsigned char oldmode, newmode;
    27.                 T /= 0.915;        //不知道为什么,会有所偏差,这里校准一下就ok了,从网上找的arduino代码也进行了校准。
    28.                 T /= 1000000;        //把T转换成秒
    29.                 prescale = (unsigned char)(osc_clock / 4096 * T - 1);
    30.                 //        printf("prescale = 0x%x", prescale);
    31.                 oldmode = wiringPiI2CReadReg8(pca9685, PCA9685_MODE1);
    32.                 newmode = (oldmode & 0x7f) | 0x10;        //准备进入sleep,设置时钟前必须先进入sleep模式
    33.                 wiringPiI2CWriteReg8(pca9685, PCA9685_MODE1, newmode);
    34.                 wiringPiI2CWriteReg8(pca9685, PCA9685_PRESCALE, prescale);
    35.                 oldmode &= 0xef;        //清除sleep位
    36.                 wiringPiI2CWriteReg8(pca9685, PCA9685_MODE1, oldmode);
    37.                 delay(0.005);
    38.                 wiringPiI2CWriteReg8(pca9685, PCA9685_MODE1, oldmode | 0xa1);
    39.         }

    40.         return pca9685;
    41. }

    42. void pca9685_setmk(int fd, int num, int mk)        //设置指定通道的脉宽。fd是在pca9685_init时获得的设备描述符,num是通道号(从0开始),mk是脉宽单位是us。周期已经固定为20ms了
    43. {
    44.         unsigned int ON, OFF;
    45.         ON = 0;        //每次周期一开始就输出高电平
    46.         OFF = (unsigned int)((((double)mk) / 20000 * 4096)*1.0067114);        //最后的1.0067114是校准用的
    47.         //    printf("off = 0x%x", OFF);

    48.         wiringPiI2CWriteReg16(fd, LED0_ON_L + 4 * num, ON);
    49.         wiringPiI2CWriteReg16(fd, LED0_OFF_L + 4 * num, OFF);
    50. }
    复制代码
    ui与控制设计:
    1. #include "widget.h"
    2. #include "ui_widget.h"

    3. #include <QtGui>
    4. #include <QGridLayout>
    5. #include <QDebug>
    6. #include <QErrorMessage>

    7. Widget::Widget(QWidget *parent) :
    8.     QWidget(parent),
    9.     ui(new Ui::Widget)
    10. {
    11.     ui->setupUi(this);

    12.     iic_fd = pca9685_init(0x40);

    13.         lineEdit = new QLineEdit("600");

    14.         slider = new QSlider(Qt::Horizontal);
    15.         slider->setMinimum(500);
    16.         slider->setMaximum(2200);
    17.         slider->setValue(600);


    18.         connect(slider, SIGNAL(sliderReleased()), this, SLOT(sendValue()));
    19.         connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setLineEditValue()));
    20.         connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(setSliderValue()));

    21.         QGridLayout *layout = new QGridLayout();
    22.         layout->addWidget(lineEdit, 0, 0, 1, 3);
    23.         layout->addWidget(slider, 0, 3, 1, 1);

    24.         this->setLayout(layout);
    25.         this->resize(500, 100);
    26.         this->setWindowTitle("QSliderDemo");
    27. }

    28. Widget::~Widget()
    29. {
    30.     delete ui;
    31. }

    32. void Widget::setLineEditValue()
    33. {
    34.     int pos = slider->value();
    35.     QString str = QString("%1").arg(pos);
    36.     lineEdit->setText(str);

    37. }

    38. void Widget::sendValue()
    39. {
    40.     pca9685_setmk(iic_fd, 0, slider->value());
    41.     qDebug() << "no time" << endl;
    42. }

    43. void Widget::setSliderValue()
    44. {
    45.     bool ok;
    46.     int dec = lineEdit->text().toInt(&ok, 10);

    47.     if (dec<500 || dec>2200)
    48.     {
    49.         QErrorMessage *errordialog = new QErrorMessage(this);
    50.         errordialog->setWindowTitle(tr("over value!"));
    51.         errordialog->showMessage(tr("over value!"));
    52.     }
    53.     else
    54.         slider->setValue(dec);

    55.     pca9685_setmk(iic_fd, 0, dec);

    56.     qDebug() << "once" << endl;
    57. }
    复制代码
    (五)编译
    对于bananapi的wiringpi函数库,编译的时候要在pro文件中加入-lwiringPi和-lcrypt两个库:
    1. LIBS    +=  -lwiringPi -lcrypt
    复制代码
    (六)硬件接线:
    N$}PVD}}]2_9MSRH)Q8[R.jpg

    这里使用SDA1、SCL1,对应的是系统第二条iic总线

    IMG_20171021_174711.jpg

    IMG_20171021_174732.jpg


    (七)视频效果和工程分享

    one.rar

    716.9 KB, 阅读权限: 10, 下载次数: 0

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /2 下一条

    手机版|爱板网 |网站地图  

    GMT+8, 2017-11-21 08:46 , Processed in 0.224907 second(s), 11 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部