Qt 开发固高运动控制卡(高创驱动器)上位机程序

发布时间 2023-08-09 10:10:20作者: 一杯清酒邀明月

  在一些控制多轴电机运动的场景下,除了需要驱动器驱动该轴的电机外,还需要用到控制卡协调各轴驱动器的运动控制。为了方便用户使用,往往还需要编写满足功能需求的上位机程序。为了方便演示Qt开发固高控制卡上位机程序的过程,这里基于Qt 5.9.0和C++实现的是最一般的上位机功能,包括运动控制卡的初始化、使能、Z轴的点位运动功能(需要用户输入点位运动的参数:行程、速度、加速度和减速度)。控制对象是Z轴方向运动的光学显微平台。使用顺序:初始化→使能→给定Pos,Vel,Acc,Dcc→写入→点击“下”即电机向下运动。

 本文演示的上位机程序界面

 控制对象:光学显微平台

  硬件部分采用GTS-VB系列4轴插卡式固高运动控制卡作为上层规划指令的发送者,与固高运动控制卡搭配使用的还有端子板。控制卡通过PCI总线插槽与上位机进行通讯,同时控制卡通过CN17连接线连接端子板,端子板上有一系列IO口和轴接口,通过轴接口可以连接各轴驱动器。这里使用的是高创驱动器。

 控制系统示意图

GTS-VB系列4轴插卡式固高运动控制卡

  我们使用固高控制卡的开环控制模式(脉冲控制),设置高创驱动器为位置齿轮模式。伺服系统的三环控制都在驱动器完成,关于高创驱动器控制算法的调试,请参考高创驱动器的用户手册。应用程序指令是上位机发出的运动规划、IO等指令,经过运动控制器转为底层的运动指令,最终以脉冲的形式发给驱动器。如果在使用过程中遇到复杂问题,可以进一步查阅官方手册《编程手册:GTS运动控制器-基本功能_R1.4》(固高的使用手册编写得还是对用户较为友好的,使用方法比较详细,同时有很多使用例程供用户参考)。

 固高控制卡的开环控制模式(脉冲控制)

1、配置驱动器

  首先,配置高创驱动器,反馈采用增量式数字量光栅尺,分辨率为0.1μm(10000cnt=1mm),

 反馈设置

  增量式数字量反馈的每转线数=电机节距/光栅尺分辨率/4倍频,然后需要根据实际需求整定高创的控制器参数,使得运动平台的定位精度和响应满足要求。在此就不赘述了。

 数字I/O设置

  在数字IO中需要设置远端使能(remote enable)。

 设置运动模式

  因为电机的每转线数是120000LPP,而在位置齿轮模式中的“转外部脉冲”是每转脉冲数,脉冲与线数之间是4倍关系,因此“转外部脉冲”设置为480000。“电子齿轮分子”和“电子齿轮分母”均可设置为1,表示固高每发送10000cnt电机就运动1mm。这里设置为-1是因为期望的方向与实际电机运动方向相反。

2、配置固高控制卡

  下一步是通过固高控制卡自带的上位机软件MCT2008配置固高控制卡。在Windows系统下使用运动控制器,首先要安装驱动程序和动态链接库。驱动程序和动态链接库请通过固高科技官网固高科技 (googoltech.com.cn)下载。安装过程和使用方法可以参考固高相应的使用手册。

 打开MCT2008软件,开环模式下 axis 配置流程如下(参考《编程手册:GTS运动控制器-基本功能_R1.4》——4.5.1 开环控制模式):

 固高控制卡自带的上位机软件MCT2008

  在“工具”-“控制器配置”中,设置需要运动的轴(这里为轴3),将“axis”这一项红框中的各个编号都设置为“none”,然后选择控制器配置中的“控制”-“写入控制器状态”,此时在“视图”-“轴状态”-3轴状态可以看到指示灯都为绿色,表明各个状态都无错误。其他设置则选择默认。

  点击“伺服使能”按钮可以使能电机,指示灯为红色。在“视图”-“点位运动”可以打开点位运动窗口,点击“启动运动”即可启动电机。

在“控制器配置”窗口中,点击“文件”-“写入到文件”可以将上述配置保存成.cfg文件,以便后续上位机使用。

 保存控制卡的配置文件

3、编写上位机程序

  最简单的开发可以参考实现与固高上位机功能类似的上位机软件。首先导入固高控制卡的动态链接库,要使用的是dll\VC\64bit\single_card中的3个文件:gts.dll,gts.h和gts.lib,将这3个文件复制到Qt工程目录下面,

 复制需要的3个文件

 放到Qt工程目录下

然后需要在Qt中指定链接库,右击项目,添加“外部库”,添加当前项目目录下的gts.lib库文件,

 在Qt中指定链接库

同时还需要添加gts.h头文件到Qt项目中,

  通过调用库文件中相关的API接口函数来实现相应的功能。固高控制卡封装好的API接口函数都是GT_开头的,可以直接在程序中调用,而且官方手册《编程手册:GTS运动控制器-基本功能_R1.4》(还有高级功能版本则主要涉及控制卡的PT运动模式、PVT运动模式等,这里没有涉及到就不作介绍了)也对函数的使用方法有很详细的例程,很多语句甚至可以直接复制到上位机程序中。

  接着开始设计用户界面,这里包括了初始化按钮pbn_Init、使能按钮pbn_Enable、写入按钮pbn_Write、向上运动按钮pbn_Up、向下运动按钮pbn_Down和行程、速度、加速度、减速度输入框lineEdit_Pos、lineEdit_Vel、lineEdit_Acc和lineEdit_Dcc。其中使能按钮pbn_Enable需要勾选“checkable”属性,默认状况下checkable是不选中的,Button默认为触发按钮(trigger button),按下去马上弹起来。选中checkable后,Button变成切换按钮(toggle button),可以有两种状态:按下/弹起。因为电机有使能和去使能两种状态,对应的就是开关的开和关。当pbn_Enable处于按下状态的时候checked为true,否则为false。

 然后转到pbn_Enable的toggled(bool)信号的槽,编写使能按钮的槽函数(或者使用Lambda表达式):

 1 //使能按钮,槽函数
 2 void MainWindow::on_pbn_Enable_toggled(bool checked)
 3 {
 4     if (checked)
 5     {
 6         GT_AxisOn(this->Z_num);//Z轴打开驱动器使能
 7     }
 8     else
 9     {
10         GT_AxisOff(this->Z_num);//关闭驱动器使能
11     }
12 }

注:在连接信号和槽的时候,槽函数可以使用Lambda表达式的方式进行处理。在使用 Qt 5 的时候,能够支持 Qt 5 的编译器都是支持 Lambda 表达式的。

1 //使能按钮的Lambda表达式
2 connect(ui->pbn_Enable, &QPushButton::toggled, [=](){
3     if(ui->pbn_Enable->isChecked())
4         GT_AxisOn(this->Z_num);//Z轴打开驱动器使能
5     else
6         GT_AxisOff(this->Z_num);//Z轴打开驱动器使能
7 });

同样的可以编写初始化按钮pbn_Init的槽函数:

 1 //初始化按钮,槽函数
 2 void MainWindow::on_pbn_Init_clicked()
 3 {
 4     ui->pbn_Enable->setChecked(false);//关闭驱动器使能按钮
 5     GT_Open();//在使用运动控制器之前,首先需要使用 GT_Open 指令打开运动控制器,和运动控制器建立通讯;只要在应用程序初始化阶段调用一次 GT_Open
 6     GT_Reset();//调用 GT_Reset 指令将使运动控制器的所有寄存器恢复到默认状态,一般在打开运动控制器之后调用该指令。
 7     GT_LoadConfig("GTS800.cfg");//下载配置信息到运动控制器,调用该指令后需再调用 GT_ClrSts 才能使该指令生效
 8     GT_EncOff(3);//将轴3设置为“脉冲计数器”计数方式。
 9     GT_ClrSts(1,4);//清除驱动器报警标志、跟随误差越限标志、限位触发标志
10     flag = 1;
11 }

在实现点位运动按钮的功能之前,可以先编写点位运动函数:

 1 //点位运动函数,可参考固高编程手册基本功能例程 6-1 点位运动
 2 void MainWindow::pointMotion(int num,long pos)//参数num是轴号,pos是点位运动的距离
 3 {
 4     TTrapPrm trap;//点位运动模式的运动参数,该参数为一个结构体,包含四个参数:加速度,减速度,起跳速度和平滑时间
 5     GT_ZeroPos(num);//num轴位置清零
 6     GT_SetPrfPos(num, 0);//num轴规划位置清零
 7     GT_PrfTrap(num);//将num轴设为点位模式
 8     GT_GetTrapPrm(num, &trap);//读取点位运动参数(需要读取所有运动参数到上位机变量)
 9     // 设置需要修改的运动参数
10     trap.acc = this->Acc;
11     trap.dec = this->Dcc;
12     trap.smoothTime = 0;//这里假设平滑时间为0
13     GT_SetTrapPrm(num, &trap);//设置点位模式运动下的运动参数
14     GT_SetPos(num, pos);//设置num轴的目标位置
15     GT_SetVel(num, this->Vel);//设置num轴的目标速度
16     GT_Update(1<<(num-1));//启动num轴的运动
17 }

然后用户通过输入框指定点位运动的四个参数,再点击写入按钮pbn_Write保存运动参数:

 1 //写入按钮,槽函数
 2 void MainWindow::on_pbn_Write_clicked()
 3 {
 4     QString str1;
 5     QString str2;
 6     QString str3;
 7     QString str4;
 8     str1 = ui->lineEdit_Pos->text();//Pos位置输入框的内容
 9     str2 = ui->lineEdit_Vel->text();
10     str3 = ui->lineEdit_Acc->text();
11     str4 = ui->lineEdit_Dcc->text();
12     if(str2 == NULL)
13         str2 = "20";//若输入框无内容,则程序设置速度、加速度和减速度的默认值
14 
15     if(str3 == NULL)
16         str3 = "1";
17 
18     if(str4 == NULL)
19         str4 = "1";
20     this->Pos = qAbs(str1.toLong());//将string类型转换为long类型
21     this->Vel = qAbs(str2.toDouble());
22     this->Acc = qAbs(str3.toDouble());
23     this->Dcc = qAbs(str4.toDouble());
24 }

最后,两个运动按钮可直接调用上述函数:

 1 //向上运动按钮,槽函数
 2 void MainWindow::on_pbn_Up_clicked()
 3 {
 4     if(flag == 1)
 5     {
 6         pointMotion(Z_num,this->Pos);//开始点位运动
 7     }
 8 }
 9 
10 //向下运动按钮,槽函数
11 void MainWindow::on_pbn_Down_clicked()
12 {
13     if(flag == 1)
14     {
15         pointMotion(Z_num,-this->Pos);//开始点位运动
16     }
17 }

完整的头文件和源代码文件程序如下:

mainwindow.h文件:

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 #include "gts.h"
 6 
 7 namespace Ui {
 8 class MainWindow;
 9 }
10 
11 class MainWindow : public QMainWindow
12 {
13     Q_OBJECT
14 
15 public:
16     explicit MainWindow(QWidget *parent = 0);
17     ~MainWindow();
18 
19     int Z_num = 3;              //Z轴对应轴号
20     int flag = 0;              //初始化标志
21     long Pos = 0;              //位置/速度/加速度/减速度 用户输入值
22     double Vel = 1;
23     double Acc = 1;
24     double Dcc = 1;
25     void pointMotion(int num,long pos);
26 
27 private slots:
28     void on_pbn_Init_clicked();//按钮“初始化”
29     void on_pbn_Enable_toggled(bool checked);//按钮“使能”
30     void on_pbn_Write_clicked();//按钮“写入”
31     void on_pbn_Up_clicked();//按钮“上”
32     void on_pbn_Down_clicked();
33 
34 private:
35     Ui::MainWindow *ui;
36 };
37 
38 #endif // MAINWINDOW_H

mainwindow.cpp文件:

  1 #include "mainwindow.h"
  2 #include "ui_mainwindow.h"
  3 
  4 MainWindow::MainWindow(QWidget *parent) :
  5     QMainWindow(parent),
  6     ui(new Ui::MainWindow)
  7 {
  8     ui->setupUi(this);
  9 
 10     this->setWindowTitle(tr("Z轴上位机实验"));
 11 
 12 //    //使能按钮的Lambda表达式
 13 //    connect(ui->pbn_Enable, &QPushButton::toggled, [=](){
 14 //        if(ui->pbn_Enable->isChecked())
 15 //            GT_AxisOn(this->Z_num);//Z轴打开驱动器使能
 16 //        else
 17 //            GT_AxisOff(this->Z_num);//Z轴打开驱动器使能
 18 //    });
 19 }
 20 
 21 MainWindow::~MainWindow()
 22 {
 23     GT_AxisOff(this->Z_num);//在析构函数中可以去使能,即关闭窗口的同时,电机去使能
 24     delete ui;
 25 }
 26 
 27 //点位运动函数,可参考固高编程手册基本功能例程 6-1 点位运动
 28 void MainWindow::pointMotion(int num,long pos)//参数num是轴号,pos是点位运动的距离
 29 {
 30     TTrapPrm trap;//点位运动模式的运动参数,该参数为一个结构体,包含四个参数:加速度,减速度,起跳速度和平滑时间
 31     GT_ZeroPos(num);//num轴位置清零
 32     GT_SetPrfPos(num, 0);//num轴规划位置清零
 33     GT_PrfTrap(num);//将num轴设为点位模式
 34     GT_GetTrapPrm(num, &trap);//读取点位运动参数(需要读取所有运动参数到上位机变量)
 35     // 设置需要修改的运动参数
 36     trap.acc = this->Acc;
 37     trap.dec = this->Dcc;
 38     trap.smoothTime = 0;//这里假设平滑时间为0
 39     GT_SetTrapPrm(num, &trap);//设置点位模式运动下的运动参数
 40     GT_SetPos(num, pos);//设置num轴的目标位置
 41     GT_SetVel(num, this->Vel);//设置num轴的目标速度
 42     GT_Update(1<<(num-1));//启动num轴的运动
 43 }
 44 
 45 //初始化按钮,槽函数
 46 void MainWindow::on_pbn_Init_clicked()
 47 {
 48     ui->pbn_Enable->setChecked(false);//关闭驱动器使能按钮
 49     GT_Open();//在使用运动控制器之前,首先需要使用 GT_Open 指令打开运动控制器,和运动控制器建立通讯;只要在应用程序初始化阶段调用一次 GT_Open
 50     GT_Reset();//调用 GT_Reset 指令将使运动控制器的所有寄存器恢复到默认状态,一般在打开运动控制器之后调用该指令。
 51     GT_LoadConfig("GTS800.cfg");//下载配置信息到运动控制器,调用该指令后需再调用 GT_ClrSts 才能使该指令生效
 52     GT_EncOff(3);//将轴3设置为“脉冲计数器”计数方式。
 53     GT_ClrSts(1,4);//清除驱动器报警标志、跟随误差越限标志、限位触发标志
 54     flag = 1;//初始化标志
 55 }
 56 
 57 //使能按钮,槽函数
 58 void MainWindow::on_pbn_Enable_toggled(bool checked)
 59 {
 60     if (checked)
 61     {
 62         GT_AxisOn(this->Z_num);//Z轴打开驱动器使能
 63     }
 64     else
 65     {
 66         GT_AxisOff(this->Z_num);//关闭驱动器使能
 67     }
 68 }
 69 
 70 //写入按钮,槽函数
 71 void MainWindow::on_pbn_Write_clicked()
 72 {
 73     QString str1;
 74     QString str2;
 75     QString str3;
 76     QString str4;
 77     str1 = ui->lineEdit_Pos->text();//Pos位置输入框的内容
 78     str2 = ui->lineEdit_Vel->text();
 79     str3 = ui->lineEdit_Acc->text();
 80     str4 = ui->lineEdit_Dcc->text();
 81     if(str2 == NULL)
 82         str2 = "20";//若输入框无内容,则程序设置速度、加速度和减速度的默认值
 83 
 84     if(str3 == NULL)
 85         str3 = "1";
 86 
 87     if(str4 == NULL)
 88         str4 = "1";
 89     this->Pos = qAbs(str1.toLong());//将string类型转换为long类型
 90     this->Vel = qAbs(str2.toDouble());
 91     this->Acc = qAbs(str3.toDouble());
 92     this->Dcc = qAbs(str4.toDouble());
 93 }
 94 
 95 //向上运动按钮,槽函数
 96 void MainWindow::on_pbn_Up_clicked()
 97 {
 98     if(flag == 1)
 99     {
100         pointMotion(Z_num,this->Pos);//开始点位运动
101     }
102 }
103 
104 //向下运动按钮,槽函数
105 void MainWindow::on_pbn_Down_clicked()
106 {
107     if(flag == 1)
108     {
109         pointMotion(Z_num,-this->Pos);//开始点位运动
110     }
111 }

  考虑到后续程序的发布,且debug版本程序依赖的dll文件很大,一般使用release版本。在Qt左下角的目标选择器(Target selector)中将构建目标设置为Release,编译后项目目录文件夹即包含了release目录,再将配置固高卡时生成的配置文件GTS800.cfg放到release目录下。

 至此完成了简单的上位机开发。