文章目录

前言

一、cubemx配置

二、代码

1.datou.h文件

2.datou.c文件

3. 主函数编写以及函数调用

总结

前言

本文继续简述使用stm32对张大头步进电机进行速度控制和角度控制。 张大头与stm32的硬件连接请看这个

要注意哈!usart模式要先通过张大头的小屏幕进行设置的哈!!要配置好波特率和地址。这些在张大头提供的pdf说明文档里面都有写!

一、cubemx配置

基础配置不说了,由于我们需要用stm32的usart,所以打开一个usart,波特率要和电机设置的匹配,我使用的是115200 然后生成代码即可。

二、代码

首先要知道,控制转速和控制旋转的角度发送的字节长度不同。所以本文中默认了电机的功能,只能在角度控制和速度控制中选择一个。

1.datou.h文件

先看.h文件,文件中有两个结构体,一个是速度的,一个是角度控制的,角度控制里面有一个专门记录当前位置的值,这样方便进行角度控制。 还有一个枚举,这个枚举是来控制角度模式下的电机转动方向的,用1个0 来表示,那个不动的2 是电机角度模式下到达指定位置的速度的高字节,由于一般情况下到达指定位置的速度是设定好的,所以在角度控制模式下我没有写相应的修改函数。extern StepperMotorControl moto1;这些声明的变量都是.c文件中的,当需要几个电机的时候就创建几个这样的变量。

#ifndef __DATOU_H

#define __DATOU_H

#include "main.h"

typedef struct

{

uint8_t controlBytes[6];

uint8_t lastControlBytes[6];

} StepperMotorControl;

typedef struct

{

uint8_t controlBytes[9];

uint8_t lastControlBytes[9];

float now_angle;

} StepperMotorControl_location;

typedef enum

{

forward=0x12, //正

reverse=0x02 //反

}Command;

extern StepperMotorControl moto1;

extern StepperMotorControl moto2;

extern StepperMotorControl moto3;

extern StepperMotorControl moto4;

void StepperMotorControl_init(StepperMotorControl *control, uint8_t address);

void set_speed(StepperMotorControl *control, uint8_t direction, uint16_t speed);

void set_acceleration(StepperMotorControl *control, uint16_t acceleration);

extern StepperMotorControl_location moto_9;//下

extern StepperMotorControl_location moto_8;//上

void StepperMotorControl_init_location(StepperMotorControl_location *control, uint8_t address) ;

void set_angle_control_location(StepperMotorControl_location *control, float target_angle_num);

2.datou.c文件

有了对.h文件的大体了解,现在我们来说一下.c文件 其中要注意的是在速度模式下只有3个可以调用的函数,角度模式下有2个可以调用的函数

速度模式下 初始化

void StepperMotorControl_init(StepperMotorControl *control, uint8_t address);

设置速度

void set_speed(StepperMotorControl *control, uint8_t direction, uint16_t speed);

设置加速度

void set_acceleration(StepperMotorControl *control, uint16_t acceleration);

角度模式下 初始化

void StepperMotorControl_init_location(StepperMotorControl_location *control, uint8_t address) ;

设置角度

void set_angle_control_location(StepperMotorControl_location *control, float target_angle_num);

文件中有些static 的函数,这些函数是用来进行一些调用和判断以及发送的,外部使用的时候不需要调用这些函数。

#include "datou.h"

#include

#include

#include

#include

StepperMotorControl moto1;//一号轮

StepperMotorControl moto2;//二号轮

StepperMotorControl moto3;//三号轮

StepperMotorControl moto4;//四号轮

/******************************************************

Function: void StepperMotorControl_init(StepperMotorControl *control, uint8_t address)

Description: 指定电机初始化函数(这个函数是用来指定电机的速度的)

Calls: NONE

Input: StepperMotorControl *control这个变量是结构体变量,这个结构体里面有2个成员

分别对应了当前发送的数据,上次发送的数据

address 是电机设定的地址

******************************************************/

void StepperMotorControl_init(StepperMotorControl *control, uint8_t address)

{

uint8_t defaultBytes[6] = {0x00, 0xF6, 0x10, 0x00, 0xaf, 0x6B};

memcpy(control->controlBytes, defaultBytes, 6);

memcpy(control->lastControlBytes, defaultBytes, 6);

control->controlBytes[0] = address;

}

static uint8_t hasChanged(StepperMotorControl *control)

{

for (uint8_t i = 0; i < 6; i++) {

if (control->controlBytes[i] != control->lastControlBytes[i])

{

return 1;

}

}

return 0;

}

static void updateLastControlBytes(StepperMotorControl *control)

{

for (uint8_t i = 0; i < 6; i++) {

control->lastControlBytes[i] = control->controlBytes[i];

}

}

static void sendCommand(StepperMotorControl *control)

{

if (hasChanged(control)) {

HAL_UART_Transmit(&huart3, control->controlBytes, 6, 100);

updateLastControlBytes(control);

}

}

/******************************************************

Function: void set_speed(StepperMotorControl *control, uint8_t direction, uint16_t speed)

Description: 设置电机的转速

Calls: static void sendCommand(StepperMotorControl *control)

Input: StepperMotorControl *control这个变量是结构体变量,这个结构体里面有2个成员

分别对应了当前发送的数据,上次发送的数据

direction 是电机的方向

speed 是电机的速度

******************************************************/

void set_speed(StepperMotorControl *control, uint8_t direction, uint16_t speed)

{

if (direction) {

control->controlBytes[2] = (0x10) | ((speed >> 8) & 0x0F); // 逆时针方向

} else {

control->controlBytes[2] = (0x00) | ((speed >> 8) & 0x0F); // 顺时针方向

}

control->controlBytes[3] = speed & 0xFF;

sendCommand(control);

}

/******************************************************

Function: void set_acceleration(StepperMotorControl *control, uint16_t acceleration)

Description: 设置电机的加转速

Calls: static void sendCommand(StepperMotorControl *control)

Input: StepperMotorControl *control这个变量是结构体变量,这个结构体里面有2个成员

分别对应了当前发送的数据,上次发送的数据

acceleration 是电机的加速度

******************************************************/

void set_acceleration(StepperMotorControl *control, uint16_t acceleration)

{

control->controlBytes[4] = acceleration;

sendCommand(control);

}

StepperMotorControl_location moto_9;//下

StepperMotorControl_location moto_8;//上

/******************************************************

Function: void StepperMotorControl_init_location(StepperMotorControl_location *control, uint8_t address)

Description: 指定电机初始化函数(这个函数是用来指定电机的位置的)

Calls: NONE

Input: StepperMotorControl_location *control这个变量是结构体变量,这个结构体里面有3个成员

分别对应了当前发送的数据,上次发送的数据,以及当前的位置值

address 是电机设定的地址

******************************************************/

void StepperMotorControl_init_location(StepperMotorControl_location *control, uint8_t address)

{

uint8_t defaultBytes[9] = {0x00, 0xFD, 0x12, 0x00, 0xaf,0x00,0x00,0x00,0x6B};

memcpy(control->controlBytes, defaultBytes, 9);

memcpy(control->lastControlBytes, defaultBytes, 9);

control->controlBytes[0] = address;

}

static uint8_t hasChanged_location(StepperMotorControl_location *control)

{

for (uint8_t i = 0; i < 9; i++) {

if (control->controlBytes[i] != control->lastControlBytes[i])

{

return 1;

}

}

return 0;

}

static void updateLastControlBytes_location(StepperMotorControl_location *control)

{

for (uint8_t i = 0; i < 9; i++) {

control->lastControlBytes[i] = control->controlBytes[i];

}

}

static void sendCommand_location(StepperMotorControl_location *control)

{

if (hasChanged_location(control)) {

HAL_UART_Transmit(&huart3, control->controlBytes, 9, 100);

updateLastControlBytes_location(control);

}

}

static void set_location(StepperMotorControl_location *control, Command com, int pulse_num)

{

control->controlBytes[2] =com;

control->controlBytes[6] = pulse_num>>8;/* 脉冲数中字节 */

control->controlBytes[7] = pulse_num-((pulse_num>>8)<<8); /* 脉冲数低字节 */

sendCommand_location(control);

}

/******************************************************

Function: void set_angle_control_location(StepperMotorControl_location *control, float target_angle_num)

Description: 控制指定电机的角度

Calls: static void set_location(StepperMotorControl_location *control, Command com, int pulse_num)

Input: StepperMotorControl_location *control这个变量是结构体变量,这个结构体里面有3个成员

分别对应了当前发送的数据,上次发送的数据,以及当前的位置值(由于需要通过用角度的差值来计算脉冲数,所以需要记录当前的位置)

target_angle_num 是目标角度

******************************************************/

#define a_circle_pulse 3200.0//这是一圈需要的脉冲数

void set_angle_control_location(StepperMotorControl_location *control, float target_angle_num)

{

double error_angle=target_angle_num-(control->now_angle);

int need_pulse=(int)(error_angle/360.0*a_circle_pulse);

if(error_angle!=0)

{

if(need_pulse<0)

{

set_location(control,reverse, -need_pulse);//注意此处的reverse可能需要改成forward,这个要根据你的物理结构而定

}

else

{

set_location(control,forward, need_pulse);//注意此处的forward可能需要改成reverse,这个要根据你的物理结构而定

}

control->now_angle=target_angle_num;

}

}

3. 主函数编写以及函数调用

在主函数中文章来源:https://www.uudwc.com/A/PdYeg/

/*底盘电机初始化*/

StepperMotorControl_init(&moto1,0x01);

StepperMotorControl_init(&moto2,0x02);

StepperMotorControl_init(&moto3,0x03);

StepperMotorControl_init(&moto4,0x04);

HAL_Delay(100);

/*云台电机初始化*/

StepperMotorControl_init_location(&moto_9,0x09);//下云台是9

StepperMotorControl_init_location(&moto_8,0x08);

HAL_Delay(100);

set_angle_control_location(&moto_8,-900);//电机转-900度

HAL_Delay(2000);

set_speed(&moto1,1,200) ;//电机正转且速度为200

总结

代码的可读性可能不算高,emm,望大佬指正。谢谢!文章来源地址https://www.uudwc.com/A/PdYeg/