查看: 4523|回复: 2

[经验] 基于qt+wiringPi pca9685开发系列——简单的qt控制界面

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-10 08:31
  • 签到天数: 300 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2017-9-20 22:04:18 | 显示全部楼层 |阅读模式
    分享到:
    pca9685模块是16路的舵机控制板,目前正在捣鼓多轴机械臂,显然树莓派加一般的电机控制板就是在找虐,这个16路的舵机控制板显然是绝佳的方案。
    树莓派操作硬件可以通过wiringpi的库,这个库实现了一些基本的硬件操作,其中就包括pca9685模块的通讯方式——iic。
    之前写过通过命令行操作的方案,那个makefile简直反人类,添加头文件什么的搞到崩溃。相比之下qt就很和谐了,控制台应用管理整个工程。不过控制台应用人机交互性还是不怎么让人满足,自从开始搞linux,就对单片机的那套不感冒了,因此开发ui界面势在必行。
    (一)舵机控制原理
    e23cfbfe18bad7a5d0420acb392c8951.jpg
    20ms的周期长度、0.6-2.4ms的占空比。不过对于楼主使用的sg90舵机,占空比一般在0.5ms-1.5ms之间,所以以后者为准。
    (二)pca9685原理
    参考:http://blog.csdn.net/nicekwell/article/details/53616277
    d8b9bd1ef8834f3ae8d2bf767c8c23f5.png
    第一第二位是模式控制;
    从第七位(06)开始,每四位控制一路舵机信号。当ON匹配时,输出高电平(LEDX_ON_L==LEDX_ON_H);当OFF匹配时,输出低电平。
    FE位控制占空比,计算公式:
    0818c324d06d592c01e3b0d31e7760b8.jpg
    其中还要引入校正,具体看上述帖子。
    所以说,如果我们想得到上述的占空比形式,LEDX_ON_L=0,PRE_SCALE=osc_clock/4096*T - 1;
    (三)qt程序
    pca9685控制的源文件可以参考上面那个博客,不过由于引入的代码是c代码,而ui界面是c++的界面,所以必须经过一些转化处理,否则会报错。
    1. /*
    2. 这个驱动是在树莓派的wiringPi基础上的,基于wiringPi对i2c的接口函数。
    3. 此驱动的使用方法是:
    4. 1、先用 pca9685_init(从机地址) 初始化,得到一个设备描述符(int型),这个设备描述符代表这个pca9685芯片,因为可能多个pca9685级联,通过这个设备描述符来区分它们。
    5. 它的
    6. 2、调用 pca9685_setmk
    7. */

    8. #ifndef PCA9685_WIRINGPI_H
    9. #define PCA9685_WIRINGPI_H
    10. #include <wiringPi.h>

    11. #ifdef __cplusplus
    12. extern "C" {
    13. #endif

    14. int pca9685_init(unsigned char addr);        // addr是7位的i2c从机地址,返回的是linux标准的设备描述符,调用它的地方视作pca9685的设备描述符
    15.                                         //因为可以多个pca9685级联,通过设备描述符区别它们
    16.                                         //此驱动仅作为驱动舵机使用,周期固定死位20ms,不允许外部设置
    17. void pca9685_setmk(int fd, int num, int mk);

    18. #ifdef __cplusplus
    19. }
    20. #endif
    21.                                         //设置指定通道的脉宽。fd是在pca9685_init时获得的设备描述符,num是通道号(从0开始),mk是脉宽单位是us。周期已经固定为20ms了

    22. #endif
    复制代码
    添加了extern "C"就可以在c++工程中调用c代码。
    ui界面程序如下:
    Dialog.h:
    1. #ifndef DIALOG_H
    2. #define DIALOG_H

    3. #include <QDialog>
    4. #include"iic_pwm.h"

    5. class QLineEdit;
    6. class QSlider;

    7. namespace Ui {
    8. class Dialog;
    9. }

    10. class Dialog : public QDialog
    11. {
    12.     Q_OBJECT
    13.    
    14. public:
    15.     explicit Dialog(QWidget *parent = 0);
    16.     ~Dialog();
    17.    
    18. signals:

    19. public slots:
    20.   void setLineEditValue();
    21.   void sendValue();
    22.     void setSliderValue();

    23. private:
    24.     Ui::Dialog *ui;
    25.     QLineEdit *lineEdit;
    26.     QSlider *slider;
    27.     int iic_fd;
    28. };

    29. #endif // DIALOG_H
    复制代码
    Dialog.c:
    1. #include "dialog.h"
    2. #include "ui_dialog.h"

    3. #include <QtGui/QLineEdit>
    4. #include <QtGui/QSlider>
    5. #include <QtGui/QHBoxLayout>
    6. #include <QDebug>
    7. #include <QErrorMessage>

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

    13.     iic_fd=pca9685_init(0x40);

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

    15.     //新建一个水平方向的滑动条QSlider控件
    16.     slider = new QSlider(Qt::Horizontal);
    17.     //设置滑动条控件的最小值
    18.     slider->setMinimum(500);
    19.     //设置滑动条控件的最大值
    20.     slider->setMaximum(1500);
    21.     //设置滑动条控件的值
    22.     slider->setValue(600);

    23.     //信号和槽 当滑动条的值发生改变时,即产生一个valueChanged(int)信号 设置QLineEdit控件的显示文本
    24.     connect(slider, SIGNAL(sliderReleased()), this, SLOT(sendValue()));
    25.     connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setLineEditValue()));
    26.     connect(lineEdit,SIGNAL(editingFinished()),this,SLOT(setSliderValue()));

    27.       QGridLayout *layout = new QGridLayout();
    28.       layout->addWidget(lineEdit,0,0,1,3);
    29.       layout->addWidget(slider,0,3,1,1);

    30.       this->setLayout(layout);
    31.       this->resize(500,100);
    32.       this->setWindowTitle("QSliderDemo");

    33. }

    34. Dialog::~Dialog()
    35. {
    36.     delete ui;
    37. }

    38. void Dialog::setLineEditValue()
    39. {
    40.     int pos = slider->value();
    41.     QString str = QString("%1").arg(pos);
    42.     lineEdit->setText(str);

    43. }

    44. void Dialog::sendValue()
    45. {
    46.     pca9685_setmk(iic_fd,0,slider->value());
    47.     qDebug()<<"no time"<<endl;
    48. }

    49. void Dialog::setSliderValue()
    50. {
    51.     bool ok;
    52.     int dec=lineEdit->text().toInt(&ok,10);

    53.     if(dec<500||dec>1500)
    54.     {
    55.         QErrorMessage *errordialog= new QErrorMessage(this);
    56.         errordialog->setWindowTitle(tr("over value!"));
    57.         errordialog->showMessage(tr("over value!"));
    58.     }
    59.     else
    60.        slider->setValue(dec);

    61.     pca9685_setmk(iic_fd,0,dec);

    62.     qDebug()<<"once"<<endl;
    63. }
    复制代码
    之后我会继续发布关于qt-qt的socket控制、qt-android的socket控制源码分享。

    pro文件中加上这句:
    1. LIBS += -wiringPi
    复制代码

    pca9685.zip

    6.33 KB, 阅读权限: 10, 下载次数: 17

    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2017-10-18 20:34
  • 签到天数: 19 天

    连续签到: 4 天

    [LV.4]偶尔看看III

    发表于 2017-10-18 20:33:07 | 显示全部楼层
    大神啊 带带我
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-4-10 08:31
  • 签到天数: 300 天

    连续签到: 1 天

    [LV.8]以坛为家I

     楼主| 发表于 2017-10-19 20:41:13 | 显示全部楼层
    lygoing 发表于 2017-10-18 20:33
    大神啊 带带我

    本白白有什么好说的,大佬莫开我玩笑
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

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



    手机版|小黑屋|与非网

    GMT+8, 2024-4-26 06:21 , Processed in 0.129534 second(s), 19 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.