stm32与伺服驱动器进行can通信

2019-09-30来源: 互联网关键字:stm32  伺服驱动器  can通信

实验室师兄之前用stm32之间进行can通信,其中一个作为主机,另外作为从机,从机负责电机运转,并取出电机的速度,然后通过can通信发送给主机,然后主机通过串口与上位机进行通信。这一部分操作可以参照以下链接:https://www.ncnynl.com/archives/201703/1414.html


现在我们选择用伺服驱动器与一个stm32进行can通信,从而实现对电机的控制,目前我们实现的是对电机的速度输入,启动电机,(并进行速度反馈,进行OLED输出,从而进行电机的PID调节)。

首先我们选择了以下图示伺服驱动器,驱动器这块选择淘宝搜索可进行can通信的编码器应该可以找到类似产品

在这里插入图片描述

然后按照手册,我们将电机的编码器信号线CN2,与电机相连,同时将电机三根动力线与电机相连,然后将RS232/CAN端口连出,由于我们首先测试的是商家给的PC端软件与伺服驱动器进行RS232通信,所以这里我们通过RS232与PC端相连,给伺服驱动器供电。效果图如下:

在这里插入图片描述

然后我们通过上位机软件给电机写入速度参数,加速度参数等,可以启动电机并有电流,位置,速度的实时反馈,初始如图:

在这里插入图片描述

上面进行了电机的初步测试,通过电机空载反馈回来的电流,我们初步判断电机是否工作正常,这里我们刚开始就出现电流在空载且速度较小的情况下,出现了电流输出过大的情况,于是在相关技术人员的帮助下随与商家联系更换了电机。

在这里插入图片描述

接下来就进入can通信的正题,can通信这一块我们最好通过实验板跑一下例程,然后结合程序去分析一下can通信的具体实现原理,及其各个寄存器的作用是什么,卡门一下stm32的技术文档(这里面时一些关于can通信的技术文档链接:https://pan.baidu.com/s/1LJJOMAxTTGgzYFfVnVGx5Q

提取码:agzo )。


想深入了解can通信,这里我推荐以下链接:

https://blog。csdn。net/qq_36355662/article/details/80607453

https://pan。baidu。com/s/1iy5z9g03Z4ZYn5gJYoN5WA?errno=0&errmsg=Auth Login Sucess&&bduss=&ssnerror=0&traceid=#list/path=%2F

(这是洋桃电子的资料,里面老师讲的很好很细,有助于对can通信理解)


首先在完成对can通信的理解后,我们会发现can通信的连线非常简单,只需要把can_h,can_l与其他can_h,can_l对应连接即可,其中两端需要串入120欧电阻,其作用是匹配总线阻抗,提高数据通信的抗干扰性及可靠行。(这里在设备较少时可以不接,但最好接上,消除干扰,本身stm32板内部已经串入120欧电阻,而且驱动器本身也有拨动按键来配置120欧电阻)

下一步我们需要按照手册编写can通信协议,通过stm32发送指令给伺服驱动器,从而实现电机的控制。这里特别提醒一下,这里需要用到can分析仪来分析到底哪里出了问题,这里我们走了弯路,问了技术人员后才发现这里离不开can分析仪对指令进行分析,can分析仪网上200元左右可以买到,如下:

在这里插入图片描述

接下来结合程序和手册分析一下到底如何编写指令,下面来自手册

在这里插入图片描述
在这里插入图片描述

通过这一块我们可以发现想要点对点的给伺服驱动器进行写数据操作的指令,这里伺服驱动器的ID号和组号可以通过之前的PC软件通过串口RS232写入。下一步就是需要用那些寄存器,并怎么给寄存器赋数据,这里从bite0-bite8的顺序我们可以发现指令写入的顺序。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过 这一部分寄存器,我们实现给伺服驱动器发送速度模式,并设定速度,最后启动电机的指令。然后通过自动报告的方式可以获取到反馈回来的速度,电流,位置。

下面是在stm32上的部分程序:


//can通信发送指令

//motor_init。c的写入数据代码

void Motor_Init(void)

{

CommandData[0]=Group_Motors; 

CommandData[1]=FCW_One2One; 

CommandData[2]=Register_SpeedSet; //速度设定寄存器

CommandData[3]=0x02; 

CommandData[4]=0xFE;

CommandData[5]=Register_Moter; //启动电机

CommandData[6]=0x00; 

CommandData[7]=0x00;

CAN_SendMsg(ID_MASTER, CommandData);

   CommandData[0]=Group_Motors; 

CommandData[1]=FCW_One2One; 

CommandData[2]=Resister_ReportTime; //自动报告时间设置成1s

CommandData[3]=0x07; 

CommandData[4]=0xd0;

CommandData[5]=Resister_AutoReportMode; //位置反馈 ,电流,速度

CommandData[6]=0x00; 

CommandData[7]=0x00;

  CAN_SendMsg(ID_LeftMotor, CommandData);

}



float Get_SpeedActual(uint32_t ID, float actual_speed)

{

int speed = 0;

actual_speed = 0;

CommandData[0]=Group_Motors; 

CommandData[1]=FCR_One2One; 

CommandData[2]=Resister_RSpeed; //读取的输出转速

CommandData[3]=0x00; 

CommandData[4]=0x00;

CommandData[5]=0xFF; //设置为无效寄存器

CommandData[6]=0x00; 

CommandData[7]=0x00;

Clear_canBuffer();

  CAN_SendMsg(ID, CommandData);


OLED_ShowString(0, 2,"Lspeed:",16);

while(Check_canRX()) ;

if((RxMessage.StdId) == 0x05 && RxMessage.Data[2]==Resister_RSpeed ) //设置为无效寄存器)//是否收到八位字节,且为输出转速寄存器

{

//将得到的数组合并成原始数

speed = RxMessage.Data[3] << 8 | RxMessage.Data[4];

// speed = RxMessage.Data[6] << 8 | RxMessage.Data[7];

//*actual_speed = RPM2Speed(speed/3000.0 * 8192.0);

actual_speed = RPM2Speed(speed/8192.0 * 3000.0); //实际电机转速转换成m/s

// OLED_ShowNumber(54, 2, actual_speed);

OLED_ShowNumber(12, 4, actual_speed);


//OLED_ShowString(12, 3,"stm32_master",16);

return 1;

}

return 0;

}


在motor.h文件下,我们对寄存器进行了宏定义例如:


#ifndef __MOTOR_H

#define __MOTOR_H


//FunctionCodeWrite,点对点的写数据操作功能码

#define FCW_One2One  0x1A  //发送指令,指令码,写数据,但不保存数据

#define FCW_One2One_Ri 0x1B //接收正确后返回指令

#define FCW_One2One_E  0x1C //接收错误后返回指令


//FunctionCodeRead,点对点的读数据操作功能码

#define FCR_One2One 0x2A // 指令的功能码,表示读数据,从机接收到指令后,把地址相应的数据内容上传

#define FCR_One2One_Ri 0x2B //接收正确后返回指令

#define FCR_One2One_E 0x2C //接收错误后返回指令


//FunctionCodeWrite,一对多的写数据操作功能码,主机发送数据指令,接收正确后,从机返回相应数据指令

#define FCW_One2Many  0x8A  //发送指令,写数据,但不保存数据

#define FCW_One2Many_Ri 0x8B //接收正确后返回指令

#define FCW_One2Many_E  0x8C //接收错误后返回指令


//FunctionCodeRead,一对多的读数据操作功能码

#define FCR_One2Many 0x9A //发送指令

#define FCR_One2Many_E 0x9C //接收错误后返回指令


//相关寄存器地址

#define Register_Moter 0x00  //电机寄存器   功能:写入数据不同,电机的启动和停止

#define Register_Mode 0x02  //电机输入模式选择,功能:写入数据不同,模式不同

#define Resister_SiteMode 0x51 //位置模式寄存器

#define Register_SpeedSet 0x06  //PC模式-速度给定

#define Resister_GroupNum 0x0b //设置从机CAN组号

#define Resister_IDNum 0x0d //设置从机CAN-ID号

#define Resister_ReportTime 0x0c //设置从机CAN报告时间

#define Resister_AutoReportMode 0x2e //设置自动报告内容选择



//10代表0到3000RPM 所用时间是 100ms

#define Resister_AccTimeInSpeed 0x0A //速度模式下,加减速时间设定,

#define Resister_AccTimeInSite 0x09 //位置模式下,加减速时间设定

//设定的数字量 8192 对应实际转速 3000RPM

#define Resister_SpeedLimit 0x1D //位置模式下,速度限幅值


//读参数地址列表

#define Resister_RLocation  0x55 //定位是否完成

#define Resister_RCircuit   0xE2//输出电流

#define Resister_RSpeed 0xE4//输出转速

#define Resister_ROdomH 0xE8//位置反馈高16位

#define Resister_ROdomL 0xE9//位置反馈低16位

#define Resister_RError 0xE3


//电机的组号,以及ID号

#define Group_Motors 0x00

#define ID_MASTER          0x00     //定义主机ID

#define ID_LeftMotor 0x05      //定义左伺服ID

#define ID_RightMotor 0x06      //定义右伺服ID


#define PI 3.1415926

#define Diameter 25 //轮子直径

#define PlusePerRound  2000 //脉冲数每转


#include "sys。h" 

#include "usart。h"

#include "delay.h"

#include "led.h" 

#include "oled.h"

#include "string。h"

#include "can.h"


//下面的速度单位是RPM,表示转每分钟(round per minute) 

void Motor_Init(void);

void Set_SpeedLimit(uint32_t ID, float limit_speed);

void Set_SpeedTarget(uint32_t ID, float target_speed);

//int Get_SpeedActual(uint32_t ID, float* actual_speed);

float Get_SpeedActual(uint32_t ID, float actual_speed);

int Get_Odometry(uint32_t ID, float* odom);

int Speed2RPM(float speed);

float RPM2Speed(int rpm);


#endif

写好指令后,首先用can分析仪给电机驱动器发消息,控制电机旋转,这样可以派出伺服驱动器是否有问题

如下

在这里插入图片描述

波特率的设置:1M,can通道用的2

在这里插入图片描述

首先看到接受到的数据是来自于伺服驱动器的心跳返回,

然后发送指令,发送正确后可以返回指令,可以看到can通讯成功了

在这里插入图片描述

其他指令是伺服驱动器的“心跳”,里面会包含我们自动报告的位置,速度等


然后我们用stm32与伺服驱动器进行通信

写入上述程序可以运行程序:

can分析仪:

在这里插入图片描述

然后发送指令,停止电机运转

在这里插入图片描述

can分析仪:

在这里插入图片描述

发现我们可以控制电机的运转和停止,并通过”心跳“可以取出返回的速度,这里目前只取出了一个速度并用OLED显示,希望显示实时速度,进行PID调试,后续还需要补充。

关键字:stm32  伺服驱动器  can通信 编辑:什么鱼 引用地址:http://news.2689mr.com/mcu/ic476230.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:小用stm32f4-CAN控制器(使用库函数)
下一篇:STM32 CAN 通讯发送不能连续,不能接收

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32F10X ADC原理详解(STM32F103ZET6)
STM32ADC的工作原理模/数转换器STM32F10x  ADC特点12位逐次逼近型的模拟数字转换器。最多带3个ADC控制器最多支持18个通道,可最多测量16个外部和2个内部信号源。支持单次和连续转换模式转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。通道0到通道n的自动扫描模式自动校准采样间隔可以按通道编程规则通道和注入通道均有外部触发选项转换结果支持左对齐或右对齐方式存储在16位数据寄存器ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到。)ADC供电要求:2.4V-3.6VADC输入范围:VREF- ≤  VIN 
发表于 2020-07-25
<font color='red'>STM32</font>F10X ADC原理详解(<font color='red'>STM32</font>F103ZET6)
STM32控制步进电机程序
、IN3:PC0、IN4:PC13、//步进电机初始化函数void Motor_Init(void){        GPIO_InitTypeDef GPIO_InitStructure;                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启时钟                GPIO_InitStructure.GPIO
发表于 2020-07-25
<font color='red'>STM32</font>控制步进电机程序
基于IAR环境下STM32F103单片机读取BME280程序
自己编写的基于IAR环境下STM32F103单片机读取BME280程序,没有太多的寄存器操作,简单易懂,可以直接调用,上电后只要对IO口初始化,调用函数Bme_ReadDigValue()读取校准寄存器参数并保存,再调用函数Bme_Init()初始化之后就可以用函数Bme_ReadStatus()读取传感器状态判断是否读取数据了,也可不判断传感器状态直接读取数据,读取数据直接调用函数ReadBme280()。单片机源程序:void ReadBme280(){        u32 value_ad;        double var1; 
发表于 2020-07-25
STM32步进伺服电机梯形加速源程序 单轴简易运动控制器
步进电机梯形加速程序单片机源程序如下:/*基于STM32的单轴简易运动控制器/脉冲发生器*//*脉冲+方向控制步进伺服电机*//*优化记录:增加急停GPIOC.0、正向极限GPIOC.1、负向极限GPIOC.2等输入IO接点中断修改TIMx_PSC一个寄存器的值,而不是修改TIMx_ARR预加载寄存器+TIMx_CCRx比较值寄存器两个值,缩短中断处理时间定位指令DRVI/DRVA中,目标频率设定过高、而实际输出脉冲数过少时,则不必加速到目标频率即进入减速区*//*DRVI(A);相对定位,输出A(A取绝对值)个脉冲A不能为0若A为正数,则方向为正、GPIOB.0为高电平若A为负数,则方向为负、GPIOB.0为低电平DRVA
发表于 2020-07-25
STM32实现ADS1256进行数据电压采集程序
通过cubeMX配置STM32RCT6的IO口与ads1256ADC模块的连接IO口工作模式SPI,还有接受中断接受状态引脚,最终ADC采集数据经过卡尔曼滤波器滤波输出单片机源程序如下:#include "ads1256.h"int32_t adcVaule = 0x00;float voltage = 0x00;float filterVoltage = 0.0;float filterVoltage2 = 0.0;void delayXus(uint16_t us) {    uint16_t diff = 0xffff - 5 - us;    //设置定时器的计数
发表于 2020-07-25
基于WiFi的网络授时时钟(带实时天气更新)STM32程序设计
本方案采用的是MCU+AT指令的形式开发,MCU是大家比较熟悉的意法半导体公司STM32F103C8T6,WiFi模块使用的是安信可ESP-12F,本方案是一个Demo设计,比较简单,仅实现了功能,算是一个抛砖引玉吧!先上视频演示:https://v.youku.com/v_show/id_XN ... m=a2hzp.8244740.0.0WiFi模块资料链接:wiki点ai-thinker点com/esp8266STM32F103C8芯片资料链接:https://www.stmicroelectronics.c ... 103c8.html#overview硬件部分,由时钟电路+WiFi模块+MCU最小系统+OLED
发表于 2020-07-25
基于WiFi的网络授时时钟(带实时天气更新)<font color='red'>STM32</font>程序设计
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 2689mr.com, Inc. All rights reserved
怎么找送彩金的网站 真钱棋牌注册送彩金 彩票大赢家 白菜送彩金38网站大全 彩票大赢家 娱乐平台充值送彩金 qq等级送彩金线上娱乐 网上百家乐送彩金 易迅彩票送彩金 送彩金棋牌平台大全