【飞凌OKA40i-C开发板试用体验】伺服电机控制完结篇

描述

本文来源电子发烧友社区,作者:刘建华, 帖子地址:https://bbs.elecfans.com/jishu_2309556_1_1.html


【话外】经过大伙的一个星期的努力,疫情得到控制,核酸检测社会面清零。今天,单位的领导热情的用鲜花迎接我们凯旋而归。

飞凌

飞凌
到家后立马投入到这个帖子的收尾工作,因为今天是最后一天提交作品。话不多说继续我的工作。
前面已经实现的界面的制作,今天完结伺服电机的控制。

1、生成电机控制指令,电机的指令是通过modbus(RTU 模式)来控制驱动器的。主机可以通过 modbus 的读写寄存器功能来设置驱动器参数和控制运行。这里只用到了功能码为 0x3(读寄存器)、0x6(写寄存器)这两个指令。指令格式如下:
飞凌

2、这里需要用到CRC16的较验。具体的函数如下:

quint16 MainWindow::CalcCRC16(quint8 *SC_Buffer, quint8 SC_Amount)//生成校验码
{
    quint16 Crc;
    quint8 n, m, x;

    Crc= 0xFFFF;//16个1
    m= SC_Amount;//拿到长度
    x= 0;

    while(m>0){
        Crc ^= SC_Buffer[x];//第一个数据帧异或
        for(n=0; n<8; n++){//因为是quint8是8位数据,所以循环8次
            if(Crc & 1){//移出位为1,就进行异或
                Crc >>= 1;
                Crc ^= 0xA001;
            }else//为0继续移出
                Crc >>= 1;
        }
        m--;//下一个数据帧
        x++;
    }

    x = Crc>>8;//拿到高8位
    Crc <<= 8;//剩下低8位
    Crc &= 0xff00;//低位清0
    Crc |= x;//实现高低位位置互换

    return Crc;
}

3、有了CRC16的较验后,组装设置使能电机命令如下:

void MainWindow::on_openMotorBut_clicked()
{
    QByteArray data;
    data.resize(8);
    quint8 crc[8];
    quint8 n;

    ui->textBrowser->insertPlainText("start clicked!n");
    if(ui->openMotorBut->text() == "启动电机")
    {
        //EN set
        crc[0] = 0x01;
        crc[1] = 0x06;
        crc[2] = 0x00;
        crc[3] = 0x00;
        crc[4] = 0x00;
        crc[5] = 0x01;
        quint16 reCrc;
        reCrc = CalcCRC16(crc,6);
        crc[6] = reCrc>>8;
        crc[7] = reCrc & 0xff;

        for(n=0;n<8;n++){
            data[n] = crc[n];
        }
        serialPort->write(data);
        ui->openMotorBut->setText("关闭电机");
    }
    else {
        //close
        crc[0] = 0x01;
        crc[1] = 0x06;
        crc[2] = 0x00;
        crc[3] = 0x00;
        crc[4] = 0x00;
        crc[5] = 0x01;
        quint16 reCrc;
        reCrc = CalcCRC16(crc,6);
        crc[6] = reCrc>>8;
        crc[7] = reCrc & 0xff;
        ui->openMotorBut->setText("启动电机");
    }
}

4、组装设置电机目标速度,输入框在设计时规定,只能输入整数,在获取目标速度时,电机的最高转速为3000转,所以如果设置值高于3000,也只设置3000转。具体函数如下:

void MainWindow::on_setSpeedBut_clicked()
{
    QByteArray data;
    data.resize(8);
    quint8 crc[8];
    quint8 n;
    quint16 speed_val;
    ui->textBrowser->insertPlainText("set speed!n");
        //speed set 01 06 00 02 05 DC 2A C3
    speed_val = ui->editSetSpeed->text().toInt();
    if (speed_val>3000)
    {
        speed_val = 3000;
    }
    crc[0] = 0x01;
    crc[1] = 0x06;
    crc[2] = 0x00;
    crc[3] = 0x02;

    crc[4] = speed_val>>8;
    crc[5] = speed_val & 0xff;
    quint16 reCrc;
    reCrc = CalcCRC16(crc,6);
    crc[6] = reCrc>>8;
    crc[7] = reCrc & 0xff;

    for(n=0;n<8;n++){
        data[n] = crc[n];
    }
    serialPort->write(data);
    ui->textBrowser->setText("set speed val");

}

5、获取实时的电机速度。获取电机实时速度,设置了一个定时器,每一秒向电机发送读取电机的指令:01 03 00 10 00 01 85 cf。串口接收数据时,判断前3位是否为收到的速度的指令,如果是就更新LCDNUMBER。具体指令如下:

void MainWindow::read_speed()
{
    QByteArray data;
    quint8 n;
    quint8 crc[8] = {0x01, 0x03, 0x00, 0x10, 0x00, 0x01, 0x85, 0xcf};
    for(n=0;n<8;n++){
        data[n] = crc[n];
    }
    serialPort->write(data);
}
void MainWindow::serialPortReadyRead()
 {
     /* 接收缓冲区中读取数据 */
    quint16 speed;
     QByteArray buf = serialPort->readAll();
     if(buf[0] == 0x01 && buf[1] == 0x03 && buf[2] == 0x02)
     {
         speed = buf[3]<<8 | buf[4];
         speed = speed/10;
         ui->lcdNumber->display(QString::number(speed));
     }
     ui->textBrowser->insertPlainText(QString(buf.toHex()));
 }

这里还有另外一个技巧,就是要设置一个标志,只能是串口打开成功,才能启用定时器。
6、组装好电机、控制器后,开发板后,成功的实现了对电机的实时控制与监控。
【总结】经过了差不多两个多月的学习试用,虽然写出了多篇帖子,学习到了不少东西,但是对这块开发板的了解还是只在皮毛。如果有时间,还会继续了解这块优秀的开发板,争取写出更好的作品。
附工程源码

*附件:myserial.zip

控制
电机视频,详见作者原帖子内容

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分