实现功能:
1.两步进电机分别使能和循环运动,可以设置循环次数、循环里分别运行的角度、旋转的速度和加减速度等等,在最下方的表格里显示发送和接收的CAN报文
2.读取水平电机当前位置和速度并画图显示,示波器暂停、缩放、滑动等功能
3.MCU监听串口IMU数据并通过TCP客户端发出
4.QT服务端接收TCP数据并进行解析,显示对应波形
监听TCP客户端
QT软件在初始化时,对指定TCP端口进行监听,并在成功连接后执行数据监听
Widget::Widget(QWidget *parent):
QWidget(parent),
ui(new Ui::Widget),
time(QTime::currentTime())
{
tcpServer = new QTcpServer(this); //创建一个服务器类
tcpSocket = new QTcpSocket(this); //创建一个socket类
tcpServer->listen(QHostAddress::Any,ui->portEdit->text().toUInt()); //服务器对端口号进行监听
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(newConnection_slot())); //有网络用户连接进来,就会执行槽函数
}
//当连接客户端tcp,执行相关函数
void Widget::newConnection_slot()
{
qDebug() << "connected";
tcpSocket = tcpServer->nextPendingConnection(); //获取与客户端进行通信的套接字
ui->TCPButton->setStyleSheet("background:rgb(85,255,127)");
connect(tcpSocket,&QTcpSocket::disconnected,this,&Widget::disonnection_slot); //有网络用户断开连接
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_slot())); //客户端有数据到达服务器,就会产生readyRead信号
}
//当客户端断开连接执行相关函数
void Widget::disonnection_slot(){
qDebug() << "disconnected";
ui->TCPButton->setStyleSheet("background:rgb(255,255,127)");//按钮变绿提示已连接
}
//当有数据来,更新波形图
void Widget::readyRead_slot()
{
int num = tcpSocket->read((char *)&imu_data_,sizeof(ImuData)*10);
for(int i=0;i<(num/112);i++){
PlotViewUpdate(1,imu_data_[i].gyro.z*PI/(180*16.4));
PlotViewUpdate(3,imu_data_[i].ypr.yaw);
}
//ui->receTCPEdit->setText(QString::number(imu_data_[0].cnt));
}
这里imu_data_为结构体类型,这样服务端就能一次性接收完数据,无需按照各个变量分别接收
struct ImuQuat {
double w;
double x;
double y;
double z;
};
struct ImuAcc {
int16_t x;
int16_t y;
int16_t z;
};
struct ImuGyro {
int16_t x;
int16_t y;
int16_t z;
};
struct ImuYpr {
double yaw;
double pitch;
double roll;
};
struct ImuData {
uint64_t timestamp;
ImuQuat quat;
ImuAcc acc;
ImuGyro gyro;
ImuGyro gyro_offset;
ImuYpr ypr;
uint16_t update_rate;
uint64_t cnt;
uint64_t imu_time;
};
ImuData imu_data_[10];
对于客户端,发送方式与之对应,imu_data_的数据格式与服务端一致
send(client_sockfd,(char*)&imu_data_,sizeof(ImuData),0);
CAN通信
使用ControlCAN库,需要对应版本,否则可以成功运行,但是Debug会报程序异常终止的错误
根据文档需要使能电机,激活操作模式为位置模式,同时设置运动参数,包括速度、加速度、减速度等,这样就完成了CAN电机的基本配置。
这里需要电机可以多段一直运行,设置电机的目标位置,启动多段运行。
在第一段运行后,执行CAN命令可以直接运行下一段
其中,数据的后四字节为数据,40 0D 03 00代表200000,而对应的十六进制为30D40,即按一字节划分,低位在前,符号位代表旋转的方向。
CAN PDO通信(过程数据对象)
SDO是发-收的形式,频率无法提升,在读取电机速度时频率只有5Hz,这里考虑用PDO自动发送的方式提升数据更新频率。
1.PDO映射对应的SDO报文
采用Tx-PDO2
节点地址:280h + 1=281 COB_ID范围1-7F
第一步:关闭PDO分配功能,把对应PDO的COB-ID的最高位置1;
关闭TPDO2,报文:23 01 18 01 80 02 00 80
第二步:清除原有有映射的内容,把0X1600~0X1603和0X1A00~1A03的子索引置0;
设置映射对象的数量为0,报文为:2F 01 1A 00 00 00 00 00
第三步:写入PDO映射内容;
映射对象0X606C到TPDO2的子索引1中,报文为:23 01 1A 01 40 00 6C 60 电机速度
映射对象0X6064到TPDO2的子索引2中,报文为:23 01 1A 02 40 00 64 60 电机位置
此时发送报文的格式为:
第四步:写入该PDO映射对象的总个数;
设置映射对象总数量为2,报文为2F 01 1A 00 02 00 00 00
第五步:重新打开PDO分配功能,把对应PDO的COB-ID的最高位置0;
开启TPDO2,报文:23 01 18 01 80 02 00 00
第六步:保存所有参数,给对象字典(OD)1010的子索引0x01中写入“65766173h”(ASCII码:save)时执行保存;处理完成后,无论是否成功,此对象的值自动恢复为0;
保存所有参数,报文:23 10 10 01 73 61 76 65
2.配置异步模式的报文
同步模式需要同步帧,这里采用异步模式,当无事件发生时,按照Event timer上传数据;当有事件发生时,数据会立即上传。
配置异步模式的步骤:
第一步:将NMT状态切换到运行状态;
将NMT状态切换到运行状态:01 01 将COB_ID设置000
第二步:配置异步TPDO通道;
配置异步模式:23 01 18 02 FF 00 00 00
第三步:如果要读取驱动器相关参数,需要把NMT状态机切换到运行状态;
第四步:改变相关参数,数据会立即上传;
第五步:异步模式下设置Event timer
异步模式下,设置Event timer:2B 01 18 05 D0 07 00 00(设置事件时间为2000ms),当无事件发生时,按照2s上传数据;当有事件发生时,数据会立即上传;