2回答

1收藏

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

Raspberry Pi Raspberry Pi 6361 人阅读 | 2 人回复 | 2017-09-20

pca9685模块是16路的舵机控制板,目前正在捣鼓多轴机械臂,显然树莓派加一般的电机控制板就是在找虐,这个16路的舵机控制板显然是绝佳的方案。
树莓派操作硬件可以通过wiringpi的库,这个库实现了一些基本的硬件操作,其中就包括pca9685模块的通讯方式——iic。
之前写过通过命令行操作的方案,那个makefile简直反人类,添加头文件什么的搞到崩溃。相比之下qt就很和谐了,控制台应用管理整个工程。不过控制台应用人机交互性还是不怎么让人满足,自从开始搞linux,就对单片机的那套不感冒了,因此开发ui界面势在必行。
(一)舵机控制原理

20ms的周期长度、0.6-2.4ms的占空比。不过对于楼主使用的sg90舵机,占空比一般在0.5ms-1.5ms之间,所以以后者为准。
(二)pca9685原理
参考:http://blog.csdn.net/nicekwell/article/details/53616277

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

其中还要引入校正,具体看上述帖子。
所以说,如果我们想得到上述的占空比形式,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, 下载次数: 20

分享到:
回复

使用道具 举报

回答|共 2 个

倒序浏览

沙发

lygoing

发表于 2017-10-18 20:33:07 | 只看该作者

大神啊 带带我
板凳

day_day

发表于 2017-10-19 20:41:13 | 只看该作者

lygoing 发表于 2017-10-18 20:33
大神啊 带带我

本白白有什么好说的,大佬莫开我玩笑
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

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