系统相关
首页 > 系统相关> > 基于CAN通讯以及RS485的电机控制(ROS/Ubuntu)

基于CAN通讯以及RS485的电机控制(ROS/Ubuntu)

作者:互联网

一.电机

这个SHABI电机是日本的多摩川伺服电机,型号也是很老的型号,中国的代理都没有见过。
开始说使用CAN通讯控制电机,让我弄了一个多月,结果这玩意儿用中国的CAN卡根本就不行。

二. CAN通讯

开始的CAN通讯其实也学到了一些东西,CAN通讯主要就是对电机的ID号发送信息,最重要的三个部分就是:
1.电机ID号码,这个通常是可以根据电机自带软件更改的,控制的时候注意以下就好
2.波特率,这个也很简单,说明书就有
3.发送的消息,一般情况下就是八个字节,都是十六进制

调试经验:一般情况下先在WINDOWS下面用CAN卡自带的调试软件调试一下,一般把消息发送出去后会收到绿的消息回来,电机驱动可以后,就能够使用UBUNTU了。由于这个本比电机不会CAN,这里就不说了。

三.RS485

RS485跟CAN通讯相差不大,也是上面的三个部分,调这个电机的时候,我把波特率也更改了,虽然这个电机傻逼,不过日本人做的还是很OK的。
这个也很简单,在UBUNTU 里面先打开串口,

//定义串口
string port="/dev/ttyUSB1";
//打开串口的函数
bool openSerial(const char* port)
{
    com=modbus_new_rtu(port,19200,'E',8,1);
    if(com==nullptr)
    {
        cout<<"wrong modbus parameter."<<endl;
        return false;
    }
    timeval time_out;
    time_out.tv_sec=0;
    time_out.tv_usec=1000*100;
   // modbus_set_response_timeout(com,time_out.tv_sec,time_out.tv_usec);
    modbus_rtu_set_serial_mode(com,MODBUS_RTU_RS485);
    if(modbus_connect(com)==-1)
    {
        cout<<"Cannot connect modbus at port:"<<port<<endl;
        return false;
    } else
        cout<<"Connected modbus at port:"<<port<<endl;
    return true;
}

这些也都比较简单,然后初始化电机,为了防止电机打开后异常,开始就设置成“清除电机警报”。然后就是电机伺服打开-----位置控制模式。

RS485在UBUNTU中使用的是modbus这个库,因为我的傻逼电脑在CMAKlist里面好像找不到这个库,就直接把库的一些头文件放进了INCLUDE里面了,反正也不影响使用。
`

modbus_t* com;//com用于电机速度控制反馈
///************电机伺服打开*************//
void SetModbus(int motor1)
{
    const uint16_t src[]={0x3};    
    const uint16_t clear[]={0x8};    
    modbus_set_slave(com,motor1); 
    modbus_write_registers(com,startstop,1,clear);   //清除报警
    modbus_write_registers(com,startstop,1,src);      //电机伺服打开
}

///************电机控制模式*************//
void controlset(int motor1)
{
    const uint16_t src[]={0x01};
    modbus_set_slave(com,motor1); 
    modbus_write_registers(com,controlmod,1,src);  //设置控制模式---位置控制 
    const uint16_t acc[]={0x64};
    const uint16_t v[]={0x190};
    modbus_write_registers(com,seta,1,acc);       //设置加速度
    modbus_write_registers(com,setv,1,v);         //设置定位目标速度
    modbus_write_registers(com,setaa,1,acc);      //设置减速度
    cout<<"motor INIT!!!!!!!"<<endl;
}
//****************************************************************************************
///************电机位置控制*************//
void movemotor(int motor1,int speed)
{
    if(speed>0)
    {
    //左转
    uint16_t src[]={0X00};
    uint16_t srcc[]= {(uint16_t)speed};
    cout<<*srcc<<endl;
    modbus_set_slave(com,motor1); 
    modbus_write_registers(com,posezero,1,src);       // 发出位置指令
    modbus_write_registers(com,posezero1,1,srcc);      // 发出位置指令
    }
    else
    {
    //右转&&向后??????
    //如果speed = -100,那么speed = 0XFFFF-speed=65535-100=65435,不知道具体输入到电机是什么情况
    //可以向将一个10进制数输入到srcc里面看看情况。
    speed =-speed;
    speed = 65535-speed;
     uint16_t srrc[]={0XFFFF};
    uint16_t ssrcc[]= {(uint16_t)speed};
    modbus_set_slave(com,motor1); 
    modbus_write_registers(com,posezero,1,srrc);
    modbus_write_registers(com,posezero1,1,ssrcc);
    }
   
}

这个里面就是用modbus库的一些函数给电机发送指令,“motor1”里面应该是电机的ID号码,一般为十六进制,modbus_set_slave的意思是设置从站,modbus_write_registers是发送功能消息指令,带有S的应该功能码10,这个可以对多个电机同时发送,不太会用这个函数,所以写了很多次数,看起来有些傻逼。

另外就是这个电机也比较傻逼,位置控制的时候,不能控制他的加速度和减速度,加速太大的话,直接就自保护了。后面设置成每发送一次电机位置就设置一次速度,就可以了。

标签:registers,电机,speed,RS485,modbus,uint16,Ubuntu,ROS,com
来源: https://blog.csdn.net/qq_41707788/article/details/114192116