cyy的垃圾堆


  • 首页
  • 归档
  • 标签
  • 关于CYY
  • 友链

© 2025 CYY

Theme Typography by Makito

Proudly published with Hexo

YZ-AIM电机驱动记录

发布于 2024-06-01

​ 仅仅是驱动电机,实现加减速,具体实现方式数据传输见于电机说明书,对于其数据传输存在疑惑,可以串口助手先进行尝试,可以利用上位机,然后配合串口监控精灵,观察他到底是传的是什么。

​ 这个作为代码存档,这是一大坨屎山,但网上没有相关代码可以抄,对于串口传输规范并没怎么研究,没有像其他地方的范例一样规范,CV进入代码绝对会有报错,补充相关变量即可,实现驱动功能的芯片为stm32f103zet6

STM32驱动实现

代码的实现均在速度模式下实现

串口初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void UART5_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE); //使能GPIOC/GPIOD时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); //使能UART5时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PC12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//传输速度50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//PD2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIO
//UART 初始化设置
USART_DeInit(UART5); //复位串口5
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(UART5, &USART_InitStructure); //初始化串口5
//Uart5 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;//串口5中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(UART5, ENABLE); //使能串口5
}

电机运动控制,其传输指令结合为:地址+写功能(一个读取一个写入)+功能码+转速(若功能码为速度)+CRC校验码,更多功能详见说明书

CRC16校验,采用的是查表法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* CRC 高位字节值表 */ static unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC 低位字节值表*/ static char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 };
//CRC查表
unsigned short CRC16(u32 *puchMsg, u8 usDataLen) /* 要进行 CRC 校验的消息 */ /* 消息中字节数 */
{u16 uchCRCHi = 0xFF ; /* 高 CRC 字节初始化 */
u16 uchCRCLo = 0xFF ; /* 低 CRC 字节初始化 */
unsigned uIndex ; /* CRC 循环中的索引 */
while (usDataLen--) /* 传输消息缓冲区 */
{uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算 CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}

​ 前进,后退和停止基本上都是这么处理的:若是前进,将其速度分成两个两位数字,就像0XFFFF分成,0XFF,0XFF,因为数值位有4位,便于CRC函数校验数组,然后依次将数存入数组,然后扔给CRC校验函数即可,获得CRC的值,然后依次发给电机即可,反转就传入负数,取反加一即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void run(u16 Left,u16 Right)// 
{
u8 temp1_L;u8 temp2_L;
u8 temp1_R;u8 temp2_R;
u16 crc_L;
u16 crc_R;//低位前置 CRC
Left=range(Left,0,800);
Right=range(Right,0,800);
// 实现后退取消注释以下代码即可
// Left=~Left+0x01;
// Right=~Right+0x01;
temp1_L = (Left&0XFF00)>>8;
temp2_L = (Left&0X00FF);
temp1_R = (Right&0XFF00)>>8;
temp2_R = (Right&0X00FF);
u32 tempL[6] = {0x01, 0x06, 0x00, 0x02, temp1_L, temp2_L};
u32 tempR[6] = {0x01, 0x06, 0x00, 0x02, temp1_R, temp2_R};

crc_R=CRC16(tempR,6);
crc_L=CRC16(tempL,6);
//地址
USART_SendData(UART5,0x01);
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
//写功能
USART_SendData(UART5,0x06);
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
//功能
USART_SendData(UART5,0x00);
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
USART_SendData(UART5,0x02);
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
//转速
USART_SendData(UART5,(Left&0XFF00)>>8);
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
USART_SendData(UART5,(Left&0X00FF));
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
//CRC校验码
USART_SendData(UART5,(crc_L&0XFF00)>>8);
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
USART_SendData(UART5,(crc_L&0X00FF));
while (USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
}

​ 有了底层实现,加减速与普通代码实现就类似,建议传输的间隔小一点,与普通直流电机相比,内部会闭环控制,当你给定一个速度时,电机会立马到达这个速度,导致电机加减速时一震一震的,还有个方法,修改其内部加速度。

YZ-AIM上位机

p1

​ 对于打开串口,软件不能自动识别已经连接了哪个串口,打开设备管理器或者一个个试下去,然后不能开太久,软件会自己崩掉。

电机连接RS485转USB连接电脑并且上电,打开串口,左下出现数值,先modbus使能电机,改为速度模式,将特殊参数改为3(速度模式对应的值)。根据实际情况,修改下电机内部的pid的值。完成一系列操作后,最后将参数保存,将其置2。

手册

上位机

分享到 

 上一篇: 飞特舵机使用 下一篇: f28335以及ccs环境 

© 2025 CYY

Theme Typography by Makito

Proudly published with Hexo