前言
本文繼續(xù)簡(jiǎn)述使用stm32對(duì)張大頭步進(jìn)電機(jī)進(jìn)行速度控制和角度控制。
張大頭與stm32的硬件連接請(qǐng)看這個(gè)
要注意哈!usart模式要先通過張大頭的小屏幕進(jìn)行設(shè)置的哈??!要配置好波特率和地址。這些在張大頭提供的pdf說明文檔里面都有寫!
一、cubemx配置
基礎(chǔ)配置不說了,由于我們需要用stm32的usart,所以打開一個(gè)usart,波特率要和電機(jī)設(shè)置的匹配,我使用的是115200
然后生成代碼即可。
二、代碼
首先要知道,控制轉(zhuǎn)速和控制旋轉(zhuǎn)的角度發(fā)送的字節(jié)長(zhǎng)度不同。所以本文中默認(rèn)了電機(jī)的功能,只能在角度控制和速度控制中選擇一個(gè)。
1.datou.h文件
先看.h文件,文件中有兩個(gè)結(jié)構(gòu)體,一個(gè)是速度的,一個(gè)是角度控制的,角度控制里面有一個(gè)專門記錄當(dāng)前位置的值,這樣方便進(jìn)行角度控制。
還有一個(gè)枚舉,這個(gè)枚舉是來控制角度模式下的電機(jī)轉(zhuǎn)動(dòng)方向的,用1個(gè)0 來表示,那個(gè)不動(dòng)的2 是電機(jī)角度模式下到達(dá)指定位置的速度的高字節(jié),由于一般情況下到達(dá)指定位置的速度是設(shè)定好的,所以在角度控制模式下我沒有寫相應(yīng)的修改函數(shù)。extern StepperMotorControl moto1;
這些聲明的變量都是.c文件中的,當(dāng)需要幾個(gè)電機(jī)的時(shí)候就創(chuàng)建幾個(gè)這樣的變量。
#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文件
有了對(duì).h文件的大體了解,現(xiàn)在我們來說一下.c文件
其中要注意的是在速度模式下只有3個(gè)可以調(diào)用的函數(shù),角度模式下有2個(gè)可以調(diào)用的函數(shù)
- 速度模式下
初始化
void StepperMotorControl_init(StepperMotorControl *control, uint8_t address);
設(shè)置速度
void set_speed(StepperMotorControl *control, uint8_t direction, uint16_t speed);
設(shè)置加速度
void set_acceleration(StepperMotorControl *control, uint16_t acceleration);
- 角度模式下
初始化
void StepperMotorControl_init_location(StepperMotorControl_location *control, uint8_t address) ;
設(shè)置角度
void set_angle_control_location(StepperMotorControl_location *control, float target_angle_num);
文件中有些static
的函數(shù),這些函數(shù)是用來進(jìn)行一些調(diào)用和判斷以及發(fā)送的,外部使用的時(shí)候不需要調(diào)用這些函數(shù)。
#include "datou.h"
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <usart.h>
StepperMotorControl moto1;//一號(hào)輪
StepperMotorControl moto2;//二號(hào)輪
StepperMotorControl moto3;//三號(hào)輪
StepperMotorControl moto4;//四號(hào)輪
/******************************************************
Function: void StepperMotorControl_init(StepperMotorControl *control, uint8_t address)
Description: 指定電機(jī)初始化函數(shù)(這個(gè)函數(shù)是用來指定電機(jī)的速度的)
Calls: NONE
Input: StepperMotorControl *control這個(gè)變量是結(jié)構(gòu)體變量,這個(gè)結(jié)構(gòu)體里面有2個(gè)成員
分別對(duì)應(yīng)了當(dāng)前發(fā)送的數(shù)據(jù),上次發(fā)送的數(shù)據(jù)
address 是電機(jī)設(shè)定的地址
******************************************************/
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: 設(shè)置電機(jī)的轉(zhuǎn)速
Calls: static void sendCommand(StepperMotorControl *control)
Input: StepperMotorControl *control這個(gè)變量是結(jié)構(gòu)體變量,這個(gè)結(jié)構(gòu)體里面有2個(gè)成員
分別對(duì)應(yīng)了當(dāng)前發(fā)送的數(shù)據(jù),上次發(fā)送的數(shù)據(jù)
direction 是電機(jī)的方向
speed 是電機(jī)的速度
******************************************************/
void set_speed(StepperMotorControl *control, uint8_t direction, uint16_t speed)
{
if (direction) {
control->controlBytes[2] = (0x10) | ((speed >> 8) & 0x0F); // 逆時(shí)針方向
} else {
control->controlBytes[2] = (0x00) | ((speed >> 8) & 0x0F); // 順時(shí)針方向
}
control->controlBytes[3] = speed & 0xFF;
sendCommand(control);
}
/******************************************************
Function: void set_acceleration(StepperMotorControl *control, uint16_t acceleration)
Description: 設(shè)置電機(jī)的加轉(zhuǎn)速
Calls: static void sendCommand(StepperMotorControl *control)
Input: StepperMotorControl *control這個(gè)變量是結(jié)構(gòu)體變量,這個(gè)結(jié)構(gòu)體里面有2個(gè)成員
分別對(duì)應(yīng)了當(dāng)前發(fā)送的數(shù)據(jù),上次發(fā)送的數(shù)據(jù)
acceleration 是電機(jī)的加速度
******************************************************/
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: 指定電機(jī)初始化函數(shù)(這個(gè)函數(shù)是用來指定電機(jī)的位置的)
Calls: NONE
Input: StepperMotorControl_location *control這個(gè)變量是結(jié)構(gòu)體變量,這個(gè)結(jié)構(gòu)體里面有3個(gè)成員
分別對(duì)應(yīng)了當(dāng)前發(fā)送的數(shù)據(jù),上次發(fā)送的數(shù)據(jù),以及當(dāng)前的位置值
address 是電機(jī)設(shè)定的地址
******************************************************/
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;/* 脈沖數(shù)中字節(jié) */
control->controlBytes[7] = pulse_num-((pulse_num>>8)<<8); /* 脈沖數(shù)低字節(jié) */
sendCommand_location(control);
}
/******************************************************
Function: void set_angle_control_location(StepperMotorControl_location *control, float target_angle_num)
Description: 控制指定電機(jī)的角度
Calls: static void set_location(StepperMotorControl_location *control, Command com, int pulse_num)
Input: StepperMotorControl_location *control這個(gè)變量是結(jié)構(gòu)體變量,這個(gè)結(jié)構(gòu)體里面有3個(gè)成員
分別對(duì)應(yīng)了當(dāng)前發(fā)送的數(shù)據(jù),上次發(fā)送的數(shù)據(jù),以及當(dāng)前的位置值(由于需要通過用角度的差值來計(jì)算脈沖數(shù),所以需要記錄當(dāng)前的位置)
target_angle_num 是目標(biāo)角度
******************************************************/
#define a_circle_pulse 3200.0//這是一圈需要的脈沖數(shù)
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,這個(gè)要根據(jù)你的物理結(jié)構(gòu)而定
}
else
{
set_location(control,forward, need_pulse);//注意此處的forward可能需要改成reverse,這個(gè)要根據(jù)你的物理結(jié)構(gòu)而定
}
control->now_angle=target_angle_num;
}
}
3. 主函數(shù)編寫以及函數(shù)調(diào)用
在主函數(shù)中文章來源:http://www.zghlxwxcb.cn/news/detail-626896.html
/*底盤電機(jī)初始化*/
StepperMotorControl_init(&moto1,0x01);
StepperMotorControl_init(&moto2,0x02);
StepperMotorControl_init(&moto3,0x03);
StepperMotorControl_init(&moto4,0x04);
HAL_Delay(100);
/*云臺(tái)電機(jī)初始化*/
StepperMotorControl_init_location(&moto_9,0x09);//下云臺(tái)是9
StepperMotorControl_init_location(&moto_8,0x08);
HAL_Delay(100);
set_angle_control_location(&moto_8,-900);//電機(jī)轉(zhuǎn)-900度
HAL_Delay(2000);
set_speed(&moto1,1,200) ;//電機(jī)正轉(zhuǎn)且速度為200
總結(jié)
代碼的可讀性可能不算高,emm,望大佬指正。謝謝!文章來源地址http://www.zghlxwxcb.cn/news/detail-626896.html
到了這里,關(guān)于STM32步進(jìn)閉環(huán)控制、速度控制(張大頭Emm_V4.2驅(qū)動(dòng)器)速度控制 角度控制 位置控制的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!